github.com/decred/dcrd/blockchain@v1.2.1/validate_test.go (about)

     1  // Copyright (c) 2013-2016 The btcsuite developers
     2  // Copyright (c) 2015-2019 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package blockchain
     7  
     8  import (
     9  	"bytes"
    10  	"compress/bzip2"
    11  	"encoding/gob"
    12  	"fmt"
    13  	mrand "math/rand"
    14  	"os"
    15  	"path/filepath"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/decred/dcrd/blockchain/chaingen"
    20  	"github.com/decred/dcrd/chaincfg"
    21  	"github.com/decred/dcrd/chaincfg/chainhash"
    22  	"github.com/decred/dcrd/database"
    23  	"github.com/decred/dcrd/dcrutil"
    24  	"github.com/decred/dcrd/wire"
    25  )
    26  
    27  // TestBlockchainSpendJournal tests for whether or not the spend journal is being
    28  // written to disk correctly on a live blockchain.
    29  func TestBlockchainSpendJournal(t *testing.T) {
    30  	// Update parameters to reflect what is expected by the legacy data.
    31  	params := cloneParams(&chaincfg.RegNetParams)
    32  	params.GenesisBlock.Header.MerkleRoot = *mustParseHash("a216ea043f0d481a072424af646787794c32bcefd3ed181a090319bbf8a37105")
    33  	params.GenesisBlock.Header.Timestamp = time.Unix(1401292357, 0)
    34  	params.GenesisBlock.Transactions[0].TxIn[0].ValueIn = 0
    35  	params.PubKeyHashAddrID = [2]byte{0x0e, 0x91}
    36  	params.StakeBaseSigScript = []byte{0xde, 0xad, 0xbe, 0xef}
    37  	params.OrganizationPkScript = hexToBytes("a914cbb08d6ca783b533b2c7d24a51fbca92d937bf9987")
    38  	params.BlockOneLedger = []*chaincfg.TokenPayout{
    39  		{Address: "Sshw6S86G2bV6W32cbc7EhtFy8f93rU6pae", Amount: 100000 * 1e8},
    40  		{Address: "SsjXRK6Xz6CFuBt6PugBvrkdAa4xGbcZ18w", Amount: 100000 * 1e8},
    41  		{Address: "SsfXiYkYkCoo31CuVQw428N6wWKus2ZEw5X", Amount: 100000 * 1e8},
    42  	}
    43  	genesisHash := params.GenesisBlock.BlockHash()
    44  	params.GenesisHash = &genesisHash
    45  
    46  	// Create a new database and chain instance to run tests against.
    47  	chain, teardownFunc, err := chainSetup("spendjournalunittest", params)
    48  	if err != nil {
    49  		t.Errorf("Failed to setup chain instance: %v", err)
    50  		return
    51  	}
    52  	defer teardownFunc()
    53  
    54  	// Load up the rest of the blocks up to HEAD.
    55  	filename := filepath.Join("testdata", "reorgto179.bz2")
    56  	fi, err := os.Open(filename)
    57  	if err != nil {
    58  		t.Errorf("Failed to open %s: %v", filename, err)
    59  	}
    60  	bcStream := bzip2.NewReader(fi)
    61  	defer fi.Close()
    62  
    63  	// Create a buffer of the read file
    64  	bcBuf := new(bytes.Buffer)
    65  	bcBuf.ReadFrom(bcStream)
    66  
    67  	// Create decoder from the buffer and a map to store the data
    68  	bcDecoder := gob.NewDecoder(bcBuf)
    69  	blockChain := make(map[int64][]byte)
    70  
    71  	// Decode the blockchain into the map
    72  	if err := bcDecoder.Decode(&blockChain); err != nil {
    73  		t.Errorf("error decoding test blockchain: %v", err.Error())
    74  	}
    75  
    76  	// Load up the short chain
    77  	finalIdx1 := 179
    78  	for i := 1; i < finalIdx1+1; i++ {
    79  		bl, err := dcrutil.NewBlockFromBytes(blockChain[int64(i)])
    80  		if err != nil {
    81  			t.Fatalf("NewBlockFromBytes error: %v", err.Error())
    82  		}
    83  
    84  		forkLen, isOrphan, err := chain.ProcessBlock(bl, BFNone)
    85  		if err != nil {
    86  			t.Fatalf("ProcessBlock error at height %v: %v", i, err.Error())
    87  		}
    88  		isMainChain := !isOrphan && forkLen == 0
    89  		if !isMainChain {
    90  			t.Fatalf("block %s (height %d) should have been "+
    91  				"accepted to the main chain", bl.Hash(),
    92  				bl.MsgBlock().Header.Height)
    93  		}
    94  	}
    95  
    96  	// Loop through all of the blocks and ensure the number of spent outputs
    97  	// matches up with the information loaded from the spend journal.
    98  	err = chain.db.View(func(dbTx database.Tx) error {
    99  		for i := int64(2); i <= chain.bestChain.Tip().height; i++ {
   100  			node := chain.bestChain.NodeByHeight(i)
   101  			if node == nil {
   102  				str := fmt.Sprintf("no block at height %d exists", i)
   103  				return errNotInMainChain(str)
   104  			}
   105  			block, err := dbFetchBlockByNode(dbTx, node)
   106  			if err != nil {
   107  				return err
   108  			}
   109  
   110  			ntx := countSpentOutputs(block)
   111  			stxos, err := dbFetchSpendJournalEntry(dbTx, block)
   112  			if err != nil {
   113  				return err
   114  			}
   115  
   116  			if ntx != len(stxos) {
   117  				return fmt.Errorf("bad number of stxos "+
   118  					"calculated at "+"height %v, got %v "+
   119  					"expected %v", i, len(stxos), ntx)
   120  			}
   121  		}
   122  
   123  		return nil
   124  	})
   125  	if err != nil {
   126  		t.Errorf("unexpected error: %v", err)
   127  	}
   128  }
   129  
   130  // TestSequenceLocksActive ensure the sequence locks are detected as active or
   131  // not as expected in all possible scenarios.
   132  func TestSequenceLocksActive(t *testing.T) {
   133  	now := time.Now().Unix()
   134  	tests := []struct {
   135  		name          string
   136  		seqLockHeight int64
   137  		seqLockTime   int64
   138  		blockHeight   int64
   139  		medianTime    int64
   140  		want          bool
   141  	}{
   142  		{
   143  			// Block based sequence lock with height at min
   144  			// required.
   145  			name:          "min active block height",
   146  			seqLockHeight: 1000,
   147  			seqLockTime:   -1,
   148  			blockHeight:   1001,
   149  			medianTime:    now + 31,
   150  			want:          true,
   151  		},
   152  		{
   153  			// Time based sequence lock with relative time at min
   154  			// required.
   155  			name:          "min active median time",
   156  			seqLockHeight: -1,
   157  			seqLockTime:   now + 30,
   158  			blockHeight:   1001,
   159  			medianTime:    now + 31,
   160  			want:          true,
   161  		},
   162  		{
   163  			// Block based sequence lock at same height.
   164  			name:          "same height",
   165  			seqLockHeight: 1000,
   166  			seqLockTime:   -1,
   167  			blockHeight:   1000,
   168  			medianTime:    now + 31,
   169  			want:          false,
   170  		},
   171  		{
   172  			// Time based sequence lock with relative time equal to
   173  			// lock time.
   174  			name:          "same median time",
   175  			seqLockHeight: -1,
   176  			seqLockTime:   now + 30,
   177  			blockHeight:   1001,
   178  			medianTime:    now + 30,
   179  			want:          false,
   180  		},
   181  		{
   182  			// Block based sequence lock with relative height below
   183  			// required.
   184  			name:          "height below required",
   185  			seqLockHeight: 1000,
   186  			seqLockTime:   -1,
   187  			blockHeight:   999,
   188  			medianTime:    now + 31,
   189  			want:          false,
   190  		},
   191  		{
   192  			// Time based sequence lock with relative time before
   193  			// required.
   194  			name:          "median time before required",
   195  			seqLockHeight: -1,
   196  			seqLockTime:   now + 30,
   197  			blockHeight:   1001,
   198  			medianTime:    now + 29,
   199  			want:          false,
   200  		},
   201  	}
   202  
   203  	for _, test := range tests {
   204  		seqLock := SequenceLock{
   205  			MinHeight: test.seqLockHeight,
   206  			MinTime:   test.seqLockTime,
   207  		}
   208  		got := SequenceLockActive(&seqLock, test.blockHeight,
   209  			time.Unix(test.medianTime, 0))
   210  		if got != test.want {
   211  			t.Errorf("%s: mismatched seqence lock status - got %v, "+
   212  				"want %v", test.name, got, test.want)
   213  			continue
   214  		}
   215  	}
   216  }
   217  
   218  // quickVoteActivationParams returns a set of test chain parameters which allow
   219  // for quicker vote activation as compared to various existing network params by
   220  // reducing the required maturities, the ticket pool size, the stake enabled and
   221  // validation heights, the proof-of-work block version upgrade window, the stake
   222  // version interval, and the rule change activation interval.
   223  func quickVoteActivationParams() *chaincfg.Params {
   224  	params := cloneParams(&chaincfg.RegNetParams)
   225  	params.WorkDiffWindowSize = 200000
   226  	params.WorkDiffWindows = 1
   227  	params.TargetTimespan = params.TargetTimePerBlock *
   228  		time.Duration(params.WorkDiffWindowSize)
   229  	params.CoinbaseMaturity = 2
   230  	params.BlockEnforceNumRequired = 5
   231  	params.BlockRejectNumRequired = 7
   232  	params.BlockUpgradeNumToCheck = 10
   233  	params.TicketMaturity = 2
   234  	params.TicketPoolSize = 4
   235  	params.TicketExpiry = 6 * uint32(params.TicketPoolSize)
   236  	params.StakeEnabledHeight = int64(params.CoinbaseMaturity) +
   237  		int64(params.TicketMaturity)
   238  	params.StakeValidationHeight = int64(params.CoinbaseMaturity) +
   239  		int64(params.TicketPoolSize)*2
   240  	params.StakeVersionInterval = 10
   241  	params.RuleChangeActivationInterval = uint32(params.TicketPoolSize) *
   242  		uint32(params.TicketsPerBlock)
   243  	params.RuleChangeActivationQuorum = params.RuleChangeActivationInterval *
   244  		uint32(params.TicketsPerBlock*100) / 1000
   245  
   246  	return params
   247  }
   248  
   249  // TestLegacySequenceLocks ensure that sequence locks within blocks behave as
   250  // expected according to the legacy semantics in previous version of the
   251  // software.
   252  func TestLegacySequenceLocks(t *testing.T) {
   253  	// Use a set of test chain parameters which allow for quicker vote
   254  	// activation as compared to various existing network params.
   255  	params := quickVoteActivationParams()
   256  
   257  	// Clone the parameters so they can be mutated, find the correct deployment
   258  	// for the LN features agenda, and, finally, ensure it is always available
   259  	// to vote by removing the time constraints to prevent test failures when
   260  	// the real expiration time passes.
   261  	const lnfVoteID = chaincfg.VoteIDLNFeatures
   262  	params = cloneParams(params)
   263  	lnfVersion, deployment, err := findDeployment(params, lnfVoteID)
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  	removeDeploymentTimeConstraints(deployment)
   268  
   269  	// Create a test harness initialized with the genesis block as the tip.
   270  	g, teardownFunc := newChaingenHarness(t, params, "seqlocksoldsemanticstest")
   271  	defer teardownFunc()
   272  
   273  	// replaceLNFeaturesVersions is a munge function which modifies the provided
   274  	// block by replacing the block, stake, and vote versions with the LN
   275  	// features deployment version.
   276  	replaceLNFeaturesVersions := func(b *wire.MsgBlock) {
   277  		chaingen.ReplaceBlockVersion(int32(lnfVersion))(b)
   278  		chaingen.ReplaceStakeVersion(lnfVersion)(b)
   279  		chaingen.ReplaceVoteVersions(lnfVersion)(b)
   280  	}
   281  
   282  	// ---------------------------------------------------------------------
   283  	// Generate and accept enough blocks with the appropriate vote bits set
   284  	// to reach one block prior to the LN features agenda becoming active.
   285  	// ---------------------------------------------------------------------
   286  
   287  	g.AdvanceToStakeValidationHeight()
   288  	g.AdvanceFromSVHToActiveAgenda(lnfVoteID)
   289  
   290  	// ---------------------------------------------------------------------
   291  	// Perform a series of sequence lock tests now that ln feature
   292  	// enforcement is active.
   293  	// ---------------------------------------------------------------------
   294  
   295  	// enableSeqLocks modifies the passed transaction to enable sequence locks
   296  	// for the provided input.
   297  	enableSeqLocks := func(tx *wire.MsgTx, txInIdx int) {
   298  		tx.Version = 2
   299  		tx.TxIn[txInIdx].Sequence = 0
   300  	}
   301  
   302  	// ---------------------------------------------------------------------
   303  	// Create block that has a transaction with an input shared with a
   304  	// transaction in the stake tree and has several outputs used in
   305  	// subsequent blocks.  Also, enable sequence locks for the first of
   306  	// those outputs.
   307  	//
   308  	//   ... -> b0
   309  	// ---------------------------------------------------------------------
   310  
   311  	outs := g.OldestCoinbaseOuts()
   312  	b0 := g.NextBlock("b0", &outs[0], outs[1:], replaceLNFeaturesVersions,
   313  		func(b *wire.MsgBlock) {
   314  			// Save the current outputs of the spend tx and clear them.
   315  			tx := b.Transactions[1]
   316  			origOut := tx.TxOut[0]
   317  			origOpReturnOut := tx.TxOut[1]
   318  			tx.TxOut = tx.TxOut[:0]
   319  
   320  			// Evenly split the original output amount over multiple outputs.
   321  			const numOutputs = 6
   322  			amount := origOut.Value / numOutputs
   323  			for i := 0; i < numOutputs; i++ {
   324  				if i == numOutputs-1 {
   325  					amount = origOut.Value - amount*(numOutputs-1)
   326  				}
   327  				tx.AddTxOut(wire.NewTxOut(amount, origOut.PkScript))
   328  			}
   329  
   330  			// Add the original op return back to the outputs and enable
   331  			// sequence locks for the first output.
   332  			tx.AddTxOut(origOpReturnOut)
   333  			enableSeqLocks(tx, 0)
   334  		})
   335  	g.SaveTipCoinbaseOuts()
   336  	g.AcceptTipBlock()
   337  
   338  	// ---------------------------------------------------------------------
   339  	// Create block that spends from an output created in the previous
   340  	// block.
   341  	//
   342  	//   ... -> b0 -> b1a
   343  	// ---------------------------------------------------------------------
   344  
   345  	outs = g.OldestCoinbaseOuts()
   346  	g.NextBlock("b1a", nil, outs[1:], replaceLNFeaturesVersions,
   347  		func(b *wire.MsgBlock) {
   348  			spend := chaingen.MakeSpendableOut(b0, 1, 0)
   349  			tx := g.CreateSpendTx(&spend, dcrutil.Amount(1))
   350  			enableSeqLocks(tx, 0)
   351  			b.AddTransaction(tx)
   352  		})
   353  	g.AcceptTipBlock()
   354  
   355  	// ---------------------------------------------------------------------
   356  	// Create block that involves reorganize to a sequence lock spending
   357  	// from an output created in a block prior to the parent also spent on
   358  	// on the side chain.
   359  	//
   360  	//   ... -> b0 -> b1  -> b2
   361  	//            \-> b1a
   362  	// ---------------------------------------------------------------------
   363  	g.SetTip("b0")
   364  	g.NextBlock("b1", nil, outs[1:], replaceLNFeaturesVersions)
   365  	g.SaveTipCoinbaseOuts()
   366  	g.AcceptedToSideChainWithExpectedTip("b1a")
   367  
   368  	outs = g.OldestCoinbaseOuts()
   369  	g.NextBlock("b2", nil, outs[1:], replaceLNFeaturesVersions,
   370  		func(b *wire.MsgBlock) {
   371  			spend := chaingen.MakeSpendableOut(b0, 1, 0)
   372  			tx := g.CreateSpendTx(&spend, dcrutil.Amount(1))
   373  			enableSeqLocks(tx, 0)
   374  			b.AddTransaction(tx)
   375  		})
   376  	g.SaveTipCoinbaseOuts()
   377  	g.AcceptTipBlock()
   378  	g.ExpectTip("b2")
   379  
   380  	// ---------------------------------------------------------------------
   381  	// Create block that involves a sequence lock on a vote.
   382  	//
   383  	//   ... -> b2 -> b3
   384  	// ---------------------------------------------------------------------
   385  
   386  	outs = g.OldestCoinbaseOuts()
   387  	g.NextBlock("b3", nil, outs[1:], replaceLNFeaturesVersions,
   388  		func(b *wire.MsgBlock) {
   389  			enableSeqLocks(b.STransactions[0], 0)
   390  		})
   391  	g.SaveTipCoinbaseOuts()
   392  	g.AcceptTipBlock()
   393  
   394  	// ---------------------------------------------------------------------
   395  	// Create block that involves a sequence lock on a ticket.
   396  	//
   397  	//   ... -> b3 -> b4
   398  	// ---------------------------------------------------------------------
   399  
   400  	outs = g.OldestCoinbaseOuts()
   401  	g.NextBlock("b4", nil, outs[1:], replaceLNFeaturesVersions,
   402  		func(b *wire.MsgBlock) {
   403  			enableSeqLocks(b.STransactions[5], 0)
   404  		})
   405  	g.SaveTipCoinbaseOuts()
   406  	g.AcceptTipBlock()
   407  
   408  	// ---------------------------------------------------------------------
   409  	// Create two blocks such that the tip block involves a sequence lock
   410  	// spending from a different output of a transaction the parent block
   411  	// also spends from.
   412  	//
   413  	//   ... -> b4 -> b5 -> b6
   414  	// ---------------------------------------------------------------------
   415  
   416  	outs = g.OldestCoinbaseOuts()
   417  	g.NextBlock("b5", nil, outs[1:], replaceLNFeaturesVersions,
   418  		func(b *wire.MsgBlock) {
   419  			spend := chaingen.MakeSpendableOut(b0, 1, 1)
   420  			tx := g.CreateSpendTx(&spend, dcrutil.Amount(1))
   421  			b.AddTransaction(tx)
   422  		})
   423  	g.SaveTipCoinbaseOuts()
   424  	g.AcceptTipBlock()
   425  
   426  	outs = g.OldestCoinbaseOuts()
   427  	g.NextBlock("b6", nil, outs[1:], replaceLNFeaturesVersions,
   428  		func(b *wire.MsgBlock) {
   429  			spend := chaingen.MakeSpendableOut(b0, 1, 2)
   430  			tx := g.CreateSpendTx(&spend, dcrutil.Amount(1))
   431  			enableSeqLocks(tx, 0)
   432  			b.AddTransaction(tx)
   433  		})
   434  	g.SaveTipCoinbaseOuts()
   435  	g.AcceptTipBlock()
   436  
   437  	// ---------------------------------------------------------------------
   438  	// Create block that involves a sequence lock spending from a regular
   439  	// tree transaction earlier in the block.  It should be rejected due
   440  	// to a consensus bug.
   441  	//
   442  	//   ... -> b6
   443  	//            \-> b7
   444  	// ---------------------------------------------------------------------
   445  
   446  	outs = g.OldestCoinbaseOuts()
   447  	g.NextBlock("b7", &outs[0], outs[1:], replaceLNFeaturesVersions,
   448  		func(b *wire.MsgBlock) {
   449  			spend := chaingen.MakeSpendableOut(b, 1, 0)
   450  			tx := g.CreateSpendTx(&spend, dcrutil.Amount(1))
   451  			enableSeqLocks(tx, 0)
   452  			b.AddTransaction(tx)
   453  		})
   454  	g.RejectTipBlock(ErrMissingTxOut)
   455  
   456  	// ---------------------------------------------------------------------
   457  	// Create block that involves a sequence lock spending from a block
   458  	// prior to the parent.  It should be rejected due to a consensus bug.
   459  	//
   460  	//   ... -> b6 -> b8
   461  	//                  \-> b9
   462  	// ---------------------------------------------------------------------
   463  
   464  	g.SetTip("b6")
   465  	g.NextBlock("b8", nil, outs[1:], replaceLNFeaturesVersions)
   466  	g.SaveTipCoinbaseOuts()
   467  	g.AcceptTipBlock()
   468  
   469  	outs = g.OldestCoinbaseOuts()
   470  	g.NextBlock("b9", nil, outs[1:], replaceLNFeaturesVersions,
   471  		func(b *wire.MsgBlock) {
   472  			spend := chaingen.MakeSpendableOut(b0, 1, 3)
   473  			tx := g.CreateSpendTx(&spend, dcrutil.Amount(1))
   474  			enableSeqLocks(tx, 0)
   475  			b.AddTransaction(tx)
   476  		})
   477  	g.RejectTipBlock(ErrMissingTxOut)
   478  
   479  	// ---------------------------------------------------------------------
   480  	// Create two blocks such that the tip block involves a sequence lock
   481  	// spending from a different output of a transaction the parent block
   482  	// also spends from when the parent block has been disapproved.    It
   483  	// should be rejected due to a consensus bug.
   484  	//
   485  	//   ... -> b8 -> b10
   486  	//                   \-> b11
   487  	// ---------------------------------------------------------------------
   488  
   489  	const (
   490  		// vbDisapprovePrev and vbApprovePrev represent no and yes votes,
   491  		// respectively, on whether or not to approve the previous block.
   492  		vbDisapprovePrev = 0x0000
   493  		vbApprovePrev    = 0x0001
   494  	)
   495  
   496  	g.SetTip("b8")
   497  	g.NextBlock("b10", nil, outs[1:], replaceLNFeaturesVersions,
   498  		func(b *wire.MsgBlock) {
   499  			spend := chaingen.MakeSpendableOut(b0, 1, 4)
   500  			tx := g.CreateSpendTx(&spend, dcrutil.Amount(1))
   501  			b.AddTransaction(tx)
   502  		})
   503  	g.SaveTipCoinbaseOuts()
   504  	g.AcceptTipBlock()
   505  
   506  	outs = g.OldestCoinbaseOuts()
   507  	g.NextBlock("b11", nil, outs[1:], replaceLNFeaturesVersions,
   508  		chaingen.ReplaceVotes(vbDisapprovePrev, lnfVersion),
   509  		func(b *wire.MsgBlock) {
   510  			b.Header.VoteBits &^= vbApprovePrev
   511  			spend := chaingen.MakeSpendableOut(b0, 1, 5)
   512  			tx := g.CreateSpendTx(&spend, dcrutil.Amount(1))
   513  			enableSeqLocks(tx, 0)
   514  			b.AddTransaction(tx)
   515  		})
   516  	g.RejectTipBlock(ErrMissingTxOut)
   517  }
   518  
   519  // TestCheckBlockSanity tests the context free block sanity checks with blocks
   520  // not on a chain.
   521  func TestCheckBlockSanity(t *testing.T) {
   522  	params := &chaincfg.RegNetParams
   523  	timeSource := NewMedianTime()
   524  	block := dcrutil.NewBlock(&badBlock)
   525  	err := CheckBlockSanity(block, timeSource, params)
   526  	if err == nil {
   527  		t.Fatalf("block should fail.\n")
   528  	}
   529  }
   530  
   531  // TestCheckBlockHeaderContext tests that genesis block passes context headers
   532  // because its parent is nil.
   533  func TestCheckBlockHeaderContext(t *testing.T) {
   534  	// Create a new database for the blocks.
   535  	params := &chaincfg.RegNetParams
   536  	dbPath := filepath.Join(os.TempDir(), "examplecheckheadercontext")
   537  	_ = os.RemoveAll(dbPath)
   538  	db, err := database.Create("ffldb", dbPath, params.Net)
   539  	if err != nil {
   540  		t.Fatalf("Failed to create database: %v\n", err)
   541  		return
   542  	}
   543  	defer os.RemoveAll(dbPath)
   544  	defer db.Close()
   545  
   546  	// Create a new BlockChain instance using the underlying database for
   547  	// the simnet network.
   548  	chain, err := New(&Config{
   549  		DB:          db,
   550  		ChainParams: params,
   551  		TimeSource:  NewMedianTime(),
   552  	})
   553  	if err != nil {
   554  		t.Fatalf("Failed to create chain instance: %v\n", err)
   555  		return
   556  	}
   557  
   558  	err = chain.checkBlockHeaderContext(&params.GenesisBlock.Header, nil, BFNone)
   559  	if err != nil {
   560  		t.Fatalf("genesisblock should pass just by definition: %v\n", err)
   561  		return
   562  	}
   563  
   564  	// Test failing checkBlockHeaderContext when calcNextRequiredDifficulty
   565  	// fails.
   566  	block := dcrutil.NewBlock(&badBlock)
   567  	newNode := newBlockNode(&block.MsgBlock().Header, nil)
   568  	err = chain.checkBlockHeaderContext(&block.MsgBlock().Header, newNode, BFNone)
   569  	if err == nil {
   570  		t.Fatalf("Should fail due to bad diff in newNode\n")
   571  		return
   572  	}
   573  }
   574  
   575  // TestTxValidationErrors ensures certain malformed freestanding transactions
   576  // are rejected as as expected.
   577  func TestTxValidationErrors(t *testing.T) {
   578  	// Create a transaction that is too large
   579  	tx := wire.NewMsgTx()
   580  	prevOut := wire.NewOutPoint(&chainhash.Hash{0x01}, 0, wire.TxTreeRegular)
   581  	tx.AddTxIn(wire.NewTxIn(prevOut, 0, nil))
   582  	pkScript := bytes.Repeat([]byte{0x00}, wire.MaxBlockPayload)
   583  	tx.AddTxOut(wire.NewTxOut(0, pkScript))
   584  
   585  	// Assert the transaction is larger than the max allowed size.
   586  	txSize := tx.SerializeSize()
   587  	if txSize <= wire.MaxBlockPayload {
   588  		t.Fatalf("generated transaction is not large enough -- got "+
   589  			"%d, want > %d", txSize, wire.MaxBlockPayload)
   590  	}
   591  
   592  	// Ensure transaction is rejected due to being too large.
   593  	err := CheckTransactionSanity(tx, &chaincfg.MainNetParams)
   594  	rerr, ok := err.(RuleError)
   595  	if !ok {
   596  		t.Fatalf("CheckTransactionSanity: unexpected error type for "+
   597  			"transaction that is too large -- got %T", err)
   598  	}
   599  	if rerr.ErrorCode != ErrTxTooBig {
   600  		t.Fatalf("CheckTransactionSanity: unexpected error code for "+
   601  			"transaction that is too large -- got %v, want %v",
   602  			rerr.ErrorCode, ErrTxTooBig)
   603  	}
   604  }
   605  
   606  // badBlock is an intentionally bad block that should fail the context-less
   607  // sanity checks.
   608  var badBlock = wire.MsgBlock{
   609  	Header: wire.BlockHeader{
   610  		Version:      1,
   611  		MerkleRoot:   chaincfg.RegNetParams.GenesisBlock.Header.MerkleRoot,
   612  		VoteBits:     uint16(0x0000),
   613  		FinalState:   [6]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
   614  		Voters:       uint16(0x0000),
   615  		FreshStake:   uint8(0x00),
   616  		Revocations:  uint8(0x00),
   617  		Timestamp:    time.Unix(1401292357, 0), // 2009-01-08 20:54:25 -0600 CST
   618  		PoolSize:     uint32(0),
   619  		Bits:         0x207fffff, // 545259519
   620  		SBits:        int64(0x0000000000000000),
   621  		Nonce:        0x37580963,
   622  		StakeVersion: uint32(0),
   623  		Height:       uint32(0),
   624  	},
   625  	Transactions:  []*wire.MsgTx{},
   626  	STransactions: []*wire.MsgTx{},
   627  }
   628  
   629  // TestCheckConnectBlockTemplate ensures that the code which deals with
   630  // checking block templates works as expected.
   631  func TestCheckConnectBlockTemplate(t *testing.T) {
   632  	// Create a test harness initialized with the genesis block as the tip.
   633  	params := &chaincfg.RegNetParams
   634  	g, teardownFunc := newChaingenHarness(t, params, "connectblktemplatetest")
   635  	defer teardownFunc()
   636  
   637  	// Define some additional convenience helper functions to process the
   638  	// current tip block associated with the generator.
   639  	//
   640  	// acceptedBlockTemplate expected the block to considered a valid block
   641  	// template.
   642  	//
   643  	// rejectedBlockTemplate expects the block to be considered an invalid
   644  	// block template due to the provided error code.
   645  	acceptedBlockTemplate := func() {
   646  		msgBlock := g.Tip()
   647  		blockHeight := msgBlock.Header.Height
   648  		block := dcrutil.NewBlock(msgBlock)
   649  		t.Logf("Testing block template %s (hash %s, height %d)",
   650  			g.TipName(), block.Hash(), blockHeight)
   651  
   652  		err := g.chain.CheckConnectBlockTemplate(block)
   653  		if err != nil {
   654  			t.Fatalf("block template %q (hash %s, height %d) should "+
   655  				"have been accepted: %v", g.TipName(),
   656  				block.Hash(), blockHeight, err)
   657  		}
   658  	}
   659  	rejectedBlockTemplate := func(code ErrorCode) {
   660  		msgBlock := g.Tip()
   661  		blockHeight := msgBlock.Header.Height
   662  		block := dcrutil.NewBlock(msgBlock)
   663  		t.Logf("Testing block template %s (hash %s, height %d)",
   664  			g.TipName(), block.Hash(), blockHeight)
   665  
   666  		err := g.chain.CheckConnectBlockTemplate(block)
   667  		if err == nil {
   668  			t.Fatalf("block template %q (hash %s, height %d) should "+
   669  				"not have been accepted", g.TipName(), block.Hash(),
   670  				blockHeight)
   671  		}
   672  
   673  		// Ensure the error code is of the expected type and the reject
   674  		// code matches the value specified in the test instance.
   675  		rerr, ok := err.(RuleError)
   676  		if !ok {
   677  			t.Fatalf("block template %q (hash %s, height %d) "+
   678  				"returned unexpected error type -- got %T, want "+
   679  				"blockchain.RuleError", g.TipName(),
   680  				block.Hash(), blockHeight, err)
   681  		}
   682  		if rerr.ErrorCode != code {
   683  			t.Fatalf("block template %q (hash %s, height %d) does "+
   684  				"not have expected reject code -- got %v, want %v",
   685  				g.TipName(), block.Hash(), blockHeight,
   686  				rerr.ErrorCode, code)
   687  		}
   688  	}
   689  
   690  	// changeNonce is a munger that modifies the block by changing the header
   691  	// nonce to a pseudo-random value.
   692  	prng := mrand.New(mrand.NewSource(0))
   693  	changeNonce := func(b *wire.MsgBlock) {
   694  		// Change the nonce so the block isn't actively solved.
   695  		b.Header.Nonce = prng.Uint32()
   696  	}
   697  
   698  	// Shorter versions of useful params for convenience.
   699  	ticketsPerBlock := params.TicketsPerBlock
   700  	coinbaseMaturity := params.CoinbaseMaturity
   701  	stakeEnabledHeight := params.StakeEnabledHeight
   702  	stakeValidationHeight := params.StakeValidationHeight
   703  
   704  	// ---------------------------------------------------------------------
   705  	// First block templates.
   706  	//
   707  	// NOTE: The advance funcs on the harness are intentionally not used in
   708  	// these tests since they need to manually test block templates at all
   709  	// heights.
   710  	// ---------------------------------------------------------------------
   711  
   712  	// Produce an initial block with too much coinbase and ensure the block
   713  	// template is rejected.
   714  	//
   715  	//   genesis
   716  	//          \-> bfbbad
   717  	g.CreatePremineBlock("bfbbad", 1)
   718  	g.AssertTipHeight(1)
   719  	rejectedBlockTemplate(ErrBadCoinbaseValue)
   720  
   721  	// Produce a valid, but unsolved initial block and ensure the block template
   722  	// is accepted while the unsolved block is rejected.
   723  	//
   724  	//   genesis
   725  	//          \-> bfbunsolved
   726  	g.SetTip("genesis")
   727  	bfbunsolved := g.CreatePremineBlock("bfbunsolved", 0, changeNonce)
   728  	// Since the difficulty is so low in the tests, the block might still
   729  	// end up being inadvertently solved.  It can't be checked inside the
   730  	// munger because the block is finalized after the function returns and
   731  	// those changes could also inadvertently solve the block.  Thus, just
   732  	// increment the nonce until it's not solved and then replace it in the
   733  	// generator's state.
   734  	{
   735  		origHash := bfbunsolved.BlockHash()
   736  		for chaingen.IsSolved(&bfbunsolved.Header) {
   737  			bfbunsolved.Header.Nonce++
   738  		}
   739  		g.UpdateBlockState("bfbunsolved", origHash, "bfbunsolved", bfbunsolved)
   740  	}
   741  	g.AssertTipHeight(1)
   742  	acceptedBlockTemplate()
   743  	g.RejectTipBlock(ErrHighHash)
   744  	g.ExpectTip("genesis")
   745  
   746  	// Produce a valid and solved initial block.
   747  	//
   748  	//   genesis -> bfb
   749  	g.SetTip("genesis")
   750  	g.CreatePremineBlock("bfb", 0)
   751  	g.AssertTipHeight(1)
   752  	g.AcceptTipBlock()
   753  
   754  	// ---------------------------------------------------------------------
   755  	// Generate enough blocks to have mature coinbase outputs to work with.
   756  	//
   757  	// Also, ensure that each block is considered a valid template along the
   758  	// way.
   759  	//
   760  	//   genesis -> bfb -> bm0 -> bm1 -> ... -> bm#
   761  	// ---------------------------------------------------------------------
   762  
   763  	var tipName string
   764  	for i := uint16(0); i < coinbaseMaturity; i++ {
   765  		blockName := fmt.Sprintf("bm%d", i)
   766  		g.NextBlock(blockName, nil, nil)
   767  		g.SaveTipCoinbaseOuts()
   768  		acceptedBlockTemplate()
   769  		g.AcceptTipBlock()
   770  		tipName = blockName
   771  	}
   772  	g.AssertTipHeight(uint32(coinbaseMaturity) + 1)
   773  
   774  	// ---------------------------------------------------------------------
   775  	// Generate block templates that include invalid ticket purchases.
   776  	// ---------------------------------------------------------------------
   777  
   778  	// Create a block template with a ticket that claims too much input
   779  	// amount.
   780  	//
   781  	//   ... -> bm#
   782  	//             \-> btixt1
   783  	tempOuts := g.OldestCoinbaseOuts()
   784  	tempTicketOuts := tempOuts[1:]
   785  	g.NextBlock("btixt1", nil, tempTicketOuts, func(b *wire.MsgBlock) {
   786  		changeNonce(b)
   787  		b.STransactions[3].TxIn[0].ValueIn--
   788  	})
   789  	rejectedBlockTemplate(ErrFraudAmountIn)
   790  
   791  	// Create a block template with a ticket that does not pay enough.
   792  	//
   793  	//   ... -> bm#
   794  	//             \-> btixt2
   795  	g.SetTip(tipName)
   796  	g.NextBlock("btixt2", nil, tempTicketOuts, func(b *wire.MsgBlock) {
   797  		changeNonce(b)
   798  		b.STransactions[2].TxOut[0].Value--
   799  	})
   800  	rejectedBlockTemplate(ErrNotEnoughStake)
   801  
   802  	// ---------------------------------------------------------------------
   803  	// Generate enough blocks to reach the stake enabled height while
   804  	// creating ticket purchases that spend from the coinbases matured
   805  	// above.  This will also populate the pool of immature tickets.
   806  	//
   807  	// Also, ensure that each block is considered a valid template along the
   808  	// way.
   809  	//
   810  	//   ... -> bm# ... -> bse0 -> bse1 -> ... -> bse#
   811  	// ---------------------------------------------------------------------
   812  
   813  	// Use the already popped outputs.
   814  	g.SetTip(tipName)
   815  	g.NextBlock("bse0", nil, tempTicketOuts)
   816  	g.SaveTipCoinbaseOuts()
   817  	acceptedBlockTemplate()
   818  	g.AcceptTipBlock()
   819  
   820  	var ticketsPurchased int
   821  	for i := int64(1); int64(g.Tip().Header.Height) < stakeEnabledHeight; i++ {
   822  		outs := g.OldestCoinbaseOuts()
   823  		ticketOuts := outs[1:]
   824  		ticketsPurchased += len(ticketOuts)
   825  		blockName := fmt.Sprintf("bse%d", i)
   826  		g.NextBlock(blockName, nil, ticketOuts)
   827  		g.SaveTipCoinbaseOuts()
   828  		acceptedBlockTemplate()
   829  		g.AcceptTipBlock()
   830  	}
   831  	g.AssertTipHeight(uint32(stakeEnabledHeight))
   832  
   833  	// ---------------------------------------------------------------------
   834  	// Generate enough blocks to reach the stake validation height while
   835  	// continuing to purchase tickets using the coinbases matured above and
   836  	// allowing the immature tickets to mature and thus become live.
   837  	//
   838  	// Also, ensure that each block is considered a valid template along the
   839  	// way.
   840  	//
   841  	//   ... -> bse# -> bsv0 -> bsv1 -> ... -> bsv#
   842  	// ---------------------------------------------------------------------
   843  
   844  	targetPoolSize := g.Params().TicketPoolSize * ticketsPerBlock
   845  	for i := int64(0); int64(g.Tip().Header.Height) < stakeValidationHeight; i++ {
   846  		// Only purchase tickets until the target ticket pool size is
   847  		// reached.
   848  		outs := g.OldestCoinbaseOuts()
   849  		ticketOuts := outs[1:]
   850  		if ticketsPurchased+len(ticketOuts) > int(targetPoolSize) {
   851  			ticketsNeeded := int(targetPoolSize) - ticketsPurchased
   852  			if ticketsNeeded > 0 {
   853  				ticketOuts = ticketOuts[1 : ticketsNeeded+1]
   854  			} else {
   855  				ticketOuts = nil
   856  			}
   857  		}
   858  		ticketsPurchased += len(ticketOuts)
   859  
   860  		blockName := fmt.Sprintf("bsv%d", i)
   861  		g.NextBlock(blockName, nil, ticketOuts)
   862  		g.SaveTipCoinbaseOuts()
   863  		acceptedBlockTemplate()
   864  		g.AcceptTipBlock()
   865  	}
   866  	g.AssertTipHeight(uint32(stakeValidationHeight))
   867  
   868  	// ---------------------------------------------------------------------
   869  	// Generate enough blocks to have a known distance to the first mature
   870  	// coinbase outputs for all tests that follow.  These blocks continue
   871  	// to purchase tickets to avoid running out of votes.
   872  	//
   873  	// Also, ensure that each block is considered a valid template along the
   874  	// way.
   875  	//
   876  	//   ... -> bsv# -> bbm0 -> bbm1 -> ... -> bbm#
   877  	// ---------------------------------------------------------------------
   878  
   879  	for i := uint16(0); i < coinbaseMaturity; i++ {
   880  		outs := g.OldestCoinbaseOuts()
   881  		blockName := fmt.Sprintf("bbm%d", i)
   882  		g.NextBlock(blockName, nil, outs[1:])
   883  		g.SaveTipCoinbaseOuts()
   884  		acceptedBlockTemplate()
   885  		g.AcceptTipBlock()
   886  	}
   887  	g.AssertTipHeight(uint32(stakeValidationHeight) + uint32(coinbaseMaturity))
   888  
   889  	// Collect spendable outputs into two different slices.  The outs slice
   890  	// is intended to be used for regular transactions that spend from the
   891  	// output, while the ticketOuts slice is intended to be used for stake
   892  	// ticket purchases.
   893  	var outs []*chaingen.SpendableOut
   894  	var ticketOuts [][]chaingen.SpendableOut
   895  	for i := uint16(0); i < coinbaseMaturity; i++ {
   896  		coinbaseOuts := g.OldestCoinbaseOuts()
   897  		outs = append(outs, &coinbaseOuts[0])
   898  		ticketOuts = append(ticketOuts, coinbaseOuts[1:])
   899  	}
   900  
   901  	// ---------------------------------------------------------------------
   902  	// Generate block templates that build on ancestors of the tip.
   903  	// ---------------------------------------------------------------------
   904  
   905  	// Start by building a few of blocks at current tip (value in parens
   906  	// is which output is spent):
   907  	//
   908  	//   ... -> b1(0) -> b2(1) -> b3(2)
   909  	g.NextBlock("b1", outs[0], ticketOuts[0])
   910  	g.AcceptTipBlock()
   911  
   912  	g.NextBlock("b2", outs[1], ticketOuts[1])
   913  	g.AcceptTipBlock()
   914  
   915  	g.NextBlock("b3", outs[2], ticketOuts[2])
   916  	g.AcceptTipBlock()
   917  
   918  	// Create a block template that forks from b1.  It should not be allowed
   919  	// since it is not the current tip or its parent.
   920  	//
   921  	//   ... -> b1(0) -> b2(1)  -> b3(2)
   922  	//               \-> b2at(1)
   923  	g.SetTip("b1")
   924  	g.NextBlock("b2at", outs[1], ticketOuts[1], changeNonce)
   925  	rejectedBlockTemplate(ErrInvalidTemplateParent)
   926  
   927  	// Create a block template that forks from b2.  It should be accepted
   928  	// because it is the current tip's parent.
   929  	//
   930  	//   ... -> b2(1) -> b3(2)
   931  	//               \-> b3at(2)
   932  	g.SetTip("b2")
   933  	g.NextBlock("b3at", outs[2], ticketOuts[2], changeNonce)
   934  	acceptedBlockTemplate()
   935  
   936  	// ---------------------------------------------------------------------
   937  	// Generate block templates that build on the tip's parent, but include
   938  	// invalid votes.
   939  	// ---------------------------------------------------------------------
   940  
   941  	// Create a block template that forks from b2 (the tip's parent) with
   942  	// votes that spend invalid tickets.
   943  	//
   944  	//   ... -> b2(1) -> b3(2)
   945  	//               \-> b3bt(2)
   946  	g.SetTip("b2")
   947  	g.NextBlock("b3bt", outs[2], ticketOuts[1], changeNonce)
   948  	rejectedBlockTemplate(ErrMissingTxOut)
   949  
   950  	// Same as before but based on the current tip.
   951  	//
   952  	//   ... -> b2(1) -> b3(2)
   953  	//                        \-> b4at(3)
   954  	g.SetTip("b3")
   955  	g.NextBlock("b4at", outs[3], ticketOuts[2], changeNonce)
   956  	rejectedBlockTemplate(ErrMissingTxOut)
   957  
   958  	// Create a block template that forks from b2 (the tip's parent) with
   959  	// a vote that pays too much.
   960  	//
   961  	//   ... -> b2(1) -> b3(2)
   962  	//               \-> b3ct(2)
   963  	g.SetTip("b2")
   964  	g.NextBlock("b3ct", outs[2], ticketOuts[2], func(b *wire.MsgBlock) {
   965  		changeNonce(b)
   966  		b.STransactions[0].TxOut[0].Value++
   967  	})
   968  	rejectedBlockTemplate(ErrSpendTooHigh)
   969  
   970  	// Same as before but based on the current tip.
   971  	//
   972  	//   ... -> b2(1) -> b3(2)
   973  	//                        \-> b4bt(3)
   974  	g.SetTip("b3")
   975  	g.NextBlock("b4bt", outs[3], ticketOuts[3], func(b *wire.MsgBlock) {
   976  		changeNonce(b)
   977  		b.STransactions[0].TxOut[0].Value++
   978  	})
   979  	rejectedBlockTemplate(ErrSpendTooHigh)
   980  
   981  	// ---------------------------------------------------------------------
   982  	// Generate block templates that build on the tip and its parent after a
   983  	// forced reorg.
   984  	// ---------------------------------------------------------------------
   985  
   986  	// Create a fork from b2.  There should not be a reorg since b3 was seen
   987  	// first.
   988  	//
   989  	//   ... -> b2(1) -> b3(2)
   990  	//               \-> b3a(2)
   991  	g.SetTip("b2")
   992  	g.NextBlock("b3a", outs[2], ticketOuts[2])
   993  	g.AcceptedToSideChainWithExpectedTip("b3")
   994  
   995  	// Force tip reorganization to b3a.
   996  	//
   997  	//   ... -> b2(1) -> b3a(2)
   998  	//               \-> b3(2)
   999  	g.ForceTipReorg("b3", "b3a")
  1000  	g.ExpectTip("b3a")
  1001  
  1002  	// Create a block template that forks from b2 (the tip's parent) and
  1003  	// ensure it is still accepted after the forced reorg.
  1004  	//
  1005  	//   ... -> b2(1) -> b3a(2)
  1006  	//               \-> b3dt(2)
  1007  	g.SetTip("b2")
  1008  	g.NextBlock("b3dt", outs[2], ticketOuts[2], changeNonce)
  1009  	acceptedBlockTemplate()
  1010  	g.ExpectTip("b3a") // Ensure chain tip didn't change.
  1011  
  1012  	// Create a block template that builds on the current tip and ensure it
  1013  	// it is still accepted after the forced reorg.
  1014  	//
  1015  	//   ... -> b2(1) -> b3a(2)
  1016  	//                         \-> b4ct(3)
  1017  	g.SetTip("b3a")
  1018  	g.NextBlock("b4ct", outs[3], ticketOuts[3], changeNonce)
  1019  	acceptedBlockTemplate()
  1020  }