rpctest: Add GenerateAndSubmitBlockWithCustomCoinbaseOutputs
This commit is contained in:
parent
9b9ef42f8a
commit
ec228f9ff9
3 changed files with 113 additions and 9 deletions
|
@ -88,7 +88,8 @@ func standardCoinbaseScript(nextBlockHeight int32, extraNonce uint64) ([]byte, e
|
||||||
// createCoinbaseTx returns a coinbase transaction paying an appropriate
|
// createCoinbaseTx returns a coinbase transaction paying an appropriate
|
||||||
// subsidy based on the passed block height to the provided address.
|
// subsidy based on the passed block height to the provided address.
|
||||||
func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32,
|
func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32,
|
||||||
addr btcutil.Address, net *chaincfg.Params) (*btcutil.Tx, error) {
|
addr btcutil.Address, mineTo []wire.TxOut,
|
||||||
|
net *chaincfg.Params) (*btcutil.Tx, error) {
|
||||||
|
|
||||||
// Create the script to pay to the provided payment address.
|
// Create the script to pay to the provided payment address.
|
||||||
pkScript, err := txscript.PayToAddrScript(addr)
|
pkScript, err := txscript.PayToAddrScript(addr)
|
||||||
|
@ -105,10 +106,16 @@ func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32,
|
||||||
SignatureScript: coinbaseScript,
|
SignatureScript: coinbaseScript,
|
||||||
Sequence: wire.MaxTxInSequenceNum,
|
Sequence: wire.MaxTxInSequenceNum,
|
||||||
})
|
})
|
||||||
|
if len(mineTo) == 0 {
|
||||||
tx.AddTxOut(&wire.TxOut{
|
tx.AddTxOut(&wire.TxOut{
|
||||||
Value: blockchain.CalcBlockSubsidy(nextBlockHeight, net),
|
Value: blockchain.CalcBlockSubsidy(nextBlockHeight, net),
|
||||||
PkScript: pkScript,
|
PkScript: pkScript,
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
for i := range mineTo {
|
||||||
|
tx.AddTxOut(&mineTo[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
return btcutil.NewTx(tx), nil
|
return btcutil.NewTx(tx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,8 +125,8 @@ func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32,
|
||||||
// second is used. Passing nil for the previous block results in a block that
|
// second is used. Passing nil for the previous block results in a block that
|
||||||
// builds off of the genesis block for the specified chain.
|
// builds off of the genesis block for the specified chain.
|
||||||
func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx,
|
func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx,
|
||||||
blockVersion int32, blockTime time.Time,
|
blockVersion int32, blockTime time.Time, miningAddr btcutil.Address,
|
||||||
miningAddr btcutil.Address, net *chaincfg.Params) (*btcutil.Block, error) {
|
mineTo []wire.TxOut, net *chaincfg.Params) (*btcutil.Block, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
prevHash *chainhash.Hash
|
prevHash *chainhash.Hash
|
||||||
|
@ -156,7 +163,7 @@ func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
coinbaseTx, err := createCoinbaseTx(coinbaseScript, blockHeight,
|
coinbaseTx, err := createCoinbaseTx(coinbaseScript, blockHeight,
|
||||||
miningAddr, net)
|
miningAddr, mineTo, net)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,6 +406,27 @@ func (h *Harness) P2PAddress() string {
|
||||||
// This function is safe for concurrent access.
|
// This function is safe for concurrent access.
|
||||||
func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32,
|
func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32,
|
||||||
blockTime time.Time) (*btcutil.Block, error) {
|
blockTime time.Time) (*btcutil.Block, error) {
|
||||||
|
return h.GenerateAndSubmitBlockWithCustomCoinbaseOutputs(txns,
|
||||||
|
blockVersion, blockTime, []wire.TxOut{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateAndSubmitBlockWithCustomCoinbaseOutputs creates a block whose
|
||||||
|
// contents include the passed coinbase outputs and transactions and submits
|
||||||
|
// it to the running simnet node. For generating blocks with only a coinbase tx,
|
||||||
|
// callers can simply pass nil instead of transactions to be mined.
|
||||||
|
// Additionally, a custom block version can be set by the caller. A blockVersion
|
||||||
|
// of -1 indicates that the current default block version should be used. An
|
||||||
|
// uninitialized time.Time should be used for the blockTime parameter if one
|
||||||
|
// doesn't wish to set a custom time. The mineTo list of outputs will be added
|
||||||
|
// to the coinbase; this is not checked for correctness until the block is
|
||||||
|
// submitted; thus, it is the caller's responsibility to ensure that the outputs
|
||||||
|
// are correct. If the list is empty, the coinbase reward goes to the wallet
|
||||||
|
// managed by the Harness.
|
||||||
|
//
|
||||||
|
// This function is safe for concurrent access.
|
||||||
|
func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs(
|
||||||
|
txns []*btcutil.Tx, blockVersion int32, blockTime time.Time,
|
||||||
|
mineTo []wire.TxOut) (*btcutil.Block, error) {
|
||||||
|
|
||||||
h.Lock()
|
h.Lock()
|
||||||
defer h.Unlock()
|
defer h.Unlock()
|
||||||
|
@ -427,7 +448,7 @@ func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32,
|
||||||
|
|
||||||
// Create a new block including the specified transactions
|
// Create a new block including the specified transactions
|
||||||
newBlock, err := CreateBlock(prevBlock, txns, blockVersion,
|
newBlock, err := CreateBlock(prevBlock, txns, blockVersion,
|
||||||
blockTime, h.wallet.coinbaseAddr, h.ActiveNet)
|
blockTime, h.wallet.coinbaseAddr, mineTo, h.ActiveNet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,6 +391,81 @@ func testGenerateAndSubmitBlock(r *Harness, t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testGenerateAndSubmitBlockWithCustomCoinbaseOutputs(r *Harness,
|
||||||
|
t *testing.T) {
|
||||||
|
// Generate a few test spend transactions.
|
||||||
|
addr, err := r.NewAddress()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate new address: %v", err)
|
||||||
|
}
|
||||||
|
pkScript, err := txscript.PayToAddrScript(addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create script: %v", err)
|
||||||
|
}
|
||||||
|
output := wire.NewTxOut(btcutil.SatoshiPerBitcoin, pkScript)
|
||||||
|
|
||||||
|
const numTxns = 5
|
||||||
|
txns := make([]*btcutil.Tx, 0, numTxns)
|
||||||
|
for i := 0; i < numTxns; i++ {
|
||||||
|
tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create tx: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
txns = append(txns, btcutil.NewTx(tx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now generate a block with the default block version, a zero'd out
|
||||||
|
// time, and a burn output.
|
||||||
|
block, err := r.GenerateAndSubmitBlockWithCustomCoinbaseOutputs(txns,
|
||||||
|
-1, time.Time{}, []wire.TxOut{{
|
||||||
|
Value: 0,
|
||||||
|
PkScript: []byte{},
|
||||||
|
}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate block: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that all created transactions were included, and that the
|
||||||
|
// block version was properly set to the default.
|
||||||
|
numBlocksTxns := len(block.Transactions())
|
||||||
|
if numBlocksTxns != numTxns+1 {
|
||||||
|
t.Fatalf("block did not include all transactions: "+
|
||||||
|
"expected %v, got %v", numTxns+1, numBlocksTxns)
|
||||||
|
}
|
||||||
|
blockVersion := block.MsgBlock().Header.Version
|
||||||
|
if blockVersion != BlockVersion {
|
||||||
|
t.Fatalf("block version is not default: expected %v, got %v",
|
||||||
|
BlockVersion, blockVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next generate a block with a "non-standard" block version along with
|
||||||
|
// time stamp a minute after the previous block's timestamp.
|
||||||
|
timestamp := block.MsgBlock().Header.Timestamp.Add(time.Minute)
|
||||||
|
targetBlockVersion := int32(1337)
|
||||||
|
block, err = r.GenerateAndSubmitBlockWithCustomCoinbaseOutputs(nil,
|
||||||
|
targetBlockVersion, timestamp, []wire.TxOut{{
|
||||||
|
Value: 0,
|
||||||
|
PkScript: []byte{},
|
||||||
|
}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate block: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally ensure that the desired block version and timestamp were set
|
||||||
|
// properly.
|
||||||
|
header := block.MsgBlock().Header
|
||||||
|
blockVersion = header.Version
|
||||||
|
if blockVersion != targetBlockVersion {
|
||||||
|
t.Fatalf("block version mismatch: expected %v, got %v",
|
||||||
|
targetBlockVersion, blockVersion)
|
||||||
|
}
|
||||||
|
if !timestamp.Equal(header.Timestamp) {
|
||||||
|
t.Fatalf("header time stamp mismatch: expected %v, got %v",
|
||||||
|
timestamp, header.Timestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testMemWalletReorg(r *Harness, t *testing.T) {
|
func testMemWalletReorg(r *Harness, t *testing.T) {
|
||||||
// Create a fresh harness, we'll be using the main harness to force a
|
// Create a fresh harness, we'll be using the main harness to force a
|
||||||
// re-org on this local harness.
|
// re-org on this local harness.
|
||||||
|
@ -478,6 +553,7 @@ var harnessTestCases = []HarnessTestCase{
|
||||||
testJoinBlocks,
|
testJoinBlocks,
|
||||||
testJoinMempools, // Depends on results of testJoinBlocks
|
testJoinMempools, // Depends on results of testJoinBlocks
|
||||||
testGenerateAndSubmitBlock,
|
testGenerateAndSubmitBlock,
|
||||||
|
testGenerateAndSubmitBlockWithCustomCoinbaseOutputs,
|
||||||
testMemWalletReorg,
|
testMemWalletReorg,
|
||||||
testMemWalletLockedOutputs,
|
testMemWalletLockedOutputs,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue