user110255: While working on go-elements I've been trying to expand on pset_test.go by implementing functions that broadcast different kinds of PSET transaction. Unfortunately I can't find many technical informations about this subject.
I'm trying to implement a test that Broadcasts a transaction created from a PSET that issues an asset, with P2PKH outputs for the asset, l-btc (for the change) and the fee.
The code I wrote is returning the error pset_test.go:324: Signature does not correspond to this input which is pretty self-explanatory but I'm not sure where I got it wrong. I would appreciate some help and also indication on technical resources that could help me understand this subject a bit better. Thank you
func TestBroadcastUnblindedIssuanceTxP2PKH(t *testing.T) {
    privkey, err := btcec.NewPrivateKey(btcec.S256())
    if err != nil {
        t.Fatal(err)
    }
    pubkey := privkey.PubKey()
    p2pkh := payment.FromPublicKey(pubkey, &network.Regtest, nil)
    address, _ := p2pkh.PubKeyHash()

    // Fund sender address.
    _, err = faucet(address)
    if err != nil {
        t.Fatal(err)
    }

    // Retrieve sender utxos.
    utxos, err := unspents(address)
    if err != nil {
        t.Fatal(err)
    }

    // The transaction will have 1 input and 3 outputs.
    txInputHash, _ := hex.DecodeString(utxos[0]["txid"].(string))
    txInputHash = bufferutil.ReverseBytes(txInputHash)
    txInputIndex := uint32(utxos[0]["vout"].(float64))
    txInput := transaction.NewTxInput(txInputHash, txInputIndex)

    lbtc, _ := hex.DecodeString(
        "5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225",
    )
    lbtc = append([]byte{0x01}, bufferutil.ReverseBytes(lbtc)...)

    changeScript := p2pkh.Script
    changeValue, _ := confidential.SatoshiToElementsValue(99999500)
    changeOutput := transaction.NewTxOutput(lbtc, changeValue[:], changeScript)

    feeScript := []byte{}
    feeValue, _ := confidential.SatoshiToElementsValue(500)
    feeOutput := transaction.NewTxOutput(lbtc, feeValue[:], feeScript)

    // Create a new pset.
    inputs := []*transaction.TxInput{txInput}
    outputs := []*transaction.TxOutput{changeOutput, feeOutput}
    p, err := New(inputs, outputs, 2, 0)
    if err != nil {
        t.Fatal(err)
    }

    updater, err := NewUpdater(p)
    if err != nil {
        t.Fatal(err)
    }

    arg := AddIssuanceArg{
        Precision: 0,
        Contract: &transaction.IssuanceContract{
            Name:      "Test",
            Ticker:    "TST",
            Version:   0,
            Precision: 0,
            Entity: transaction.IssuanceEntity{
                Domain: "test.io",
            },
        },
        AssetAmount:  1000,
        TokenAmount:  1,
        AssetAddress: address,
        TokenAddress: address,
        TokenFlag:    0,
        Net:          network.Regtest,
    }
    err = updater.AddIssuance(arg)
    if err != nil {
        t.Fatal(err)
    }

    err = updater.AddInSighashType(txscript.SigHashAll, 0)
    if err != nil {
        t.Fatal(err)
    }

    err = updater.AddInNonWitnessUtxo(updater.Data.UnsignedTx, 0)
    if err != nil {
        t.Fatal(err)
    }

    txHash := updater.Data.UnsignedTx.TxHash()
    sig, err := privkey.Sign(txHash[:])
    if err != nil {
        t.Fatal(err)
    }

    sigWithHashType := append(sig.Serialize(), byte(txscript.SigHashAll))

    // Update the pset adding the input signature script and the pubkey.
    _, err = updater.Sign(0, sigWithHashType, pubkey.SerializeCompressed(), nil, nil)
    if err != nil {
        t.Fatal(err)
    }

    valid, err := updater.Data.ValidateAllSignatures()
    if err != nil {
        t.Fatal(err)
    }
    if !valid {
        t.Fatal(errors.New("invalid signatures"))
    }

    // Finalize the partial transaction.
    p = updater.Data
    err = FinalizeAll(p)
    if err != nil {
        t.Fatal(err)
    }

    // Extract the final signed transaction from the Pset wrapper.
    finalTx, err := Extract(p)
    if err != nil {
        t.Fatal(err)
    }

    // Serialize the transaction and try to broadcast.
    txHex, err := finalTx.ToHex()
    if err != nil {
        t.Fatal(err)
    }
    _, err = broadcast(txHex)
    if err != nil {
        t.Fatal(err)
    }
}


user110263: The error hints that you're not signing the transaction correctly.
In fact, you're generating a signature with:
txHash := updater.Data.UnsignedTx.TxHash()
sig, err := privkey.Sign(txHash[:])

But the current transaction hash is not what you need to sign. Instead, you should use HashForSignature for legacy input types:
sigHash, err := updater.Data.UnsignedTx.HashForSignature(0, p2pkh.Script, txscript.SigHashAll)
if err != nil {
    t.Fatal(err)
}
sig, err := privkey.Sign(sigHash[:])

PS. Note that at the moment the Elements protocol does not allow you to use an input owned by a legacy scriptpubkey, therefore even if the transaction is well-formed it won't get accepted in mempool and included in the blockchain.

