I am making an attempt to open a channel on regtest with LND v0.13.0-beta.rc3 utilizing their PSBT workflow to permit for distant signing.
I’ve performed the next steps:
- I create a regtest pockets utilizing the BIP39 mnemonic
bronze execute spirit sense rack this repeat entry crash practice elder goal lease acquire limb view gossip say finest desert uncover jaguar exhaust card
- I import the prolonged public key for my account into LND
seed, err := bip39.MnemonicToByteArray(pockets.Mnemonic, true)
if err != nil {
return err
}
// Generate a brand new grasp node utilizing the seed.
prvkey, err := hdkeychain.NewMaster(seed, &chaincfg.RegressionNetParams)
if err != nil {
return err
}
for i := 0; i < 3; i++ {
prvkey, err = prvkey.Derive(hdkeychain.HardenedKeyStart)
if err != nil {
return err
}
}
key, err := prvkey.Neuter()
if err != nil {
return err
}
importReq := &walletrpc.ImportAccountRequest{
Title: "check",
ExtendedPublicKey: key.String(),
MasterKeyFingerprint: writeUint32(prvkey.ParentFingerprint()),
AddressType: 1,
DryRun: false,
}
res, err := m.shopper.ImportAccount(ctx, importReq)
lnd@alice:/$ lncli pockets accounts listing
{
"accounts": [
{
"name": "default",
"address_type": "HYBRID_NESTED_WITNESS_PUBKEY_HASH",
"extended_public_key": "upub5Dbp2w1Q7VPuhHQhPtq6rJj7wy8bbEdjFyn1TuHg6MmoSTvR3biPji1nvMRAeoyskhBUBNGGFhzUBm5KQ51M24nKcoxQ7ioFuFeyuiWqk8p",
"master_key_fingerprint": null,
"derivation_path": "m/49'/0'/0'",
"external_key_count": 0,
"internal_key_count": 0,
"watch_only": false
},
{
"name": "default",
"address_type": "WITNESS_PUBKEY_HASH",
"extended_public_key": "vpub5YyjQMoehZ9g6gu4sQ1VdBTwwMfgfBsPzViqWjMACu1r1JcFkky2PRyYmrGNtgQZh2BY9ZprnRoUjpFm2cx9mPiJ9NhZZ7uCZgQ8x4UNay5",
"master_key_fingerprint": null,
"derivation_path": "m/84'/0'/0'",
"external_key_count": 1,
"internal_key_count": 3,
"watch_only": false
},
{
"name": "test",
"address_type": "WITNESS_PUBKEY_HASH",
"extended_public_key": "tpubDDMrn46y7HdxK2AHN1anVxj8gSiYLXtmZ4Jyn1Q9Va7AZt5XBdbQ8CUms5NRv6eXBGA8FsJTcEk6h3Wihb49BYMxMqM6k83FWYCpAFLN7Rh",
"master_key_fingerprint": null,
"derivation_path": "m/84'/0'/0'",
"external_key_count": 2,
"internal_key_count": 35,
"watch_only": true
}
]
}
- I name the LND gRPC endpoint Lighting.OpenChannel with a Psbt FundingShim and obtain the empty PSBT
- I name WalletKit.FundPsbt to fund the PSBT with the check account and get the next PSBT
cHNidP8BAH0CAAAAAf1dlbtrkfmWZasLXxXBEOZbqL5bNT7xONtdc2zTvSRdAAAAAAD/////AoAaBgAAAAAAIgAgLXNsa/AXkklm/LtR6cRgyY0R3TjzCv4OpA0zK7Rc0pNmqAoAAAAAABYAFJrmQkFPaRSt6hfN8U4KFByZXIw3AAAAAAABAN4BAAAAAAEBvvrMn8zVi8D0+0mKi3TGtP8OltDfymQNbfrF1PvEvMIBAAAAAP////8C4MgQAAAAAAAWABQKYpfN3bKI+eLmUec/pPAHC5aUB4Gc1QUAAAAAFgAUOk/UwylhTSOS9zMFLinyDOpn3m4CRzBEAiB11J75wXdm8VggN5MAD2FfG6oRVwAOge+V7XVC3cv34QIgE11HHRZuFZnqaTwSsgycVSHemWoC4GjgXQcO3+odgBcBIQNThPBjoshiGPI00vjOkMJ2pFgb6cvt4qOnOn2FQhDeRgAAAAABAR/gyBAAAAAAABYAFApil83dsoj54uZR5z+k8AcLlpQHAQMEAQAAACIGAzR2EGePj6pLqU6hqkgFrayXL+8s6cj42Q118v0X0CYcGAAAAABUAACAAAAAgAAAAIAAAAAAAAAAAAAAAA==
which bitcoin-cli decode
s to
{
"tx": {
"txid": "23cec773304f28bb78fdd88b4ad31e3b5f4331b83b7106831f1a4e182e3449a4",
"hash": "23cec773304f28bb78fdd88b4ad31e3b5f4331b83b7106831f1a4e182e3449a4",
"model": 2,
"measurement": 125,
"vsize": 125,
"weight": 500,
"locktime": 0,
"vin": [
{
"txid": "5d24bdd36c735ddb38f13e355bbea85be610c1155f0bab6596f9916bbb955dfd",
"vout": 0,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00400000,
"n": 0,
"scriptPubKey": {
"asm": "0 e9c4eaee376e5961d61e73fa5e855f224b31037bab32de63ec83ced969c4dcf5",
"hex": "0020e9c4eaee376e5961d61e73fa5e855f224b31037bab32de63ec83ced969c4dcf5",
"reqSigs": 1,
"type": "witness_v0_scripthash",
"addresses": [
"bc1qa8zw4m3hdevkr4s7w0a9ap2lyf9nzqmm4veduclvs08dj6wymn6sgq85mn"
]
}
},
{
"worth": 0.00698470,
"n": 1,
"scriptPubKey": {
"asm": "0 aafc3223cb003a5077badd7af66cab8dd0576976",
"hex": "0014aafc3223cb003a5077badd7af66cab8dd0576976",
"reqSigs": 1,
"sort": "witness_v0_keyhash",
"addresses": [
"bc1q4t7ryg7tqqa9qaa6m4a0vm9t3hg9w6tkk89wnz"
]
}
}
]
},
"unknown": {
},
"inputs": [
{
"witness_utxo": {
"amount": 0.01100000,
"scriptPubKey": {
"asm": "0 0a6297cdddb288f9e2e651e73fa4f0070b969407",
"hex": "00140a6297cdddb288f9e2e651e73fa4f0070b969407",
"type": "witness_v0_keyhash",
"address": "bc1qpf3f0nwak2y0nchx28nnlf8squ9ed9q88sfrrr"
}
},
"non_witness_utxo": {
"txid": "5d24bdd36c735ddb38f13e355bbea85be610c1155f0bab6596f9916bbb955dfd",
"hash": "4b84437691dbc3ed4c4e6cb1946ebefe7f26147d6d42f25aea73582f20049800",
"version": 1,
"size": 222,
"vsize": 141,
"weight": 561,
"locktime": 0,
"vin": [
{
"txid": "c2bcc4fbd4c5fa6d0d64cadfd0960effb4c6748b8a49fbf4c08bd5cc9fccfabe",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"txinwitness": [
"3044022075d49ef9c17766f158203793000f615f1baa1157000e81ef95ed7542ddcbf7e10220135d471d166e1599ea693c12b20c9c5521de996a02e068e05d070edfea1d801701",
"035384f063a2c86218f234d2f8ce90c276a4581be9cbede2a3a73a7d854210de46"
],
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.01100000,
"n": 0,
"scriptPubKey": {
"asm": "0 0a6297cdddb288f9e2e651e73fa4f0070b969407",
"hex": "00140a6297cdddb288f9e2e651e73fa4f0070b969407",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"bc1qpf3f0nwak2y0nchx28nnlf8squ9ed9q88sfrrr"
]
}
},
{
"worth": 0.97885313,
"n": 1,
"scriptPubKey": {
"asm": "0 3a4fd4c329614d2392f733052e29f20cea67de6e",
"hex": "00143a4fd4c329614d2392f733052e29f20cea67de6e",
"reqSigs": 1,
"sort": "witness_v0_keyhash",
"addresses": [
"bc1q8f8afsefv9xj8yhhxvzju20jpn4x0hnwgnx7ny"
]
}
}
]
},
"sighash": "ALL",
"bip32_derivs": [
{
"pubkey": "03347610678f8faa4ba94ea1aa4805adac972fef2ce9c8f8d90d75f2fd17d0261c",
"master_fingerprint": "00000000",
"path": "m/84'/0'/0'/0/0"
}
]
}
],
"outputs": [
{
},
{
}
],
"payment": 0.00001530
}
- I try to signal the transaction utilizing code tailored from this SO thread.
func (w *RemoteWallet) FinalizePsbt(psbtBytes []byte) ([]byte, error) {
reader := bytes.NewReader(psbtBytes)
packet, err := psbt.NewFromRawBytes(reader, false)
if err != nil {
return nil, err
}
// Load the prolonged personal key.
seed, err := bip39.MnemonicToByteArray(w.Mnemonic, true)
if err != nil {
return nil, err
}
// Generate a brand new grasp node utilizing the seed.
bip32Key, err := hdkeychain.NewMaster(seed, &chaincfg.RegressionNetParams)
if err != nil {
return nil, err
}
log.Printf("key1 %s", bip32Key.String())
for i := 0; i < 3; i++ {
bip32Key, err = bip32Key.Derive(hdkeychain.HardenedKeyStart)
if err != nil {
return nil, err
}
}
key, err := bip32Key.Neuter()
if err != nil {
return nil, err
}
log.Printf("depth %d", key.Depth())
log.Printf("key2 %s", key.String())
log.Println("FinalizePsbt Accomplished Loading")
for idx, enter := vary packet.Inputs {
// Derivation path must be learn from PSBT.
// Observe: We ignore checking the fingerprint, and so on.
path := enter.Bip32Derivation[0]
log.Printf("enter path: %v", path.Bip32Path)
inputKey := bip32Key
for _, d := vary path.Bip32Path {
inputKey, _ = inputKey.Derive(d)
}
pubkey, err := inputKey.Neuter()
if err != nil {
return nil, err
}
log.Printf("depth %d", pubkey.Depth())
log.Printf("enter key %s", pubkey.String())
pubKey, err := bip32Key.ECPubKey()
if err != nil {
return nil, err
}
privKey, err := bip32Key.ECPrivKey()
if err != nil {
return nil, err
}
log.Printf("SighashType: %v", enter.SighashType)
log.Printf("Witness script: %v", enter.WitnessScript)
sigHashes := txscript.NewTxSigHashes(packet.UnsignedTx)
sig, err := txscript.RawTxInWitnessSignature(packet.UnsignedTx, sigHashes, idx,
enter.WitnessUtxo.Worth, enter.WitnessUtxo.PkScript,
txscript.SigHashAll, privKey)
if err != nil {
return nil, err
}
log.Println("Signing enter")
// Use the Updater so as to add the signature to the enter.
u, err := psbt.NewUpdater(packet)
if err != nil {
return nil, err
}
success, err := u.Signal(idx, sig, pubKey.SerializeCompressed(), nil, enter.WitnessScript)
if err != nil {
return nil, err
}
if success != psbt.SignSuccesful {
return nil, fmt.Errorf("couldn't sucessfully signal psbt")
}
log.Println("Signed enter")
}
// Finalize PSBT.
err = psbt.Finalize(packet, 0)
if err != nil {
return nil, err
}
tx, err := psbt.Extract(packet)
if err != nil {
return nil, err
}
var buf bytes.Buffer
err = tx.Serialize(&buf)
return buf.Bytes(), err
}
This outputs
2021/06/28 14:36:35 key1 tprv8ZgxMBicQKsPeHPJRNuvXzDo2U86CLouVfExiLeiTrcffR9aDRC3zMLTPHohQhEFSQNvCAmVeX7SXGS5te7pfdLXjWHsaaLGL3gsktdGziG
2021/06/28 14:36:35 depth 3
2021/06/28 14:36:35 key2 tpubDDMrn46y7HdxK2AHN1anVxj8gSiYLXtmZ4Jyn1Q9Va7AZt5XBdbQ8CUms5NRv6eXBGA8FsJTcEk6h3Wihb49BYMxMqM6k83FWYCpAFLN7Rh
2021/06/28 14:36:35 FinalizePsbt Accomplished Loading
2021/06/28 14:36:35 enter path: [2147483732 2147483648 2147483648 0 0]
2021/06/28 14:36:35 depth 5
2021/06/28 14:36:35 enter key tpubDFuWC8gxvpmEMQMhsr5vhE1FviMyPKpPTi2dBBMJ9sBvacjeuFbnK6JWULL25e8mXRoTRjVAe1e9GqmiynAFUwKrqKnRVC46bz4ssBRHxmW
2021/06/28 14:36:35 SighashType: 1
2021/06/28 14:36:35 Witness script: []
2021/06/28 14:36:35 Signing enter
earlier than crashing with the error Signature doesn't correspond to this enter
.
That is my first time working with PSBTs, so I am unsure what I am doing. I have been enjoying round with numerous elements of the FinalizePsbt func, however with none good sources, it has been a guessing recreation.
If I missed any vital information, please let me know. Any assistance is appreciated!