github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/txpool_test.go (about)

     1  package protocol
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/davecgh/go-spew/spew"
     8  
     9  	"github.com/bytom/bytom/consensus"
    10  	"github.com/bytom/bytom/database/storage"
    11  	"github.com/bytom/bytom/event"
    12  	"github.com/bytom/bytom/protocol/bc"
    13  	"github.com/bytom/bytom/protocol/bc/types"
    14  	"github.com/bytom/bytom/protocol/state"
    15  	"github.com/bytom/bytom/testutil"
    16  )
    17  
    18  var testTxs = []*types.Tx{
    19  	//tx0
    20  	types.NewTx(types.TxData{
    21  		SerializedSize: 100,
    22  		Inputs: []*types.TxInput{
    23  			types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}, nil),
    24  		},
    25  		Outputs: []*types.TxOutput{
    26  			types.NewOriginalTxOutput(*consensus.BTMAssetID, 1, []byte{0x6a}, nil),
    27  		},
    28  	}),
    29  	//tx1
    30  	types.NewTx(types.TxData{
    31  		SerializedSize: 100,
    32  		Inputs: []*types.TxInput{
    33  			types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}, nil),
    34  		},
    35  		Outputs: []*types.TxOutput{
    36  			types.NewOriginalTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}, nil),
    37  		},
    38  	}),
    39  	//tx2
    40  	types.NewTx(types.TxData{
    41  		SerializedSize: 150,
    42  		TimeRange:      0,
    43  		Inputs: []*types.TxInput{
    44  			types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}, nil),
    45  			types.NewSpendInput(nil, bc.NewHash([32]byte{0x02}), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x51}, nil),
    46  		},
    47  		Outputs: []*types.TxOutput{
    48  			types.NewOriginalTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}, nil),
    49  			types.NewOriginalTxOutput(bc.NewAssetID([32]byte{0xa1}), 4, []byte{0x61}, nil),
    50  		},
    51  	}),
    52  	//tx3
    53  	types.NewTx(types.TxData{
    54  		SerializedSize: 100,
    55  		Inputs: []*types.TxInput{
    56  			types.NewSpendInput(nil, testutil.MustDecodeHash("dbea684b5c5153ed7729669a53d6c59574f26015a3e1eb2a0e8a1c645425a764"), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x61}, nil),
    57  		},
    58  		Outputs: []*types.TxOutput{
    59  			types.NewOriginalTxOutput(bc.NewAssetID([32]byte{0xa1}), 3, []byte{0x62}, nil),
    60  			types.NewOriginalTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x63}, nil),
    61  		},
    62  	}),
    63  	//tx4
    64  	types.NewTx(types.TxData{
    65  		SerializedSize: 100,
    66  		Inputs: []*types.TxInput{
    67  			types.NewSpendInput(nil, testutil.MustDecodeHash("d84d0be0fd08e7341f2d127749bb0d0844d4560f53bd54861cee9981fd922cad"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}, nil),
    68  		},
    69  		Outputs: []*types.TxOutput{
    70  			types.NewOriginalTxOutput(bc.NewAssetID([32]byte{0xa1}), 2, []byte{0x64}, nil),
    71  			types.NewOriginalTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x65}, nil),
    72  		},
    73  	}),
    74  	//tx5
    75  	types.NewTx(types.TxData{
    76  		SerializedSize: 100,
    77  		Inputs: []*types.TxInput{
    78  			types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}, nil),
    79  		},
    80  		Outputs: []*types.TxOutput{
    81  			types.NewOriginalTxOutput(*consensus.BTMAssetID, 0, []byte{0x51}, nil),
    82  		},
    83  	}),
    84  	//tx6
    85  	types.NewTx(types.TxData{
    86  		SerializedSize: 100,
    87  		Inputs: []*types.TxInput{
    88  			types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 3, 1, []byte{0x51}, nil),
    89  			types.NewSpendInput(nil, testutil.MustDecodeHash("d84d0be0fd08e7341f2d127749bb0d0844d4560f53bd54861cee9981fd922cad"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}, nil),
    90  		},
    91  		Outputs: []*types.TxOutput{
    92  			types.NewOriginalTxOutput(*consensus.BTMAssetID, 2, []byte{0x51}, nil),
    93  			types.NewOriginalTxOutput(bc.NewAssetID([32]byte{0xa1}), 0, []byte{0x65}, nil),
    94  		},
    95  	}),
    96  }
    97  
    98  type mockStore struct{}
    99  
   100  func (s *mockStore) GetBlockHeader(hash *bc.Hash) (*types.BlockHeader, error)     { return nil, nil }
   101  func (s *mockStore) GetCheckpoint(hash *bc.Hash) (*state.Checkpoint, error)       { return nil, nil }
   102  func (s *mockStore) GetCheckpointsByHeight(u uint64) ([]*state.Checkpoint, error) { return nil, nil }
   103  func (s *mockStore) SaveCheckpoints([]*state.Checkpoint) error                    { return nil }
   104  func (s *mockStore) CheckpointsFromNode(height uint64, hash *bc.Hash) ([]*state.Checkpoint, error) {
   105  	return nil, nil
   106  }
   107  func (s *mockStore) BlockExist(hash *bc.Hash) bool                            { return false }
   108  func (s *mockStore) GetBlock(*bc.Hash) (*types.Block, error)                  { return nil, nil }
   109  func (s *mockStore) GetStoreStatus() *state.BlockStoreState                   { return nil }
   110  func (s *mockStore) GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error { return nil }
   111  func (s *mockStore) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error)             { return nil, nil }
   112  func (s *mockStore) GetMainChainHash(uint64) (*bc.Hash, error)                { return nil, nil }
   113  func (s *mockStore) GetContract(hash [32]byte) ([]byte, error)                { return nil, nil }
   114  func (s *mockStore) SaveBlock(*types.Block) error                             { return nil }
   115  func (s *mockStore) SaveBlockHeader(*types.BlockHeader) error                 { return nil }
   116  func (s *mockStore) SaveChainStatus(*types.BlockHeader, []*types.BlockHeader, *state.UtxoViewpoint, *state.ContractViewpoint, uint64, *bc.Hash) error {
   117  	return nil
   118  }
   119  
   120  func TestAddOrphan(t *testing.T) {
   121  	cases := []struct {
   122  		before         *TxPool
   123  		after          *TxPool
   124  		addOrphan      *TxDesc
   125  		requireParents []*bc.Hash
   126  	}{
   127  		{
   128  			before: &TxPool{
   129  				orphans:       map[bc.Hash]*orphanTx{},
   130  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
   131  			},
   132  			after: &TxPool{
   133  				orphans: map[bc.Hash]*orphanTx{
   134  					testTxs[0].ID: {
   135  						TxDesc: &TxDesc{
   136  							Tx: testTxs[0],
   137  						},
   138  					},
   139  				},
   140  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   141  					testTxs[0].SpentOutputIDs[0]: {
   142  						testTxs[0].ID: {
   143  							TxDesc: &TxDesc{
   144  								Tx: testTxs[0],
   145  							},
   146  						},
   147  					},
   148  				},
   149  			},
   150  			addOrphan:      &TxDesc{Tx: testTxs[0]},
   151  			requireParents: []*bc.Hash{&testTxs[0].SpentOutputIDs[0]},
   152  		},
   153  		{
   154  			before: &TxPool{
   155  				orphans: map[bc.Hash]*orphanTx{
   156  					testTxs[0].ID: {
   157  						TxDesc: &TxDesc{
   158  							Tx: testTxs[0],
   159  						},
   160  					},
   161  				},
   162  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   163  					testTxs[0].SpentOutputIDs[0]: {
   164  						testTxs[0].ID: {
   165  							TxDesc: &TxDesc{
   166  								Tx: testTxs[0],
   167  							},
   168  						},
   169  					},
   170  				},
   171  			},
   172  			after: &TxPool{
   173  				orphans: map[bc.Hash]*orphanTx{
   174  					testTxs[0].ID: {
   175  						TxDesc: &TxDesc{
   176  							Tx: testTxs[0],
   177  						},
   178  					},
   179  					testTxs[1].ID: {
   180  						TxDesc: &TxDesc{
   181  							Tx: testTxs[1],
   182  						},
   183  					},
   184  				},
   185  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   186  					testTxs[0].SpentOutputIDs[0]: {
   187  						testTxs[0].ID: {
   188  							TxDesc: &TxDesc{
   189  								Tx: testTxs[0],
   190  							},
   191  						},
   192  						testTxs[1].ID: {
   193  							TxDesc: &TxDesc{
   194  								Tx: testTxs[1],
   195  							},
   196  						},
   197  					},
   198  				},
   199  			},
   200  			addOrphan:      &TxDesc{Tx: testTxs[1]},
   201  			requireParents: []*bc.Hash{&testTxs[1].SpentOutputIDs[0]},
   202  		},
   203  		{
   204  			before: &TxPool{
   205  				orphans:       map[bc.Hash]*orphanTx{},
   206  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
   207  			},
   208  			after: &TxPool{
   209  				orphans: map[bc.Hash]*orphanTx{
   210  					testTxs[2].ID: {
   211  						TxDesc: &TxDesc{
   212  							Tx: testTxs[2],
   213  						},
   214  					},
   215  				},
   216  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   217  					testTxs[2].SpentOutputIDs[1]: {
   218  						testTxs[2].ID: {
   219  							TxDesc: &TxDesc{
   220  								Tx: testTxs[2],
   221  							},
   222  						},
   223  					},
   224  				},
   225  			},
   226  			addOrphan:      &TxDesc{Tx: testTxs[2]},
   227  			requireParents: []*bc.Hash{&testTxs[2].SpentOutputIDs[1]},
   228  		},
   229  	}
   230  
   231  	for i, c := range cases {
   232  		c.before.addOrphan(c.addOrphan, c.requireParents)
   233  		for _, orphan := range c.before.orphans {
   234  			orphan.expiration = time.Time{}
   235  		}
   236  		for _, orphans := range c.before.orphansByPrev {
   237  			for _, orphan := range orphans {
   238  				orphan.expiration = time.Time{}
   239  			}
   240  		}
   241  		if !testutil.DeepEqual(c.before, c.after) {
   242  			t.Errorf("case %d: got %v want %v", i, c.before, c.after)
   243  		}
   244  	}
   245  }
   246  
   247  func TestAddTransaction(t *testing.T) {
   248  	dispatcher := event.NewDispatcher()
   249  	cases := []struct {
   250  		before *TxPool
   251  		after  *TxPool
   252  		addTx  *TxDesc
   253  	}{
   254  		{
   255  			before: &TxPool{
   256  				pool:            map[bc.Hash]*TxDesc{},
   257  				utxo:            map[bc.Hash]*types.Tx{},
   258  				eventDispatcher: dispatcher,
   259  			},
   260  			after: &TxPool{
   261  				pool: map[bc.Hash]*TxDesc{
   262  					testTxs[2].ID: {
   263  						Tx: testTxs[2],
   264  					},
   265  				},
   266  				utxo: map[bc.Hash]*types.Tx{
   267  					*testTxs[2].ResultIds[0]: testTxs[2],
   268  					*testTxs[2].ResultIds[1]: testTxs[2],
   269  				},
   270  			},
   271  			addTx: &TxDesc{
   272  				Tx: testTxs[2],
   273  			},
   274  		},
   275  		{
   276  			before: &TxPool{
   277  				pool:            map[bc.Hash]*TxDesc{},
   278  				utxo:            map[bc.Hash]*types.Tx{},
   279  				eventDispatcher: dispatcher,
   280  			},
   281  			after: &TxPool{
   282  				pool: map[bc.Hash]*TxDesc{
   283  					testTxs[2].ID: {
   284  						Tx: testTxs[2],
   285  					},
   286  				},
   287  				utxo: map[bc.Hash]*types.Tx{
   288  					*testTxs[2].ResultIds[0]: testTxs[2],
   289  					*testTxs[2].ResultIds[1]: testTxs[2],
   290  				},
   291  			},
   292  			addTx: &TxDesc{
   293  				Tx: testTxs[2],
   294  			},
   295  		},
   296  	}
   297  
   298  	for i, c := range cases {
   299  		c.before.addTransaction(c.addTx)
   300  		for _, txD := range c.before.pool {
   301  			txD.Added = time.Time{}
   302  		}
   303  		if !testutil.DeepEqual(c.before.pool, c.after.pool) {
   304  			t.Errorf("case %d: pool: got %v want %v", i, c.before.pool, c.after.pool)
   305  		}
   306  		if !testutil.DeepEqual(c.before.utxo, c.after.utxo) {
   307  			t.Errorf("case %d: utxo: got %v want %v", i, c.before.utxo, c.after.utxo)
   308  		}
   309  	}
   310  }
   311  
   312  func TestExpireOrphan(t *testing.T) {
   313  	before := &TxPool{
   314  		orphans: map[bc.Hash]*orphanTx{
   315  			testTxs[0].ID: {
   316  				expiration: time.Unix(1533489701, 0),
   317  				TxDesc: &TxDesc{
   318  					Tx: testTxs[0],
   319  				},
   320  			},
   321  			testTxs[1].ID: {
   322  				expiration: time.Unix(1633489701, 0),
   323  				TxDesc: &TxDesc{
   324  					Tx: testTxs[1],
   325  				},
   326  			},
   327  		},
   328  		orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   329  			testTxs[0].SpentOutputIDs[0]: {
   330  				testTxs[0].ID: {
   331  					expiration: time.Unix(1533489701, 0),
   332  					TxDesc: &TxDesc{
   333  						Tx: testTxs[0],
   334  					},
   335  				},
   336  				testTxs[1].ID: {
   337  					expiration: time.Unix(1633489701, 0),
   338  					TxDesc: &TxDesc{
   339  						Tx: testTxs[1],
   340  					},
   341  				},
   342  			},
   343  		},
   344  	}
   345  
   346  	want := &TxPool{
   347  		orphans: map[bc.Hash]*orphanTx{
   348  			testTxs[1].ID: {
   349  				expiration: time.Unix(1633489701, 0),
   350  				TxDesc: &TxDesc{
   351  					Tx: testTxs[1],
   352  				},
   353  			},
   354  		},
   355  		orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   356  			testTxs[0].SpentOutputIDs[0]: {
   357  				testTxs[1].ID: {
   358  					expiration: time.Unix(1633489701, 0),
   359  					TxDesc: &TxDesc{
   360  						Tx: testTxs[1],
   361  					},
   362  				},
   363  			},
   364  		},
   365  	}
   366  
   367  	before.ExpireOrphan(time.Unix(1633479701, 0))
   368  	if !testutil.DeepEqual(before, want) {
   369  		t.Errorf("got %v want %v", before, want)
   370  	}
   371  }
   372  
   373  func TestProcessOrphans(t *testing.T) {
   374  	t.Skip("Skipping testing in CI environment temp")
   375  	dispatcher := event.NewDispatcher()
   376  	cases := []struct {
   377  		before    *TxPool
   378  		after     *TxPool
   379  		processTx *TxDesc
   380  	}{
   381  		{
   382  			before: &TxPool{
   383  				pool:            map[bc.Hash]*TxDesc{},
   384  				utxo:            map[bc.Hash]*types.Tx{},
   385  				eventDispatcher: dispatcher,
   386  				orphans: map[bc.Hash]*orphanTx{
   387  					testTxs[3].ID: {
   388  						TxDesc: &TxDesc{
   389  							Tx: testTxs[3],
   390  						},
   391  					},
   392  				},
   393  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   394  					testTxs[3].SpentOutputIDs[0]: {
   395  						testTxs[3].ID: {
   396  							TxDesc: &TxDesc{
   397  								Tx: testTxs[3],
   398  							},
   399  						},
   400  					},
   401  				},
   402  			},
   403  			after: &TxPool{
   404  				pool: map[bc.Hash]*TxDesc{
   405  					testTxs[3].ID: {
   406  						Tx: testTxs[3],
   407  					},
   408  				},
   409  				utxo: map[bc.Hash]*types.Tx{
   410  					*testTxs[3].ResultIds[0]: testTxs[3],
   411  					*testTxs[3].ResultIds[1]: testTxs[3],
   412  				},
   413  				eventDispatcher: dispatcher,
   414  				orphans:         map[bc.Hash]*orphanTx{},
   415  				orphansByPrev:   map[bc.Hash]map[bc.Hash]*orphanTx{},
   416  			},
   417  			processTx: &TxDesc{Tx: testTxs[2]},
   418  		},
   419  		{
   420  			before: &TxPool{
   421  				pool:            map[bc.Hash]*TxDesc{},
   422  				utxo:            map[bc.Hash]*types.Tx{},
   423  				eventDispatcher: dispatcher,
   424  				orphans: map[bc.Hash]*orphanTx{
   425  					testTxs[3].ID: {
   426  						TxDesc: &TxDesc{
   427  							Tx: testTxs[3],
   428  						},
   429  					},
   430  					testTxs[4].ID: {
   431  						TxDesc: &TxDesc{
   432  							Tx: testTxs[4],
   433  						},
   434  					},
   435  				},
   436  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   437  					testTxs[3].SpentOutputIDs[0]: {
   438  						testTxs[3].ID: {
   439  							TxDesc: &TxDesc{
   440  								Tx: testTxs[3],
   441  							},
   442  						},
   443  					},
   444  					testTxs[4].SpentOutputIDs[0]: {
   445  						testTxs[4].ID: {
   446  							TxDesc: &TxDesc{
   447  								Tx: testTxs[4],
   448  							},
   449  						},
   450  					},
   451  				},
   452  			},
   453  			after: &TxPool{
   454  				pool: map[bc.Hash]*TxDesc{
   455  					testTxs[3].ID: {
   456  						Tx: testTxs[3],
   457  					},
   458  					testTxs[4].ID: {
   459  						Tx: testTxs[4],
   460  					},
   461  				},
   462  				utxo: map[bc.Hash]*types.Tx{
   463  					*testTxs[3].ResultIds[0]: testTxs[3],
   464  					*testTxs[3].ResultIds[1]: testTxs[3],
   465  					*testTxs[4].ResultIds[0]: testTxs[4],
   466  					*testTxs[4].ResultIds[1]: testTxs[4],
   467  				},
   468  				eventDispatcher: dispatcher,
   469  				orphans:         map[bc.Hash]*orphanTx{},
   470  				orphansByPrev:   map[bc.Hash]map[bc.Hash]*orphanTx{},
   471  			},
   472  			processTx: &TxDesc{Tx: testTxs[2]},
   473  		},
   474  	}
   475  
   476  	for i, c := range cases {
   477  		c.before.store = &mockStore{}
   478  		c.before.addTransaction(c.processTx)
   479  		c.before.processOrphans(c.processTx)
   480  		c.before.RemoveTransaction(&c.processTx.Tx.ID)
   481  		c.before.store = nil
   482  		c.before.lastUpdated = 0
   483  		for _, txD := range c.before.pool {
   484  			txD.Added = time.Time{}
   485  		}
   486  
   487  		if !testutil.DeepEqual(c.before, c.after) {
   488  			t.Errorf("case %d: got %v want %v", i, c.before, c.after)
   489  		}
   490  	}
   491  }
   492  
   493  func TestRemoveOrphan(t *testing.T) {
   494  	cases := []struct {
   495  		before       *TxPool
   496  		after        *TxPool
   497  		removeHashes []*bc.Hash
   498  	}{
   499  		{
   500  			before: &TxPool{
   501  				orphans: map[bc.Hash]*orphanTx{
   502  					testTxs[0].ID: {
   503  						expiration: time.Unix(1533489701, 0),
   504  						TxDesc: &TxDesc{
   505  							Tx: testTxs[0],
   506  						},
   507  					},
   508  				},
   509  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   510  					testTxs[0].SpentOutputIDs[0]: {
   511  						testTxs[0].ID: {
   512  							expiration: time.Unix(1533489701, 0),
   513  							TxDesc: &TxDesc{
   514  								Tx: testTxs[0],
   515  							},
   516  						},
   517  					},
   518  				},
   519  			},
   520  			after: &TxPool{
   521  				orphans:       map[bc.Hash]*orphanTx{},
   522  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
   523  			},
   524  			removeHashes: []*bc.Hash{
   525  				&testTxs[0].ID,
   526  			},
   527  		},
   528  		{
   529  			before: &TxPool{
   530  				orphans: map[bc.Hash]*orphanTx{
   531  					testTxs[0].ID: {
   532  						expiration: time.Unix(1533489701, 0),
   533  						TxDesc: &TxDesc{
   534  							Tx: testTxs[0],
   535  						},
   536  					},
   537  					testTxs[1].ID: {
   538  						expiration: time.Unix(1533489701, 0),
   539  						TxDesc: &TxDesc{
   540  							Tx: testTxs[1],
   541  						},
   542  					},
   543  				},
   544  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   545  					testTxs[0].SpentOutputIDs[0]: {
   546  						testTxs[0].ID: {
   547  							expiration: time.Unix(1533489701, 0),
   548  							TxDesc: &TxDesc{
   549  								Tx: testTxs[0],
   550  							},
   551  						},
   552  						testTxs[1].ID: {
   553  							expiration: time.Unix(1533489701, 0),
   554  							TxDesc: &TxDesc{
   555  								Tx: testTxs[1],
   556  							},
   557  						},
   558  					},
   559  				},
   560  			},
   561  			after: &TxPool{
   562  				orphans: map[bc.Hash]*orphanTx{
   563  					testTxs[0].ID: {
   564  						expiration: time.Unix(1533489701, 0),
   565  						TxDesc: &TxDesc{
   566  							Tx: testTxs[0],
   567  						},
   568  					},
   569  				},
   570  				orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
   571  					testTxs[0].SpentOutputIDs[0]: {
   572  						testTxs[0].ID: {
   573  							expiration: time.Unix(1533489701, 0),
   574  							TxDesc: &TxDesc{
   575  								Tx: testTxs[0],
   576  							},
   577  						},
   578  					},
   579  				},
   580  			},
   581  			removeHashes: []*bc.Hash{
   582  				&testTxs[1].ID,
   583  			},
   584  		},
   585  	}
   586  
   587  	for i, c := range cases {
   588  		for _, hash := range c.removeHashes {
   589  			c.before.removeOrphan(hash)
   590  		}
   591  		if !testutil.DeepEqual(c.before, c.after) {
   592  			t.Errorf("case %d: got %v want %v", i, c.before, c.after)
   593  		}
   594  	}
   595  }
   596  
   597  type mockStore1 struct{}
   598  
   599  func (s *mockStore1) GetBlockHeader(hash *bc.Hash) (*types.BlockHeader, error)     { return nil, nil }
   600  func (s *mockStore1) GetCheckpoint(hash *bc.Hash) (*state.Checkpoint, error)       { return nil, nil }
   601  func (s *mockStore1) GetCheckpointsByHeight(u uint64) ([]*state.Checkpoint, error) { return nil, nil }
   602  func (s *mockStore1) SaveCheckpoints([]*state.Checkpoint) error                    { return nil }
   603  func (s *mockStore1) CheckpointsFromNode(height uint64, hash *bc.Hash) ([]*state.Checkpoint, error) {
   604  	return nil, nil
   605  }
   606  func (s *mockStore1) BlockExist(hash *bc.Hash) bool           { return false }
   607  func (s *mockStore1) GetBlock(*bc.Hash) (*types.Block, error) { return nil, nil }
   608  func (s *mockStore1) GetStoreStatus() *state.BlockStoreState  { return nil }
   609  func (s *mockStore1) GetTransactionsUtxo(utxoView *state.UtxoViewpoint, tx []*bc.Tx) error {
   610  	for _, hash := range testTxs[2].SpentOutputIDs {
   611  		utxoView.Entries[hash] = &storage.UtxoEntry{Type: storage.NormalUTXOType, Spent: false}
   612  	}
   613  	return nil
   614  }
   615  func (s *mockStore1) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) { return nil, nil }
   616  func (s *mockStore1) GetMainChainHash(uint64) (*bc.Hash, error)    { return nil, nil }
   617  func (s *mockStore1) GetContract(hash [32]byte) ([]byte, error)    { return nil, nil }
   618  func (s *mockStore1) SaveBlock(*types.Block) error                 { return nil }
   619  func (s *mockStore1) SaveBlockHeader(*types.BlockHeader) error     { return nil }
   620  func (s *mockStore1) SaveChainStatus(*types.BlockHeader, []*types.BlockHeader, *state.UtxoViewpoint, *state.ContractViewpoint, uint64, *bc.Hash) error {
   621  	return nil
   622  }
   623  
   624  func TestProcessTransaction(t *testing.T) {
   625  	txPool := &TxPool{
   626  		pool:            make(map[bc.Hash]*TxDesc),
   627  		utxo:            make(map[bc.Hash]*types.Tx),
   628  		orphans:         make(map[bc.Hash]*orphanTx),
   629  		orphansByPrev:   make(map[bc.Hash]map[bc.Hash]*orphanTx),
   630  		store:           &mockStore1{},
   631  		eventDispatcher: event.NewDispatcher(),
   632  	}
   633  	cases := []struct {
   634  		want  *TxPool
   635  		addTx *TxDesc
   636  	}{
   637  		//Dust tx
   638  		{
   639  			want: &TxPool{},
   640  			addTx: &TxDesc{
   641  				Tx: testTxs[3],
   642  			},
   643  		},
   644  		//Dust tx
   645  		{
   646  			want: &TxPool{},
   647  			addTx: &TxDesc{
   648  				Tx: testTxs[4],
   649  			},
   650  		},
   651  		//Dust tx
   652  		{
   653  			want: &TxPool{},
   654  			addTx: &TxDesc{
   655  				Tx: testTxs[5],
   656  			},
   657  		},
   658  		//Dust tx
   659  		{
   660  			want: &TxPool{},
   661  			addTx: &TxDesc{
   662  				Tx: testTxs[6],
   663  			},
   664  		},
   665  		//normal tx
   666  		{
   667  			want: &TxPool{
   668  				pool: map[bc.Hash]*TxDesc{
   669  					testTxs[2].ID: {
   670  						Tx:     testTxs[2],
   671  						Weight: 150,
   672  					},
   673  				},
   674  				utxo: map[bc.Hash]*types.Tx{
   675  					*testTxs[2].ResultIds[0]: testTxs[2],
   676  					*testTxs[2].ResultIds[1]: testTxs[2],
   677  				},
   678  			},
   679  			addTx: &TxDesc{
   680  				Tx: testTxs[2],
   681  			},
   682  		},
   683  	}
   684  
   685  	for i, c := range cases {
   686  		txPool.ProcessTransaction(c.addTx.Tx, 0, 0)
   687  		for _, txD := range txPool.pool {
   688  			txD.Added = time.Time{}
   689  		}
   690  		for _, txD := range txPool.orphans {
   691  			txD.Added = time.Time{}
   692  			txD.expiration = time.Time{}
   693  		}
   694  
   695  		if !testutil.DeepEqual(txPool.pool, c.want.pool) {
   696  			t.Errorf("case %d: test ProcessTransaction pool mismatch got %s want %s", i, spew.Sdump(txPool.pool), spew.Sdump(c.want.pool))
   697  		}
   698  		if !testutil.DeepEqual(txPool.utxo, c.want.utxo) {
   699  			t.Errorf("case %d: test ProcessTransaction utxo mismatch got %s want %s", i, spew.Sdump(txPool.utxo), spew.Sdump(c.want.utxo))
   700  		}
   701  		if !testutil.DeepEqual(txPool.orphans, c.want.orphans) {
   702  			t.Errorf("case %d: test ProcessTransaction orphans mismatch got %s want %s", i, spew.Sdump(txPool.orphans), spew.Sdump(c.want.orphans))
   703  		}
   704  		if !testutil.DeepEqual(txPool.orphansByPrev, c.want.orphansByPrev) {
   705  			t.Errorf("case %d: test ProcessTransaction orphansByPrev mismatch got %s want %s", i, spew.Sdump(txPool.orphansByPrev), spew.Sdump(c.want.orphansByPrev))
   706  		}
   707  	}
   708  }