Merge pull request #1716 from halseth/witness-commitment-rpctest

rpctest: add witness commitment when calling CreateBlock
This commit is contained in:
Olaoluwa Osuntokun 2021-04-29 15:55:35 -07:00 committed by GitHub
commit ce697fe7e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 34 deletions

View file

@ -14,6 +14,7 @@ import (
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/mining"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
@ -181,6 +182,21 @@ func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx,
if inclusionTxs != nil {
blockTxns = append(blockTxns, inclusionTxs...)
}
// We must add the witness commitment to the coinbase if any
// transactions are segwit.
witnessIncluded := false
for i := 1; i < len(blockTxns); i++ {
if blockTxns[i].MsgTx().HasWitness() {
witnessIncluded = true
break
}
}
if witnessIncluded {
_ = mining.AddWitnessCommitment(coinbaseTx, blockTxns)
}
merkles := blockchain.BuildMerkleTreeStore(blockTxns, false)
var block wire.MsgBlock
block.Header = wire.BlockHeader{

View file

@ -803,40 +803,7 @@ mempoolLoop:
// OP_RETURN output within the coinbase transaction.
var witnessCommitment []byte
if witnessIncluded {
// The witness of the coinbase transaction MUST be exactly 32-bytes
// of all zeroes.
var witnessNonce [blockchain.CoinbaseWitnessDataLen]byte
coinbaseTx.MsgTx().TxIn[0].Witness = wire.TxWitness{witnessNonce[:]}
// Next, obtain the merkle root of a tree which consists of the
// wtxid of all transactions in the block. The coinbase
// transaction will have a special wtxid of all zeroes.
witnessMerkleTree := blockchain.BuildMerkleTreeStore(blockTxns,
true)
witnessMerkleRoot := witnessMerkleTree[len(witnessMerkleTree)-1]
// The preimage to the witness commitment is:
// witnessRoot || coinbaseWitness
var witnessPreimage [64]byte
copy(witnessPreimage[:32], witnessMerkleRoot[:])
copy(witnessPreimage[32:], witnessNonce[:])
// The witness commitment itself is the double-sha256 of the
// witness preimage generated above. With the commitment
// generated, the witness script for the output is: OP_RETURN
// OP_DATA_36 {0xaa21a9ed || witnessCommitment}. The leading
// prefix is referred to as the "witness magic bytes".
witnessCommitment = chainhash.DoubleHashB(witnessPreimage[:])
witnessScript := append(blockchain.WitnessMagicBytes, witnessCommitment...)
// Finally, create the OP_RETURN carrying witness commitment
// output as an additional output within the coinbase.
commitmentOutput := &wire.TxOut{
Value: 0,
PkScript: witnessScript,
}
coinbaseTx.MsgTx().TxOut = append(coinbaseTx.MsgTx().TxOut,
commitmentOutput)
witnessCommitment = AddWitnessCommitment(coinbaseTx, blockTxns)
}
// Calculate the required difficulty for the block. The timestamp
@ -895,6 +862,49 @@ mempoolLoop:
}, nil
}
// AddWitnessCommitment adds the witness commitment as an OP_RETURN outpout
// within the coinbase tx. The raw commitment is returned.
func AddWitnessCommitment(coinbaseTx *btcutil.Tx,
blockTxns []*btcutil.Tx) []byte {
// The witness of the coinbase transaction MUST be exactly 32-bytes
// of all zeroes.
var witnessNonce [blockchain.CoinbaseWitnessDataLen]byte
coinbaseTx.MsgTx().TxIn[0].Witness = wire.TxWitness{witnessNonce[:]}
// Next, obtain the merkle root of a tree which consists of the
// wtxid of all transactions in the block. The coinbase
// transaction will have a special wtxid of all zeroes.
witnessMerkleTree := blockchain.BuildMerkleTreeStore(blockTxns,
true)
witnessMerkleRoot := witnessMerkleTree[len(witnessMerkleTree)-1]
// The preimage to the witness commitment is:
// witnessRoot || coinbaseWitness
var witnessPreimage [64]byte
copy(witnessPreimage[:32], witnessMerkleRoot[:])
copy(witnessPreimage[32:], witnessNonce[:])
// The witness commitment itself is the double-sha256 of the
// witness preimage generated above. With the commitment
// generated, the witness script for the output is: OP_RETURN
// OP_DATA_36 {0xaa21a9ed || witnessCommitment}. The leading
// prefix is referred to as the "witness magic bytes".
witnessCommitment := chainhash.DoubleHashB(witnessPreimage[:])
witnessScript := append(blockchain.WitnessMagicBytes, witnessCommitment...)
// Finally, create the OP_RETURN carrying witness commitment
// output as an additional output within the coinbase.
commitmentOutput := &wire.TxOut{
Value: 0,
PkScript: witnessScript,
}
coinbaseTx.MsgTx().TxOut = append(coinbaseTx.MsgTx().TxOut,
commitmentOutput)
return witnessCommitment
}
// UpdateBlockTime updates the timestamp in the header of the passed block to
// the current time while taking into account the median time of the last
// several blocks to ensure the new time is after that time per the chain