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
|
||||
// subsidy based on the passed block height to the provided address.
|
||||
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.
|
||||
pkScript, err := txscript.PayToAddrScript(addr)
|
||||
|
@ -105,10 +106,16 @@ func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32,
|
|||
SignatureScript: coinbaseScript,
|
||||
Sequence: wire.MaxTxInSequenceNum,
|
||||
})
|
||||
tx.AddTxOut(&wire.TxOut{
|
||||
Value: blockchain.CalcBlockSubsidy(nextBlockHeight, net),
|
||||
PkScript: pkScript,
|
||||
})
|
||||
if len(mineTo) == 0 {
|
||||
tx.AddTxOut(&wire.TxOut{
|
||||
Value: blockchain.CalcBlockSubsidy(nextBlockHeight, net),
|
||||
PkScript: pkScript,
|
||||
})
|
||||
} else {
|
||||
for i := range mineTo {
|
||||
tx.AddTxOut(&mineTo[i])
|
||||
}
|
||||
}
|
||||
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
|
||||
// builds off of the genesis block for the specified chain.
|
||||
func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx,
|
||||
blockVersion int32, blockTime time.Time,
|
||||
miningAddr btcutil.Address, net *chaincfg.Params) (*btcutil.Block, error) {
|
||||
blockVersion int32, blockTime time.Time, miningAddr btcutil.Address,
|
||||
mineTo []wire.TxOut, net *chaincfg.Params) (*btcutil.Block, error) {
|
||||
|
||||
var (
|
||||
prevHash *chainhash.Hash
|
||||
|
@ -156,7 +163,7 @@ func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx,
|
|||
return nil, err
|
||||
}
|
||||
coinbaseTx, err := createCoinbaseTx(coinbaseScript, blockHeight,
|
||||
miningAddr, net)
|
||||
miningAddr, mineTo, net)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -406,6 +406,27 @@ func (h *Harness) P2PAddress() string {
|
|||
// This function is safe for concurrent access.
|
||||
func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32,
|
||||
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()
|
||||
defer h.Unlock()
|
||||
|
@ -427,7 +448,7 @@ func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32,
|
|||
|
||||
// Create a new block including the specified transactions
|
||||
newBlock, err := CreateBlock(prevBlock, txns, blockVersion,
|
||||
blockTime, h.wallet.coinbaseAddr, h.ActiveNet)
|
||||
blockTime, h.wallet.coinbaseAddr, mineTo, h.ActiveNet)
|
||||
if err != nil {
|
||||
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) {
|
||||
// Create a fresh harness, we'll be using the main harness to force a
|
||||
// re-org on this local harness.
|
||||
|
@ -478,6 +553,7 @@ var harnessTestCases = []HarnessTestCase{
|
|||
testJoinBlocks,
|
||||
testJoinMempools, // Depends on results of testJoinBlocks
|
||||
testGenerateAndSubmitBlock,
|
||||
testGenerateAndSubmitBlockWithCustomCoinbaseOutputs,
|
||||
testMemWalletReorg,
|
||||
testMemWalletLockedOutputs,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue