gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/transactionpool/transactionpool_test.go (about)

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