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