Bitcoin

Bitcoin Core – PSBT transaction RPC error: bad-txns-inputs-missingorspent

I want to create a PSBT transaction. But when I call sendrawtransaction method I get an error.

I used the Golang package: github.com/btcsuite/btcd

This is my code.
Enter image description here
PSBT input

Enter image description here
PSBT output

Then I passed it 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 the 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(in.PrivateKey)
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

Related Articles

Back to top button