github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/transactionpool/transactionpool_test.go (about)

     1  package transactionpool
     2  
     3  import (
     4  	"path/filepath"
     5  	"testing"
     6  
     7  	"SiaPrime/build"
     8  	"SiaPrime/crypto"
     9  	"SiaPrime/modules"
    10  	"SiaPrime/modules/consensus"
    11  	"SiaPrime/modules/gateway"
    12  	"SiaPrime/modules/miner"
    13  	"SiaPrime/modules/wallet"
    14  	"SiaPrime/types"
    15  	"gitlab.com/NebulousLabs/fastrand"
    16  )
    17  
    18  // A tpoolTester is used during testing to initialize a transaction pool and
    19  // useful helper modules.
    20  type tpoolTester struct {
    21  	cs        modules.ConsensusSet
    22  	gateway   modules.Gateway
    23  	tpool     *TransactionPool
    24  	miner     modules.TestMiner
    25  	wallet    modules.Wallet
    26  	walletKey crypto.TwofishKey
    27  
    28  	persistDir string
    29  }
    30  
    31  // blankTpoolTester returns a ready-to-use tpool tester, with all modules
    32  // initialized, without mining a block.
    33  func blankTpoolTester(name string) (*tpoolTester, error) {
    34  	// Initialize the modules.
    35  	testdir := build.TempDir(modules.TransactionPoolDir, name)
    36  	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	tp, err := New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	var key crypto.TwofishKey
    53  	fastrand.Read(key[:])
    54  	_, err = w.Encrypt(key)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	err = w.Unlock(key)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	// Assemble all of the objects into a tpoolTester
    68  	return &tpoolTester{
    69  		cs:        cs,
    70  		gateway:   g,
    71  		tpool:     tp,
    72  		miner:     m,
    73  		wallet:    w,
    74  		walletKey: key,
    75  
    76  		persistDir: testdir,
    77  	}, nil
    78  }
    79  
    80  // createTpoolTester returns a ready-to-use tpool tester, with all modules
    81  // initialized.
    82  func createTpoolTester(name string) (*tpoolTester, error) {
    83  	tpt, err := blankTpoolTester(name)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	// Mine blocks until there is money in the wallet.
    89  	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
    90  		b, _ := tpt.miner.FindBlock()
    91  		err = tpt.cs.AcceptBlock(b)
    92  		if err != nil {
    93  			return nil, err
    94  		}
    95  	}
    96  
    97  	return tpt, nil
    98  }
    99  
   100  // Close safely closes the tpoolTester, calling a panic in the event of an
   101  // error since there isn't a good way to errcheck when deferring a Close.
   102  func (tpt *tpoolTester) Close() error {
   103  	errs := []error{
   104  		tpt.cs.Close(),
   105  		tpt.gateway.Close(),
   106  		tpt.tpool.Close(),
   107  		tpt.miner.Close(),
   108  		tpt.wallet.Close(),
   109  	}
   110  	if err := build.JoinErrors(errs, "; "); err != nil {
   111  		panic(err)
   112  	}
   113  	return nil
   114  }
   115  
   116  // TestIntegrationNewNilInputs tries to trigger a panic with nil inputs.
   117  func TestIntegrationNewNilInputs(t *testing.T) {
   118  	if testing.Short() {
   119  		t.SkipNow()
   120  	}
   121  	// Create a gateway and consensus set.
   122  	testdir := build.TempDir(modules.TransactionPoolDir, t.Name())
   123  	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
   128  	if err != nil {
   129  		t.Fatal(err)
   130  	}
   131  	tpDir := filepath.Join(testdir, modules.TransactionPoolDir)
   132  
   133  	// Try all combinations of nil inputs.
   134  	_, err = New(nil, nil, tpDir)
   135  	if err == nil {
   136  		t.Error(err)
   137  	}
   138  	_, err = New(nil, g, tpDir)
   139  	if err != errNilCS {
   140  		t.Error(err)
   141  	}
   142  	_, err = New(cs, nil, tpDir)
   143  	if err != errNilGateway {
   144  		t.Error(err)
   145  	}
   146  	_, err = New(cs, g, tpDir)
   147  	if err != nil {
   148  		t.Error(err)
   149  	}
   150  }
   151  
   152  // TestGetTransaction verifies that the transaction pool's Transaction() method
   153  // works correctly.
   154  func TestGetTransaction(t *testing.T) {
   155  	if testing.Short() {
   156  		t.SkipNow()
   157  	}
   158  	tpt, err := createTpoolTester(t.Name())
   159  	if err != nil {
   160  		t.Fatal(err)
   161  	}
   162  	defer tpt.Close()
   163  
   164  	value := types.NewCurrency64(35e6)
   165  	fee := types.NewCurrency64(3e2)
   166  	emptyUH := types.UnlockConditions{}.UnlockHash()
   167  	txnBuilder, err := tpt.wallet.StartTransaction()
   168  	if err != nil {
   169  		t.Fatal(err)
   170  	}
   171  	err = txnBuilder.FundSiacoins(value)
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	txnBuilder.AddMinerFee(fee)
   176  	output := types.SiacoinOutput{
   177  		Value:      value.Sub(fee),
   178  		UnlockHash: emptyUH,
   179  	}
   180  	txnBuilder.AddSiacoinOutput(output)
   181  	txnSet, err := txnBuilder.Sign(true)
   182  	if err != nil {
   183  		t.Fatal(err)
   184  	}
   185  	childrenSet := []types.Transaction{{
   186  		SiacoinInputs: []types.SiacoinInput{{
   187  			ParentID: txnSet[len(txnSet)-1].SiacoinOutputID(0),
   188  		}},
   189  		SiacoinOutputs: []types.SiacoinOutput{{
   190  			Value:      value.Sub(fee),
   191  			UnlockHash: emptyUH,
   192  		}},
   193  	}}
   194  
   195  	superSet := append(txnSet, childrenSet...)
   196  	err = tpt.tpool.AcceptTransactionSet(superSet)
   197  	if err != nil {
   198  		t.Fatal(err)
   199  	}
   200  
   201  	targetTxn := childrenSet[0]
   202  	txn, parents, exists := tpt.tpool.Transaction(targetTxn.ID())
   203  	if !exists {
   204  		t.Fatal("transaction set did not exist")
   205  	}
   206  	if txn.ID() != targetTxn.ID() {
   207  		t.Fatal("returned the wrong transaction")
   208  	}
   209  	if len(parents) != len(txnSet) {
   210  		t.Fatal("transaction had wrong number of parents")
   211  	}
   212  	for i, txn := range txnSet {
   213  		if parents[i].ID() != txn.ID() {
   214  			t.Fatal("returned the wrong parent")
   215  		}
   216  	}
   217  }
   218  
   219  // TestBlockFeeEstimation checks that the fee estimation algorithm is reasonably
   220  // on target when the tpool is relying on blockchain based fee estimation.
   221  func TestFeeEstimation(t *testing.T) {
   222  	if testing.Short() || !build.VLONG {
   223  		t.Skip("Tpool is too slow to run this test regularly")
   224  	}
   225  	tpt, err := createTpoolTester(t.Name())
   226  	if err != nil {
   227  		t.Fatal(err)
   228  	}
   229  	defer tpt.Close()
   230  
   231  	// Prepare a bunch of outputs for a series of graphs to fill up the
   232  	// transaction pool.
   233  	graphLens := 400                                                                     // 80 kb per graph
   234  	numGraphs := int(types.BlockSizeLimit) * blockFeeEstimationDepth / (graphLens * 206) // Enough to fill 'estimation depth' blocks.
   235  	graphFund := types.SiacoinPrecision.Mul64(1000)
   236  	var outputs []types.SiacoinOutput
   237  	for i := 0; i < numGraphs+1; i++ {
   238  		outputs = append(outputs, types.SiacoinOutput{
   239  			UnlockHash: types.UnlockConditions{}.UnlockHash(),
   240  			Value:      graphFund,
   241  		})
   242  	}
   243  	txns, err := tpt.wallet.SendSiacoinsMulti(outputs)
   244  	if err != nil {
   245  		t.Error(err)
   246  	}
   247  
   248  	// Mine the graph setup in the consensus set so that the graph outputs are
   249  	// distinct transaction sets.
   250  	_, err = tpt.miner.AddBlock()
   251  	if err != nil {
   252  		t.Fatal(err)
   253  	}
   254  
   255  	// Create all of the graphs.
   256  	finalTxn := txns[len(txns)-1]
   257  	var graphs [][]types.Transaction
   258  	for i := 0; i < numGraphs; i++ {
   259  		var edges []types.TransactionGraphEdge
   260  		var cumFee types.Currency
   261  		for j := 0; j < graphLens; j++ {
   262  			fee := types.SiacoinPrecision.Mul64(uint64(j + i + 1)).Div64(200)
   263  			cumFee = cumFee.Add(fee)
   264  			edges = append(edges, types.TransactionGraphEdge{
   265  				Dest:   j + 1,
   266  				Fee:    fee,
   267  				Source: j,
   268  				Value:  graphFund.Sub(cumFee),
   269  			})
   270  		}
   271  		graph, err := types.TransactionGraph(finalTxn.SiacoinOutputID(uint64(i)), edges)
   272  		if err != nil {
   273  			t.Fatal(err)
   274  		}
   275  		graphs = append(graphs, graph)
   276  	}
   277  
   278  	// One block at a time, add graphs to the tpool and blockchain. Then check
   279  	// the median fee estimation and see that it's the right value.
   280  	var prevMin types.Currency
   281  	for i := 0; i < blockFeeEstimationDepth; i++ {
   282  		// Insert enough graphs to fill a block.
   283  		for j := 0; j < numGraphs/blockFeeEstimationDepth; j++ {
   284  			err = tpt.tpool.AcceptTransactionSet(graphs[0])
   285  			if err != nil {
   286  				t.Fatal(err)
   287  			}
   288  			graphs = graphs[1:]
   289  		}
   290  
   291  		// Add a block to the transaction pool.
   292  		_, err = tpt.miner.AddBlock()
   293  		if err != nil {
   294  			t.Fatal(err)
   295  		}
   296  
   297  		// Check that max is always greater than min.
   298  		min, max := tpt.tpool.FeeEstimation()
   299  		if min.Cmp(max) > 0 {
   300  			t.Error("max fee is less than min fee estimation")
   301  		}
   302  
   303  		// If we're over halfway through the depth, the suggested fee should
   304  		// start to exceed the default.
   305  		if i > blockFeeEstimationDepth/2 {
   306  			if min.Cmp(minEstimation) <= 0 {
   307  				t.Error("fee estimation does not seem to be increasing")
   308  			}
   309  			if min.Cmp(prevMin) <= 0 {
   310  				t.Error("fee estimation does not seem to be increasing")
   311  			}
   312  		}
   313  		prevMin = min
   314  
   315  		// Reset the tpool to verify that the persist structures are
   316  		// functioning.
   317  		//
   318  		// TODO: For some reason, closing and re-opeining the tpool results in
   319  		// incredible performance penalties.
   320  		/*
   321  			err = tpt.tpool.Close()
   322  			if err != nil {
   323  				t.Fatal(err)
   324  			}
   325  			tpt.tpool, err = New(tpt.cs, tpt.gateway, tpt.persistDir)
   326  			if err != nil {
   327  				t.Fatal(err)
   328  			}
   329  		*/
   330  	}
   331  
   332  	// Mine a few blocks and then check that the fee estimation has returned to
   333  	// minimum as congestion clears up.
   334  	for i := 0; i < (blockFeeEstimationDepth/2)+1; i++ {
   335  		_, err = tpt.miner.AddBlock()
   336  		if err != nil {
   337  			t.Fatal(err)
   338  		}
   339  	}
   340  	min, _ := tpt.tpool.FeeEstimation()
   341  	if !(min.Cmp(minEstimation) == 0) {
   342  		t.Error("fee estimator does not seem to be reducing with empty blocks.")
   343  	}
   344  }
   345  
   346  // TestTpoolScalability fills the whole transaction pool with complex
   347  // transactions, then mines enough blocks to empty it out. Running sequentially,
   348  // the test should take less than 250ms per mb that the transaction pool fills
   349  // up, and less than 250ms per mb to empty out - indicating linear scalability
   350  // and tolerance for a larger pool size.
   351  func TestTpoolScalability(t *testing.T) {
   352  	if testing.Short() || !build.VLONG {
   353  		t.Skip("Tpool is too slow to run this test regularly")
   354  	}
   355  	tpt, err := createTpoolTester(t.Name())
   356  	if err != nil {
   357  		t.Fatal(err)
   358  	}
   359  	defer tpt.Close()
   360  
   361  	// Mine a few more blocks to get some extra funding.
   362  	for i := 0; i < 3; i++ {
   363  		_, err := tpt.miner.AddBlock()
   364  		if err != nil {
   365  			t.Fatal(err)
   366  		}
   367  	}
   368  
   369  	// Prepare a bunch of outputs for a series of graphs to fill up the
   370  	// transaction pool.
   371  	rows := 10                                         // needs to factor into exclusively '2's and '5's.
   372  	graphSize := 11796                                 // Measured with logging. Change if 'rows' changes.
   373  	numGraphs := TransactionPoolSizeTarget / graphSize // Enough to fill the transaction pool.
   374  	graphFund := types.SiacoinPrecision.Mul64(2000)
   375  	var outputs []types.SiacoinOutput
   376  	for i := 0; i < numGraphs+1; i++ {
   377  		outputs = append(outputs, types.SiacoinOutput{
   378  			UnlockHash: types.UnlockConditions{}.UnlockHash(),
   379  			Value:      graphFund,
   380  		})
   381  	}
   382  	txns, err := tpt.wallet.SendSiacoinsMulti(outputs)
   383  	if err != nil {
   384  		t.Error(err)
   385  	}
   386  
   387  	// Mine the graph setup in the consensus set so that the graph outputs are
   388  	// distinct transaction sets.
   389  	_, err = tpt.miner.AddBlock()
   390  	if err != nil {
   391  		t.Fatal(err)
   392  	}
   393  
   394  	// Create all of the graphs.
   395  	finalTxn := txns[len(txns)-1]
   396  	var graphs [][]types.Transaction
   397  	for i := 0; i < numGraphs; i++ {
   398  		var edges []types.TransactionGraphEdge
   399  
   400  		// Create the root of the graph.
   401  		feeValues := types.SiacoinPrecision
   402  		firstRowValues := graphFund.Sub(feeValues.Mul64(uint64(rows))).Div64(uint64(rows))
   403  		for j := 0; j < rows; j++ {
   404  			edges = append(edges, types.TransactionGraphEdge{
   405  				Dest:   j + 1,
   406  				Fee:    types.SiacoinPrecision,
   407  				Source: 0,
   408  				Value:  firstRowValues,
   409  			})
   410  		}
   411  
   412  		// Create each row of the graph.
   413  		var firstNodeValue types.Currency
   414  		nodeIndex := 1
   415  		for j := 0; j < rows; j++ {
   416  			// Create the first node in the row, which has an increasing
   417  			// balance.
   418  			rowValue := firstRowValues.Sub(types.SiacoinPrecision.Mul64(uint64(j + 1)))
   419  			firstNodeValue = firstNodeValue.Add(rowValue)
   420  			edges = append(edges, types.TransactionGraphEdge{
   421  				Dest:   nodeIndex + (rows - j),
   422  				Fee:    types.SiacoinPrecision,
   423  				Source: nodeIndex,
   424  				Value:  firstNodeValue,
   425  			})
   426  			nodeIndex++
   427  
   428  			// Create the remaining nodes in this row.
   429  			for k := j + 1; k < rows; k++ {
   430  				edges = append(edges, types.TransactionGraphEdge{
   431  					Dest:   nodeIndex + (rows - (j + 1)),
   432  					Fee:    types.SiacoinPrecision,
   433  					Source: nodeIndex,
   434  					Value:  rowValue,
   435  				})
   436  				nodeIndex++
   437  			}
   438  		}
   439  
   440  		// Build the graph and add it to the stack of graphs.
   441  		graph, err := types.TransactionGraph(finalTxn.SiacoinOutputID(uint64(i)), edges)
   442  		if err != nil {
   443  			t.Fatal(err)
   444  		}
   445  		graphs = append(graphs, graph)
   446  	}
   447  
   448  	// Add all of the root transactions to the blockchain to throw off the
   449  	// parent math off for the transaction pool.
   450  	for _, graph := range graphs {
   451  		err := tpt.tpool.AcceptTransactionSet([]types.Transaction{graph[0]})
   452  		if err != nil {
   453  			t.Fatal(err)
   454  		}
   455  	}
   456  	_, err = tpt.miner.AddBlock()
   457  	if err != nil {
   458  		t.Fatal(err)
   459  	}
   460  
   461  	// Add all of the transactions in each graph into the tpool, one transaction
   462  	// at a time, interweaved, chaotically.
   463  	for i := 1; i < len(graphs[0]); i++ {
   464  		for j := 0; j < len(graphs); j++ {
   465  			err := tpt.tpool.AcceptTransactionSet([]types.Transaction{graphs[j][i]})
   466  			if err != nil {
   467  				t.Fatal(err, i, j)
   468  			}
   469  		}
   470  	}
   471  
   472  	// Mine blocks until the tpool is gone.
   473  	for tpt.tpool.transactionListSize > 0 {
   474  		_, err := tpt.miner.AddBlock()
   475  		if err != nil {
   476  			t.Fatal(err)
   477  		}
   478  	}
   479  }
   480  
   481  // TestHeapFees creates a large number of transaction graphs with increasing fee
   482  // value. Then it checks that those sets with higher value transaction fees are
   483  // prioritized for placement in blocks.
   484  func TestHeapFees(t *testing.T) {
   485  	if testing.Short() || !build.VLONG {
   486  		t.SkipNow()
   487  	}
   488  	tpt, err := createTpoolTester(t.Name())
   489  	if err != nil {
   490  		t.Fatal(err)
   491  	}
   492  	defer tpt.Close()
   493  
   494  	// Mine a few more blocks to get some extra funding.
   495  	for i := 0; i < 4; i++ {
   496  		_, err := tpt.miner.AddBlock()
   497  		if err != nil {
   498  			t.Fatal(err)
   499  		}
   500  	}
   501  
   502  	// Create transaction graph setup.
   503  	coinFrac := types.SiacoinPrecision
   504  	numGraphs := 110
   505  	graphFund := coinFrac.Mul64(12210)
   506  	var outputs []types.SiacoinOutput
   507  	for i := 0; i < numGraphs; i++ {
   508  		outputs = append(outputs, types.SiacoinOutput{
   509  			UnlockHash: types.UnlockConditions{}.UnlockHash(),
   510  			Value:      graphFund,
   511  		})
   512  	}
   513  	txns, err := tpt.wallet.SendSiacoinsMulti(outputs)
   514  	if err != nil {
   515  		t.Error(err)
   516  	}
   517  	// Mine the graph setup in the consensus set so that the graph outputs are
   518  	// transaction sets. This guarantees that the parent of every graph will be
   519  	// its own output.
   520  	_, err = tpt.miner.AddBlock()
   521  	if err != nil {
   522  		t.Fatal(err)
   523  	}
   524  	finalTxn := txns[len(txns)-1]
   525  	// For each output, create 250 transactions
   526  	var graphs [][]types.Transaction
   527  	for i := 0; i < numGraphs; i++ {
   528  		var edges []types.TransactionGraphEdge
   529  		var cumFee types.Currency
   530  		for j := 0; j < numGraphs; j++ {
   531  			fee := coinFrac.Mul64(uint64((j + 1)))
   532  			cumFee = cumFee.Add(fee)
   533  			edges = append(edges, types.TransactionGraphEdge{
   534  				Dest:   j + 1,
   535  				Fee:    fee,
   536  				Source: 0,
   537  				Value:  fee,
   538  			})
   539  		}
   540  		for k := 0; k < numGraphs; k++ {
   541  			fee := coinFrac.Mul64(uint64(k + 1)).Div64(2)
   542  			cumFee = cumFee.Add(fee)
   543  			edges = append(edges, types.TransactionGraphEdge{
   544  				Dest:   k + 251,
   545  				Fee:    fee,
   546  				Source: k + 1,
   547  				Value:  fee,
   548  			})
   549  		}
   550  		graph, err := types.TransactionGraph(finalTxn.SiacoinOutputID(uint64(i)), edges)
   551  		if err != nil {
   552  			t.Fatal(err)
   553  		}
   554  		graphs = append(graphs, graph)
   555  
   556  	}
   557  	// Accept the parent node of each graph so that its outputs we can test
   558  	// spending its outputs after mining the next block.
   559  	for _, graph := range graphs {
   560  		err := tpt.tpool.AcceptTransactionSet([]types.Transaction{graph[0]})
   561  		if err != nil {
   562  			t.Fatal(err)
   563  		}
   564  	}
   565  	block, err := tpt.miner.AddBlock()
   566  	if err != nil {
   567  		t.Fatal(err)
   568  	}
   569  
   570  	// Now accept all the other nodes of each graph.
   571  	for _, graph := range graphs {
   572  		for _, txn := range graph[1:] {
   573  			err := tpt.tpool.AcceptTransactionSet([]types.Transaction{txn})
   574  			if err != nil {
   575  				t.Fatal(err)
   576  			}
   577  		}
   578  	}
   579  	// Now we mine 2 blocks in sequence and check that higher fee transactions
   580  	// show up to the first block.
   581  	block, err = tpt.miner.AddBlock()
   582  	if err != nil {
   583  		t.Fatal(err)
   584  	}
   585  
   586  	var totalFee1 types.Currency
   587  	expectedFee1 := coinFrac.Mul64(321915)
   588  
   589  	// Add up total fees
   590  	numTxns1 := 0
   591  	maxFee1 := types.SiacoinPrecision.Div64(1000000)
   592  	minFee1 := types.SiacoinPrecision.Mul64(1000000)
   593  	for _, txn := range block.Transactions {
   594  		for _, fee := range txn.MinerFees {
   595  			if fee.Cmp(maxFee1) >= 0 {
   596  				maxFee1 = fee
   597  			}
   598  			if fee.Cmp(minFee1) <= 0 {
   599  				minFee1 = fee
   600  			}
   601  			totalFee1 = totalFee1.Add(fee)
   602  			numTxns1++
   603  		}
   604  	}
   605  	avgFee1 := totalFee1.Div64(uint64(numTxns1))
   606  	if totalFee1.Cmp(expectedFee1) != 0 {
   607  		t.Error("totalFee1 different than expected fee.", totalFee1.String(), expectedFee1.String())
   608  		//t.Log(totalFee1.Sub(expectedFee1).HumanString())
   609  
   610  	}
   611  
   612  	// Mine the next block so we can check the transactions inside
   613  	block, err = tpt.miner.AddBlock()
   614  	if err != nil {
   615  		t.Fatal(err)
   616  	}
   617  
   618  	var totalFee2 types.Currency
   619  	expectedFee2 := coinFrac.Mul64(13860)
   620  
   621  	// Add up total fees
   622  	numTxns2 := 0
   623  	maxFee2 := types.SiacoinPrecision.Div64(1000000)
   624  	minFee2 := types.SiacoinPrecision.Mul64(1000000)
   625  	for _, txn := range block.Transactions {
   626  		for _, fee := range txn.MinerFees {
   627  			if fee.Cmp(maxFee2) >= 0 {
   628  				maxFee2 = fee
   629  			}
   630  			if fee.Cmp(minFee2) <= 0 {
   631  				minFee2 = fee
   632  			}
   633  			totalFee2 = totalFee2.Add(fee)
   634  			numTxns2++
   635  		}
   636  	}
   637  	avgFee2 := totalFee2.Div64(uint64(numTxns2))
   638  	if totalFee2.Cmp(expectedFee2) != 0 {
   639  		t.Error("totalFee2 different than expected fee.", totalFee2.String(), expectedFee2.String())
   640  		//t.Log(totalFee2.Sub(expectedFee2).HumanString())
   641  	}
   642  	if avgFee1.Cmp(avgFee2) <= 0 {
   643  		t.Error("Expected average fee from first block to be greater than average fee from second block.")
   644  	}
   645  	if totalFee1.Cmp(totalFee2) <= 0 {
   646  		t.Error("Expected total fee from first block to be greater than total fee from second block.")
   647  	}
   648  	if numTxns1 < numTxns2 {
   649  		t.Error("Expected more transactions in the first block than second block.")
   650  	}
   651  	if maxFee1.Cmp(maxFee2) <= 0 {
   652  		t.Error("Expected highest fee from first block to be greater than highest fee from second block.")
   653  	}
   654  	if minFee1.Cmp(maxFee2) < 0 {
   655  		t.Error("Expected lowest fee from first block to be greater than or equal to than highest fee from second block.")
   656  	}
   657  	if maxFee1.Cmp(minFee1) <= 0 {
   658  		t.Error("Expected highest fee from first block to be greater than lowest fee from first block.")
   659  	}
   660  	if maxFee2.Cmp(minFee2) <= 0 {
   661  		t.Error("Expected highest fee from second block to be greater than lowest fee from second block.")
   662  	}
   663  }
   664  
   665  // TestBigTpool creates 3 chunks of 10,000 transactions such that the second
   666  // chunk has much greater fees than the first chunk, and the third chunk has
   667  // much greater fees than the second chunk. The fees in each chunk are also
   668  // increasing. Then, to induce move lots of movement of transactions in and out
   669  // of the miner's unsolved block, we make the tester accept the transactions by
   670  // interleaving subsets of the chunks. We then check that the miner produces the
   671  // expected sequence of blocks.
   672  func TestBigTpool(t *testing.T) {
   673  	if testing.Short() || !build.VLONG {
   674  		t.SkipNow()
   675  	}
   676  	tpt, err := createTpoolTester(t.Name())
   677  	if err != nil {
   678  		t.Fatal(err)
   679  	}
   680  	defer tpt.Close()
   681  
   682  	// Mine a few more blocks to get some extra funding.
   683  	for i := 0; i < 4; i++ {
   684  		_, err := tpt.miner.AddBlock()
   685  		if err != nil {
   686  			t.Fatal(err)
   687  		}
   688  	}
   689  
   690  	// Create transaction graph setup.
   691  	coinFrac := types.SiacoinPrecision.Div64(1)
   692  	feeFrac := types.SiacoinPrecision.Div64(10)
   693  	numGraphsPerChunk := 1000
   694  	transactionSetSizes := []int{1, 2, 5, 10, 20}
   695  
   696  	var outputs1 []types.SiacoinOutput
   697  	var outputs2 []types.SiacoinOutput
   698  	var outputs3 []types.SiacoinOutput
   699  
   700  	// Create outputs to be spent in the first chunk.
   701  	for i := 1; i <= numGraphsPerChunk; i++ {
   702  		value := coinFrac.Mul64(25).Add(feeFrac.Mul64(uint64(i))).Mul64(2)
   703  		outputs1 = append(outputs1, types.SiacoinOutput{
   704  			UnlockHash: types.UnlockConditions{}.UnlockHash(),
   705  			Value:      value,
   706  		})
   707  	}
   708  	// There's so many outputs that they need to be put into multiple
   709  	// transactions. We can fit around 500 outputs per transaction.
   710  	var outputTxns1 [][]types.Transaction
   711  	for i := 0; i < numGraphsPerChunk/500; i++ {
   712  		txns, err := tpt.wallet.SendSiacoinsMulti(outputs1[500*i : (500*i)+500])
   713  		if err != nil {
   714  			t.Error(err)
   715  		}
   716  		outputTxns1 = append(outputTxns1, txns)
   717  	}
   718  
   719  	counter := 1
   720  	var graphs [][]types.Transaction
   721  	for _, output := range outputTxns1 {
   722  		finalTxn := output[len(output)-1]
   723  		for i := 0; i < 500; i++ { // 500 is the the number of outputs
   724  			var edges []types.TransactionGraphEdge
   725  			totalValue := coinFrac.Mul64(25).Add(feeFrac.Mul64(uint64(counter))).Mul64(2)
   726  			setSize := transactionSetSizes[fastrand.Intn(5)] // 1, 2, 5, 10, or 20 with equal probability
   727  			txTotalVal := totalValue.Div64(uint64(setSize))
   728  			txFee := txTotalVal.Div64(5)
   729  			txVal := txTotalVal.Sub(txFee)
   730  			txFee2 := txVal.Div64(2)
   731  			txVal2 := txVal.Sub(txFee2)
   732  
   733  			for i := 0; i < setSize; i++ {
   734  				edges = append(edges, types.TransactionGraphEdge{
   735  					Dest:   i + 1,
   736  					Fee:    txFee,
   737  					Source: 0,
   738  					Value:  txVal,
   739  				})
   740  			}
   741  			for i := 0; i < setSize; i++ {
   742  				edges = append(edges, types.TransactionGraphEdge{
   743  					Dest:   i + 1 + setSize,
   744  					Fee:    txFee2,
   745  					Source: i + 1,
   746  					Value:  txVal2,
   747  				})
   748  			}
   749  			graph, err := types.TransactionGraph(finalTxn.SiacoinOutputID(uint64(i)), edges)
   750  			if err != nil {
   751  				t.Fatal(err)
   752  			}
   753  			graphs = append(graphs, graph)
   754  			counter++
   755  		}
   756  	}
   757  	////////////////////////////////////////////////////////////////////////////
   758  	// Chunk 2
   759  	////////////////////////////////////////////////////////////////////////////
   760  	// Create outputs to be spent in the second chunk.
   761  	for i := 1; i <= numGraphsPerChunk; i++ {
   762  		value := coinFrac.Mul64(60).Add(feeFrac.Mul64(uint64(i))).Mul64(2)
   763  		outputs2 = append(outputs2, types.SiacoinOutput{
   764  			UnlockHash: types.UnlockConditions{}.UnlockHash(),
   765  			Value:      value,
   766  		})
   767  	}
   768  	// There's so many outputs that they need to be put into multiple
   769  	// transactions. We can fit around 500 outputs per transaction.
   770  	var outputTxns2 [][]types.Transaction
   771  	for i := 0; i < numGraphsPerChunk/500; i++ {
   772  		txns, err := tpt.wallet.SendSiacoinsMulti(outputs2[500*i : (500*i)+500])
   773  		if err != nil {
   774  			t.Error(err)
   775  		}
   776  		outputTxns2 = append(outputTxns2, txns)
   777  	}
   778  
   779  	counter = 1
   780  	var graphs2 [][]types.Transaction
   781  	for _, output := range outputTxns2 {
   782  		finalTxn := output[len(output)-1]
   783  		for i := 0; i < 500; i++ { // 500 is the the number of outputs.
   784  			var edges []types.TransactionGraphEdge
   785  			totalValue := coinFrac.Mul64(60).Add(feeFrac.Mul64(uint64(counter))).Mul64(2)
   786  			setSize := transactionSetSizes[fastrand.Intn(5)] // 1, 2, 5, 10, or 20 with equal probability
   787  			txTotalVal := totalValue.Div64(uint64(setSize))
   788  			txFee := txTotalVal.Div64(5)
   789  			txVal := txTotalVal.Sub(txFee)
   790  			txFee2 := txVal.Div64(2)
   791  			txVal2 := txVal.Sub(txFee2)
   792  
   793  			for i := 0; i < setSize; i++ {
   794  				edges = append(edges, types.TransactionGraphEdge{
   795  					Dest:   i + 1,
   796  					Fee:    txFee,
   797  					Source: 0,
   798  					Value:  txVal,
   799  				})
   800  			}
   801  			for i := 0; i < setSize; i++ {
   802  				edges = append(edges, types.TransactionGraphEdge{
   803  					Dest:   i + 1 + setSize,
   804  					Fee:    txFee2,
   805  					Source: i + 1,
   806  					Value:  txVal2,
   807  				})
   808  			}
   809  			graph, err := types.TransactionGraph(finalTxn.SiacoinOutputID(uint64(i)), edges)
   810  			if err != nil {
   811  				t.Fatal(err)
   812  			}
   813  			graphs2 = append(graphs2, graph)
   814  			counter++
   815  		}
   816  	}
   817  	////////////////////////////////////////////////////////////////////////////
   818  	// Chunk 3
   819  	////////////////////////////////////////////////////////////////////////////
   820  	// Create outputs to be spent in the third chunk.
   821  	for i := 1; i <= numGraphsPerChunk; i++ {
   822  		value := coinFrac.Mul64(110).Add(feeFrac.Mul64(uint64(i))).Mul64(2)
   823  		outputs3 = append(outputs3, types.SiacoinOutput{
   824  			UnlockHash: types.UnlockConditions{}.UnlockHash(),
   825  			Value:      value,
   826  		})
   827  	}
   828  	// There's so many outputs that they need to be put into multiple
   829  	// transactions. We can fit around 500 outputs per transaction.
   830  	var outputTxns3 [][]types.Transaction
   831  	for i := 0; i < numGraphsPerChunk/500; i++ {
   832  		txns, err := tpt.wallet.SendSiacoinsMulti(outputs3[500*i : (500*i)+500])
   833  		if err != nil {
   834  			t.Error(err)
   835  		}
   836  		outputTxns3 = append(outputTxns3, txns)
   837  	}
   838  
   839  	counter = 1
   840  	var graphs3 [][]types.Transaction
   841  	for _, output := range outputTxns3 {
   842  		finalTxn := output[len(output)-1]
   843  		for i := 0; i < 500; i++ { // 500 is the the number of outputs.
   844  			var edges []types.TransactionGraphEdge
   845  			totalValue := coinFrac.Mul64(110).Add(feeFrac.Mul64(uint64(counter))).Mul64(2)
   846  			setSize := transactionSetSizes[fastrand.Intn(5)] // 1, 2, 5, 10, or 20 with equal probability
   847  			txTotalVal := totalValue.Div64(uint64(setSize))
   848  			txFee := txTotalVal.Div64(5)
   849  			txVal := txTotalVal.Sub(txFee)
   850  			txFee2 := txVal.Div64(2)
   851  			txVal2 := txVal.Sub(txFee2)
   852  
   853  			for i := 0; i < setSize; i++ {
   854  				edges = append(edges, types.TransactionGraphEdge{
   855  					Dest:   i + 1,
   856  					Fee:    txFee,
   857  					Source: 0,
   858  					Value:  txVal,
   859  				})
   860  			}
   861  			for i := 0; i < setSize; i++ {
   862  				edges = append(edges, types.TransactionGraphEdge{
   863  					Dest:   i + 1 + setSize,
   864  					Fee:    txFee2,
   865  					Source: i + 1,
   866  					Value:  txVal2,
   867  				})
   868  			}
   869  			graph, err := types.TransactionGraph(finalTxn.SiacoinOutputID(uint64(i)), edges)
   870  			if err != nil {
   871  				t.Fatal(err)
   872  			}
   873  			graphs3 = append(graphs3, graph)
   874  			counter++
   875  		}
   876  	}
   877  
   878  	block, err := tpt.miner.AddBlock()
   879  	if err != nil {
   880  		t.Fatal(err)
   881  	}
   882  
   883  	// Accept the parent node of each graph so that its outputs we can test
   884  	// spending its outputs after mining the next block.
   885  	c := 0
   886  	for _, graph := range graphs {
   887  		err := tpt.tpool.AcceptTransactionSet([]types.Transaction{graph[0]})
   888  		if err != nil {
   889  			t.Fatal(err)
   890  		}
   891  		c++
   892  	}
   893  	_, err = tpt.miner.AddBlock()
   894  	if err != nil {
   895  		t.Fatal(err)
   896  	}
   897  	for _, graph := range graphs2 {
   898  		err := tpt.tpool.AcceptTransactionSet([]types.Transaction{graph[0]})
   899  		if err != nil {
   900  			t.Fatal(err)
   901  		}
   902  	}
   903  	_, err = tpt.miner.AddBlock()
   904  	if err != nil {
   905  		t.Fatal(err)
   906  	}
   907  	for _, graph := range graphs3 {
   908  		err := tpt.tpool.AcceptTransactionSet([]types.Transaction{graph[0]})
   909  		if err != nil {
   910  			t.Fatal(err)
   911  		}
   912  	}
   913  	_, err = tpt.miner.AddBlock()
   914  	if err != nil {
   915  		t.Fatal(err)
   916  	}
   917  
   918  	var totalGraph [][]types.Transaction
   919  	totalGraph = append(totalGraph, graphs...)
   920  	totalGraph = append(totalGraph, graphs2...)
   921  	totalGraph = append(totalGraph, graphs3...)
   922  
   923  	//  Add transactions one megabyte at a time.
   924  	firstMix := fastrand.Perm(670) // around 670 graphs make 1MB of transactions
   925  	secondMix := fastrand.Perm(670)
   926  	thirdMix := fastrand.Perm(670)
   927  	fourthMix := fastrand.Perm(670)
   928  	fifthMix := fastrand.Perm(320)
   929  
   930  	for _, i := range firstMix {
   931  		graph := totalGraph[i]
   932  		for _, txn := range graph[1:] {
   933  			err := tpt.tpool.AcceptTransactionSet([]types.Transaction{txn})
   934  			if err != nil {
   935  				t.Fatal(err)
   936  			}
   937  		}
   938  	}
   939  	for _, i := range secondMix {
   940  		graph := totalGraph[i+670]
   941  		for _, txn := range graph[1:] {
   942  			err := tpt.tpool.AcceptTransactionSet([]types.Transaction{txn})
   943  			if err != nil {
   944  				t.Fatal(err)
   945  			}
   946  		}
   947  	}
   948  	for _, i := range thirdMix {
   949  		graph := totalGraph[i+670+670]
   950  		for _, txn := range graph[1:] {
   951  			err := tpt.tpool.AcceptTransactionSet([]types.Transaction{txn})
   952  			if err != nil {
   953  				t.Fatal(err)
   954  			}
   955  		}
   956  	}
   957  	for _, i := range fourthMix {
   958  		graph := totalGraph[i+670+670+670]
   959  		for _, txn := range graph[1:] {
   960  			err := tpt.tpool.AcceptTransactionSet([]types.Transaction{txn})
   961  			if err != nil {
   962  				t.Fatal(err)
   963  			}
   964  		}
   965  	}
   966  	for _, i := range fifthMix {
   967  		graph := totalGraph[i+670+670+670+670]
   968  		for _, txn := range graph[1:] {
   969  			err := tpt.tpool.AcceptTransactionSet([]types.Transaction{txn})
   970  			if err != nil {
   971  				t.Fatal(err)
   972  			}
   973  		}
   974  	}
   975  
   976  	block, err = tpt.miner.AddBlock()
   977  	if err != nil {
   978  		t.Fatal(err)
   979  	}
   980  	var totalFee1 types.Currency
   981  	minFee1 := types.SiacoinPrecision.Mul64(10000000000) // All the fees are much smaller than 1 SC.
   982  	for _, tx := range block.Transactions {
   983  		for _, fee := range tx.MinerFees {
   984  			totalFee1 = totalFee1.Add(fee)
   985  			if fee.Cmp(minFee1) < 0 {
   986  				minFee1 = fee
   987  			}
   988  		}
   989  	}
   990  
   991  	block, err = tpt.miner.AddBlock()
   992  	if err != nil {
   993  		t.Fatal(err)
   994  	}
   995  	var totalFee2 types.Currency
   996  	maxFee2 := types.ZeroCurrency
   997  	minFee2 := types.SiacoinPrecision.Mul64(10000000000) // All the fees are much smaller than 1 SC.
   998  	for _, tx := range block.Transactions {
   999  		for _, fee := range tx.MinerFees {
  1000  			totalFee2 = totalFee2.Add(fee)
  1001  			if fee.Cmp(minFee2) < 0 {
  1002  				minFee2 = fee
  1003  			}
  1004  			if fee.Cmp(maxFee2) > 0 {
  1005  				maxFee2 = fee
  1006  			}
  1007  		}
  1008  	}
  1009  
  1010  	block, err = tpt.miner.AddBlock()
  1011  	if err != nil {
  1012  		t.Fatal(err)
  1013  	}
  1014  	var totalFee3 types.Currency
  1015  	maxFee3 := types.ZeroCurrency
  1016  	minFee3 := types.SiacoinPrecision.Mul64(10000000000) // All the fees are much smaller than 1 SC.
  1017  	for _, tx := range block.Transactions {
  1018  		for _, fee := range tx.MinerFees {
  1019  			totalFee3 = totalFee3.Add(fee)
  1020  			if fee.Cmp(minFee3) < 0 {
  1021  				minFee3 = fee
  1022  			}
  1023  			if fee.Cmp(maxFee3) > 0 {
  1024  				maxFee3 = fee
  1025  			}
  1026  		}
  1027  	}
  1028  
  1029  	block, err = tpt.miner.AddBlock()
  1030  	if err != nil {
  1031  		t.Fatal(err)
  1032  	}
  1033  	totalFee4 := types.ZeroCurrency
  1034  	maxFee4 := types.ZeroCurrency
  1035  	for _, tx := range block.Transactions {
  1036  		for _, fee := range tx.MinerFees {
  1037  			totalFee4 = totalFee4.Add(fee)
  1038  			if fee.Cmp(maxFee4) > 0 {
  1039  				maxFee4 = fee
  1040  			}
  1041  		}
  1042  	}
  1043  
  1044  	// Check that the total fees from each block are decreasing.
  1045  	if totalFee1.Cmp(totalFee2) < 0 {
  1046  		t.Error("Expected fees from the first block to be greater than from the second block.")
  1047  	}
  1048  	if totalFee2.Cmp(totalFee3) < 0 {
  1049  		t.Error("Expected fees from the second block to be greater than from the third block.")
  1050  	}
  1051  	if totalFee3.Cmp(totalFee4) < 0 {
  1052  		t.Error("Expected fees from the third block to be greater than from the fourth block.")
  1053  	}
  1054  	// Check that the min fees from each block is greater than or equal to the max fee for
  1055  	// the block mined after it.
  1056  	if minFee1.Cmp(maxFee2) < 0 {
  1057  		t.Error("Expected min fee from the first block to be greater than the max fee from the second block.")
  1058  	}
  1059  	if minFee2.Cmp(maxFee3) < 0 {
  1060  		t.Error("Expected min fee from the second block to be greater than the max fee from the third block.")
  1061  	}
  1062  	if minFee3.Cmp(maxFee4) < 0 {
  1063  		t.Error("Expected min fee from the third block to be greater than the max fee from the fourth block.")
  1064  	}
  1065  }
  1066  
  1067  // TestTpoolRevert tests proper transaction pool reverts. In this test we create
  1068  // two testers who set up the same outputs for a group of transaction sets. Then
  1069  // one accepts a small subset of those sets, mines a block, and passes that
  1070  // block to the other tester. Then that tester mines two blocks. We check that
  1071  // the total fee for all 3 blocks is as expected, and that the last block only
  1072  // has transactions with fees less than those in the block prior.
  1073  func TestTpoolRevert(t *testing.T) {
  1074  	if testing.Short() || !build.VLONG {
  1075  		t.SkipNow()
  1076  	}
  1077  
  1078  	tpt, err := blankTpoolTester(t.Name())
  1079  	if err != nil {
  1080  		t.Fatal(err)
  1081  	}
  1082  	tpt2, err := blankTpoolTester(t.Name() + "2")
  1083  	if err != nil {
  1084  		t.Fatal(err)
  1085  	}
  1086  	defer tpt.Close()
  1087  	defer tpt2.Close()
  1088  
  1089  	// Mine blocks until there is money in the wallet. We have to make sure they
  1090  	// are on the same chain by feeding all blocks to the other tester.
  1091  	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
  1092  		b, _ := tpt.miner.FindBlock()
  1093  		err = tpt.cs.AcceptBlock(b)
  1094  		if err != nil {
  1095  			t.Fatal(err)
  1096  		}
  1097  		err = tpt2.cs.AcceptBlock(b)
  1098  		if err != nil {
  1099  			t.Fatal(err)
  1100  		}
  1101  	}
  1102  	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
  1103  		b, _ := tpt2.miner.FindBlock()
  1104  		err = tpt2.cs.AcceptBlock(b)
  1105  		if err != nil {
  1106  			t.Fatal(err)
  1107  		}
  1108  		err = tpt.cs.AcceptBlock(b)
  1109  		if err != nil {
  1110  			t.Fatal(err)
  1111  		}
  1112  	}
  1113  
  1114  	// Mine a few more blocks to get some extra funding.
  1115  	for i := 0; i < 4; i++ {
  1116  		block, err := tpt.miner.AddBlock()
  1117  		if err != nil {
  1118  			t.Fatal(err)
  1119  		}
  1120  		err = tpt2.cs.AcceptBlock(block)
  1121  		if err != nil {
  1122  			t.Fatal(err)
  1123  		}
  1124  	}
  1125  
  1126  	// Create transaction graph setup.
  1127  	coinFrac := types.SiacoinPrecision
  1128  	numGraphs := 110
  1129  	graphFund := coinFrac.Mul64(12210)
  1130  	var outputs []types.SiacoinOutput
  1131  	for i := 0; i < numGraphs; i++ {
  1132  		outputs = append(outputs, types.SiacoinOutput{
  1133  			UnlockHash: types.UnlockConditions{}.UnlockHash(),
  1134  			Value:      graphFund,
  1135  		})
  1136  	}
  1137  	txns, err := tpt.wallet.SendSiacoinsMulti(outputs)
  1138  	if err != nil {
  1139  		t.Error(err)
  1140  	}
  1141  	// Mine the graph setup in the consensus set so that the graph outputs are
  1142  	// transaction sets. This guarantees that the parent of every graph will be
  1143  	// its own output.
  1144  	block, err := tpt.miner.AddBlock()
  1145  	if err != nil {
  1146  		t.Fatal(err)
  1147  	}
  1148  	err = tpt2.cs.AcceptBlock(block)
  1149  	if err != nil {
  1150  		t.Fatal(err)
  1151  	}
  1152  
  1153  	finalTxn := txns[len(txns)-1]
  1154  	// For each output, create 250 transactions
  1155  	var graphs [][]types.Transaction
  1156  	for i := 0; i < numGraphs; i++ {
  1157  		var edges []types.TransactionGraphEdge
  1158  		var cumFee types.Currency
  1159  		for j := 0; j < numGraphs; j++ {
  1160  			fee := coinFrac.Mul64(uint64((j + 1)))
  1161  			cumFee = cumFee.Add(fee)
  1162  			edges = append(edges, types.TransactionGraphEdge{
  1163  				Dest:   j + 1,
  1164  				Fee:    fee,
  1165  				Source: 0,
  1166  				Value:  fee,
  1167  			})
  1168  		}
  1169  		for k := 0; k < numGraphs; k++ {
  1170  			fee := coinFrac.Mul64(uint64(k + 1)).Div64(2)
  1171  			cumFee = cumFee.Add(fee)
  1172  			edges = append(edges, types.TransactionGraphEdge{
  1173  				Dest:   k + 251,
  1174  				Fee:    fee,
  1175  				Source: k + 1,
  1176  				Value:  fee,
  1177  			})
  1178  		}
  1179  		graph, err := types.TransactionGraph(finalTxn.SiacoinOutputID(uint64(i)), edges)
  1180  		if err != nil {
  1181  			t.Fatal(err)
  1182  		}
  1183  		graphs = append(graphs, graph)
  1184  
  1185  	}
  1186  	// Accept the parent node of each graph so that its outputs we can test
  1187  	// spending its outputs after mining the next block.
  1188  	for _, graph := range graphs {
  1189  		err := tpt.tpool.AcceptTransactionSet([]types.Transaction{graph[0]})
  1190  		if err != nil {
  1191  			t.Fatal(err)
  1192  		}
  1193  		err = tpt2.tpool.AcceptTransactionSet([]types.Transaction{graph[0]})
  1194  		if err != nil {
  1195  			t.Fatal(err)
  1196  		}
  1197  	}
  1198  	block, err = tpt.miner.AddBlock()
  1199  	if err != nil {
  1200  		t.Fatal(err)
  1201  	}
  1202  	err = tpt2.cs.AcceptBlock(block)
  1203  	if err != nil {
  1204  		t.Fatal(err)
  1205  	}
  1206  
  1207  	// Now accept all the other nodes of each graph.
  1208  	for _, graph := range graphs {
  1209  		for _, txn := range graph[1:] {
  1210  			err := tpt.tpool.AcceptTransactionSet([]types.Transaction{txn})
  1211  			if err != nil {
  1212  				t.Fatal(err)
  1213  			}
  1214  		}
  1215  	}
  1216  	// Accept a randomly selected subset of transactions with the other tester.
  1217  	randSet := fastrand.Perm(len(graphs))
  1218  	for i := 0; i < len(randSet)/10; i++ {
  1219  		graph := graphs[randSet[i]]
  1220  		for _, txn := range graph[1:] {
  1221  			err := tpt2.tpool.AcceptTransactionSet([]types.Transaction{txn})
  1222  			if err != nil {
  1223  				t.Fatal(err)
  1224  			}
  1225  		}
  1226  	}
  1227  
  1228  	// Now the second tester mines the random subset, and gives the block to the
  1229  	// first tester.
  1230  	block, err = tpt2.miner.AddBlock()
  1231  	if err != nil {
  1232  		t.Fatal(err)
  1233  	}
  1234  	err = tpt.cs.AcceptBlock(block)
  1235  	if err != nil {
  1236  		t.Fatal(err)
  1237  	}
  1238  
  1239  	//Now we add up all the fees from this first block.
  1240  	var totalFeeRandBlock types.Currency
  1241  	for _, tx := range block.Transactions {
  1242  		for _, fee := range tx.MinerFees {
  1243  			totalFeeRandBlock = totalFeeRandBlock.Add(fee)
  1244  		}
  1245  	}
  1246  
  1247  	// Mine the next block so we can check the transactions inside
  1248  	block, err = tpt.miner.AddBlock()
  1249  	if err != nil {
  1250  		t.Fatal(err)
  1251  	}
  1252  	var totalFee1 types.Currency
  1253  	maxFee1 := types.SiacoinPrecision.Div64(1000000)
  1254  	minFee1 := types.SiacoinPrecision.Mul64(1000000)
  1255  	for _, txn := range block.Transactions {
  1256  		for _, fee := range txn.MinerFees {
  1257  			if fee.Cmp(maxFee1) >= 0 {
  1258  				maxFee1 = fee
  1259  			}
  1260  			if fee.Cmp(minFee1) <= 0 {
  1261  				minFee1 = fee
  1262  			}
  1263  			totalFee1 = totalFee1.Add(fee)
  1264  		}
  1265  	}
  1266  
  1267  	// Mine the next block so we can check the transactions inside
  1268  	block, err = tpt.miner.AddBlock()
  1269  	if err != nil {
  1270  		t.Fatal(err)
  1271  	}
  1272  	var totalFee2 types.Currency
  1273  	maxFee2 := types.SiacoinPrecision.Div64(1000000)
  1274  	minFee2 := types.SiacoinPrecision.Mul64(1000000)
  1275  	for _, txn := range block.Transactions {
  1276  		for _, fee := range txn.MinerFees {
  1277  			if fee.Cmp(maxFee2) >= 0 {
  1278  				maxFee2 = fee
  1279  			}
  1280  			if fee.Cmp(minFee2) <= 0 {
  1281  				minFee2 = fee
  1282  			}
  1283  			totalFee2 = totalFee2.Add(fee)
  1284  		}
  1285  	}
  1286  
  1287  	totalFeeAcrossBlocks := totalFeeRandBlock.Add(totalFee1).Add(totalFee2)
  1288  	totalExpectedFee := types.SiacoinPrecision.Mul64(13860).Add(types.SiacoinPrecision.Mul64(321915))
  1289  	if totalFeeAcrossBlocks.Cmp(totalExpectedFee) != 0 {
  1290  		t.Error("Fee different from expected.")
  1291  	}
  1292  	if maxFee1.Cmp(maxFee2) <= 0 {
  1293  		t.Error("Expected highest fee from first block to be greater than highest fee from second block.")
  1294  	}
  1295  	if minFee1.Cmp(maxFee2) < 0 {
  1296  		t.Error("Expected lowest fee from first block to be greater than or equal to than highest fee from second block.")
  1297  	}
  1298  	if maxFee1.Cmp(minFee1) < 0 {
  1299  		t.Error("Expected highest fee from first block to be greater than lowest fee from first block.")
  1300  	}
  1301  	if maxFee2.Cmp(minFee2) < 0 {
  1302  		t.Error("Expected highest fee from second block to be greater than lowest fee from second block.")
  1303  	}
  1304  }