MarkTangCd (OP)
Newbie
Offline
Activity: 3
Merit: 0
|
|
February 07, 2024, 02:35:46 AM |
|
I want to create a PSBT transaction. But get the error when to call sendrawtransaction method. I used Golang package: github.com/btcsuite/btcd This is my code:
PSBT inputs inputs = append(inputs, &TxInput{ TxId: "02b074590fcac25129ff8f6a31375d9231e86f600f82c232d5d61fe2df5a8a96", VOut: uint32(0), Sequence: uint32(0), Amount: 2774, Address: "tb1pnq36mn7l8d3kvgejvnc5q63ls9umhaqscl623eqzge8mstj332xscmeu8h", PublicKey: "02a33b6f980567e1b3bb5a4df3b086871694d0e03b70ee462a36686acda6b94b9d", PrivateKey: "privatekey", })
inputs = append(inputs, &TxInput{ TxId: "2e9f9af0bbed192bb860a172b2ab219c48da87996c7e80bf8470033b669f354e", VOut: uint32(len(inputs)), Sequence: uint32(len(inputs)), Amount: 1990, Address: config.Receiver, PublicKey: "02e8e9d1d88eb86fb56b26e267bda715ba81ad91850448d8c2d5d8e64937ac8ef9", PrivateKey: "privatekey", }) PSBT outputs func GetTxOutByUTXOs(amount int64) []*TxOutput { var outputs []*TxOutput outputs = append(outputs, &TxOutput{ Address: config.Owner, Amount: amount - 500, }) outputs = append(outputs, &TxOutput{ Address: config.Receiver, Amount: 500 + 1990 - 300, })
return outputs } Then I passed them to the function. func GenerateSignedOwnerTx(ins []*TxInput, outs []*TxOutput, network *chaincfg.Params) (string, error) { var inputs []*wire.OutPoint var nSequences []uint32 prevOuts := make(map[wire.OutPoint]*wire.TxOut) for _, in := range ins { var prevOut *wire.OutPoint txHash, err := chainhash.NewHashFromStr(in.TxId) if err != nil { panic(err) } prevOut = wire.NewOutPoint(txHash, in.VOut) inputs = append(inputs, prevOut)
prevPkScript, err := AddrToPkScript(in.Address, network) if err != nil { panic(err) } witnessUtxo := wire.NewTxOut(in.Amount, prevPkScript) prevOuts[*prevOut] = witnessUtxo
nSequences = append(nSequences, wire.MaxTxInSequenceNum) }
var outputs []*wire.TxOut for _, out := range outs { pkScript, err := AddrToPkScript(out.Address, network) if err != nil { panic(err) } outputs = append(outputs, wire.NewTxOut(out.Amount, pkScript)) }
bp, err := psbt.New(inputs, outputs, int32(2), uint32(0), nSequences) if err != nil { panic(err) }
updater, err := psbt.NewUpdater(bp) if err != nil { panic(err) }
prevOutputFetcher := txscript.NewMultiPrevOutFetcher(prevOuts)
for i, in := range ins {
if err = signInput(updater, i, in, prevOutputFetcher, txscript.SigHashAll, network); err != nil { panic(err) }
if err = psbt.Finalize(bp, i); err != nil { panic(err) } }
fmt.Println("signed bp base64 encode:") fmt.Println(bp.B64Encode()) if err = psbt.MaybeFinalizeAll(bp); err != nil { return "", err }
buyerSignedTx, err := psbt.Extract(bp) if err != nil { return "", err }
var buf bytes.Buffer if err := buyerSignedTx.Serialize(&buf); err != nil { return "", err }
return hex.EncodeToString(buf.Bytes()), nil}
This is sign function. func signInput(updater *psbt.Updater, i int, in *TxInput, prevOutFetcher *txscript.MultiPrevOutFetcher, hashType txscript.SigHashType, network *chaincfg.Params) error { wif, err := btcutil.DecodeWIF(i[Suspicious link removed]ivateKey) if err != nil && i != 1 { panic(err) } privKey := wif.PrivKey
prevPkScript, err := AddrToPkScript(in.Address, network) if err != nil { panic(err) } if txscript.IsPayToPubKeyHash(prevPkScript) { prevTx := wire.NewMsgTx(2) txBytes, err := hex.DecodeString(in.NonWitnessUtxo) if err != nil { panic(err) } if err = prevTx.Deserialize(bytes.NewReader(txBytes)); err != nil { panic(err) } if err = updater.AddInNonWitnessUtxo(prevTx, i); err != nil { panic(err) } } else { witnessUtxo := wire.NewTxOut(in.Amount, prevPkScript) if err = updater.AddInWitnessUtxo(witnessUtxo, i); err != nil { panic(err) } }
if err = updater.AddInSighashType(hashType, i); err != nil { panic(err) }
if txscript.IsPayToTaproot(prevPkScript) { internalPubKey := schnorr.SerializePubKey(privKey.PubKey()) updater.Upsbt.Inputs[i].TaprootInternalKey = internalPubKey
sigHashes := txscript.NewTxSigHashes(updater.Upsbt.UnsignedTx, prevOutFetcher) if hashType == txscript.SigHashAll { hashType = txscript.SigHashDefault } witness, err := txscript.TaprootWitnessSignature(updater.Upsbt.UnsignedTx, sigHashes, i, in.Amount, prevPkScript, hashType, privKey) if err != nil { panic(err) }
updater.Upsbt.Inputs[i].TaprootKeySpendSig = witness[0] } else if txscript.IsPayToPubKeyHash(prevPkScript) { signature, err := txscript.RawTxInSignature(updater.Upsbt.UnsignedTx, i, prevPkScript, hashType, privKey) if err != nil { panic(err) }
if _, err := updater.Sign(i, signature, privKey.PubKey().SerializeCompressed(), nil, nil); err != nil { panic(err) } } else { pubKeyBytes := privKey.PubKey().SerializeCompressed() sigHashes := txscript.NewTxSigHashes(updater.Upsbt.UnsignedTx, prevOutFetcher)
script, err := PayToPubKeyHashScript(btcutil.Hash160(pubKeyBytes)) if err != nil { panic(err) } signature, err := txscript.RawTxInWitnessSignature(updater.Upsbt.UnsignedTx, sigHashes, i, in.Amount, script, hashType, privKey) if err != nil { panic(err) }
if txscript.IsPayToScriptHash(prevPkScript) { redeemScript, err := PayToWitnessPubKeyHashScript(btcutil.Hash160(pubKeyBytes)) if err != nil { panic(err) } err = updater.AddInRedeemScript(redeemScript, i) if err != nil { panic(err) } }
if _, err := updater.Sign(i, signature, pubKeyBytes, nil, nil); err != nil { panic(err) } } return nil}
|