P2pkh

比特幣的流動網路 - 無法使用 go-elements 廣播 PSET P2PKH 發行交易

  • October 9, 2020

在處理go-elements時,我一直在嘗試通過實現廣播不同類型 PSET 事務的函式來擴展pset_test.go 。不幸的是,我找不到很多關於這個主題的技術資訊。

我正在嘗試實施一個測試,該測試廣播從發行資產的 PSET 創建的交易,以及資產的 P2PKH 輸出、l-btc(用於更改)和費用。

我寫的程式碼返回的錯誤pset_test.go:324: Signature does not correspond to this input是不言自明的,但我不確定我在哪裡弄錯了。我將不勝感激一些幫助以及有關技術資源的指示,這些資源可以幫助我更好地理解這個主題。謝謝

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)
   }
}

該錯誤提示您沒有正確簽署交易。事實上,您正在生成一個簽名:

txHash := updater.Data.UnsignedTx.TxHash()
sig, err := privkey.Sign(txHash[:])

但是目前的交易雜湊不是你需要簽名的。相反,您應該使用HashForSignature舊輸入類型:

sigHash, err := updater.Data.UnsignedTx.HashForSignature(0, p2pkh.Script, txscript.SigHashAll)
if err != nil {
   t.Fatal(err)
}
sig, err := privkey.Sign(sigHash[:])

PS。請注意,目前 Elements 協議不允許您使用舊版 scriptpubkey 擁有的輸入,因此即使交易格式正確,它也不會被 mempool 接受並包含在區塊鏈中。

引用自:https://bitcoin.stackexchange.com/questions/99399