110255: <p>While working on <a href="https://github.com/vulpemventures/go-elements/" rel="nofollow noreferrer">go-elements</a> I've been trying to expand on <a href="https://github.com/vulpemventures/go-elements/blob/master/pset/pset_test.go" rel="nofollow noreferrer">pset_test.go</a> by implementing functions that broadcast different kinds of PSET transaction. Unfortunately I can't find many technical informations about this subject.
<br>I'm trying to implement a test that Broadcasts a transaction created from a PSET that issues an asset, with P2PKH outputs for the asset, l-btc (for the change) and the fee.
<br>The code I wrote is returning the error <code>pset_test.go:324: Signature does not correspond to this input</code> which is pretty self-explanatory but I'm not sure where I got it wrong. I would appreciate some help and also indication on technical resources that could help me understand this subject a bit better. Thank you</p>
<pre><code>func TestBroadcastUnblindedIssuanceTxP2PKH(t *testing.T) {
    privkey, err := btcec.NewPrivateKey(btcec.S256())
    if err != nil {
        t.Fatal(err)
    }
    pubkey := privkey.PubKey()
    p2pkh := payment.FromPublicKey(pubkey, &amp;network.Regtest, nil)
    address, _ := p2pkh.PubKeyHash()

    // Fund sender address.
    _, err = faucet(address)
    if err != nil {
        t.Fatal(err)
    }

    // Retrieve sender utxos.
    utxos, err := unspents(address)
    if err != nil {
        t.Fatal(err)
    }

    // The transaction will have 1 input and 3 outputs.
    txInputHash, _ := hex.DecodeString(utxos[0][&quot;txid&quot;].(string))
    txInputHash = bufferutil.ReverseBytes(txInputHash)
    txInputIndex := uint32(utxos[0][&quot;vout&quot;].(float64))
    txInput := transaction.NewTxInput(txInputHash, txInputIndex)

    lbtc, _ := hex.DecodeString(
        &quot;5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225&quot;,
    )
    lbtc = append([]byte{0x01}, bufferutil.ReverseBytes(lbtc)...)

    changeScript := p2pkh.Script
    changeValue, _ := confidential.SatoshiToElementsValue(99999500)
    changeOutput := transaction.NewTxOutput(lbtc, changeValue[:], changeScript)

    feeScript := []byte{}
    feeValue, _ := confidential.SatoshiToElementsValue(500)
    feeOutput := transaction.NewTxOutput(lbtc, feeValue[:], feeScript)

    // Create a new pset.
    inputs := []*transaction.TxInput{txInput}
    outputs := []*transaction.TxOutput{changeOutput, feeOutput}
    p, err := New(inputs, outputs, 2, 0)
    if err != nil {
        t.Fatal(err)
    }

    updater, err := NewUpdater(p)
    if err != nil {
        t.Fatal(err)
    }

    arg := AddIssuanceArg{
        Precision: 0,
        Contract: &amp;transaction.IssuanceContract{
            Name:      &quot;Test&quot;,
            Ticker:    &quot;TST&quot;,
            Version:   0,
            Precision: 0,
            Entity: transaction.IssuanceEntity{
                Domain: &quot;test.io&quot;,
            },
        },
        AssetAmount:  1000,
        TokenAmount:  1,
        AssetAddress: address,
        TokenAddress: address,
        TokenFlag:    0,
        Net:          network.Regtest,
    }
    err = updater.AddIssuance(arg)
    if err != nil {
        t.Fatal(err)
    }

    err = updater.AddInSighashType(txscript.SigHashAll, 0)
    if err != nil {
        t.Fatal(err)
    }

    err = updater.AddInNonWitnessUtxo(updater.Data.UnsignedTx, 0)
    if err != nil {
        t.Fatal(err)
    }

    txHash := updater.Data.UnsignedTx.TxHash()
    sig, err := privkey.Sign(txHash[:])
    if err != nil {
        t.Fatal(err)
    }

    sigWithHashType := append(sig.Serialize(), byte(txscript.SigHashAll))

    // Update the pset adding the input signature script and the pubkey.
    _, err = updater.Sign(0, sigWithHashType, pubkey.SerializeCompressed(), nil, nil)
    if err != nil {
        t.Fatal(err)
    }

    valid, err := updater.Data.ValidateAllSignatures()
    if err != nil {
        t.Fatal(err)
    }
    if !valid {
        t.Fatal(errors.New(&quot;invalid signatures&quot;))
    }

    // Finalize the partial transaction.
    p = updater.Data
    err = FinalizeAll(p)
    if err != nil {
        t.Fatal(err)
    }

    // Extract the final signed transaction from the Pset wrapper.
    finalTx, err := Extract(p)
    if err != nil {
        t.Fatal(err)
    }

    // Serialize the transaction and try to broadcast.
    txHex, err := finalTx.ToHex()
    if err != nil {
        t.Fatal(err)
    }
    _, err = broadcast(txHex)
    if err != nil {
        t.Fatal(err)
    }
}
</code></pre>
 110263: <p>The error hints that you're not signing the transaction correctly.
In fact, you're generating a signature with:</p>
<pre><code>txHash := updater.Data.UnsignedTx.TxHash()
sig, err := privkey.Sign(txHash[:])
</code></pre>
<p>But the current transaction hash is not what you need to sign. Instead, you should use <code>HashForSignature</code> for legacy input types:</p>
<pre><code>sigHash, err := updater.Data.UnsignedTx.HashForSignature(0, p2pkh.Script, txscript.SigHashAll)
if err != nil {
    t.Fatal(err)
}
sig, err := privkey.Sign(sigHash[:])
</code></pre>
<p>PS. Note that at the moment the Elements protocol <a href="https://github.com/ElementsProject/elements/blob/18fadbafcceff70a7d328ca739e09004dc51e37a/src/confidential_validation.cpp#L282-L284" rel="nofollow noreferrer">does not allow</a> you to use an input owned by a legacy scriptpubkey, therefore even if the transaction is well-formed it won't get accepted in mempool and included in the blockchain.</p>
