github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/test/protocol_test.go (about)

     1  // +build functional
     2  
     3  package test
     4  
     5  import (
     6  	"os"
     7  	"testing"
     8  
     9  	"github.com/bytom/bytom/consensus"
    10  	dbm "github.com/bytom/bytom/database/leveldb"
    11  	"github.com/bytom/bytom/protocol/bc/types"
    12  	"github.com/bytom/bytom/protocol/vm"
    13  )
    14  
    15  // case1:           |------c1(height=7)
    16  // --------(height=5)
    17  //                  |------------c2(height=9)
    18  func TestForkCase1(t *testing.T) {
    19  	c1, err := declChain("chain1", nil, 0, 7)
    20  	defer os.RemoveAll("chain1")
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  
    25  	c2, err := declChain("chain2", c1, 5, 9)
    26  	defer os.RemoveAll("chain2")
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  
    31  	bestBlockHash := c2.BestBlockHash()
    32  	if err := merge(c1, c2); err != nil {
    33  		t.Fatal(err)
    34  	}
    35  
    36  	if *c1.BestBlockHash() != *bestBlockHash || *c2.BestBlockHash() != *bestBlockHash {
    37  		t.Fatalf("test fork case1 failed")
    38  	}
    39  
    40  	if !c1.InMainChain(*bestBlockHash) || !c2.InMainChain(*bestBlockHash) {
    41  		t.Fatalf("best block is not in main chain")
    42  	}
    43  }
    44  
    45  // case2:            |----c1(height=6)
    46  // ---------(height 5)
    47  //                   |----c2(height=6)
    48  func TestForkCase2(t *testing.T) {
    49  	c1, err := declChain("chain1", nil, 0, 6)
    50  	defer os.RemoveAll("chain1")
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  
    55  	c2, err := declChain("chain2", c1, 5, 6)
    56  	defer os.RemoveAll("chain2")
    57  	if err != nil {
    58  		t.Fatal(err)
    59  	}
    60  
    61  	c1BestBlockHash := c1.BestBlockHash()
    62  	c2BestBlockHash := c2.BestBlockHash()
    63  	if err := merge(c1, c2); err != nil {
    64  		t.Fatal(err)
    65  	}
    66  
    67  	if *c1.BestBlockHash() != *c1BestBlockHash || *c2.BestBlockHash() != *c2BestBlockHash {
    68  		t.Fatalf("test fork case2 failed")
    69  	}
    70  
    71  	if !c1.InMainChain(*c1BestBlockHash) || !c2.InMainChain(*c2BestBlockHash) {
    72  		t.Fatalf("best block is not in main chain")
    73  	}
    74  }
    75  
    76  func TestBlockSync(t *testing.T) {
    77  	c1, err := declChain("chain1", nil, 0, 5)
    78  	defer os.RemoveAll("chain1")
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	c2, err := declChain("chain2", c1, 5, 8)
    84  	defer os.RemoveAll("chain2")
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  
    89  	bestBlockHash := c2.BestBlockHash()
    90  	if err := merge(c1, c2); err != nil {
    91  		t.Fatal(err)
    92  	}
    93  
    94  	if *c1.BestBlockHash() != *bestBlockHash || *c2.BestBlockHash() != *bestBlockHash {
    95  		t.Fatalf("test block sync failed")
    96  	}
    97  
    98  	if !c1.InMainChain(*bestBlockHash) || !c2.InMainChain(*bestBlockHash) {
    99  		t.Fatalf("test block sync failed, best block is not in main chain")
   100  	}
   101  }
   102  
   103  func TestDoubleSpentInDiffBlock(t *testing.T) {
   104  	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
   105  	defer os.RemoveAll("tx_pool_test")
   106  	chain, _, txPool, err := MockChain(chainDB)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil {
   111  		t.Fatal(err)
   112  	}
   113  
   114  	// create tx spend the coinbase output in block 1
   115  	block, err := chain.GetBlockByHeight(1)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  	tx, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  
   124  	newBlock, err := NewBlock(chain, []*types.Tx{tx}, []byte{byte(vm.OP_TRUE)})
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  	_, err = chain.ProcessBlock(newBlock)
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  
   133  	// create a double spent tx in another block
   134  	tx, err = CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  
   139  	if isOrphan, err := chain.ValidateTx(tx); isOrphan == false && err == nil {
   140  		t.Fatal("validate double spent tx success")
   141  	}
   142  	if txPool.HaveTransaction(&tx.ID) {
   143  		t.Fatalf("tx pool have double spent tx")
   144  	}
   145  }
   146  
   147  func TestDoubleSpentInSameBlock(t *testing.T) {
   148  	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
   149  	defer os.RemoveAll("tx_pool_test")
   150  	chain, _, txPool, err := MockChain(chainDB)
   151  	if err != nil {
   152  		t.Fatal(err)
   153  	}
   154  	if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil {
   155  		t.Fatal(err)
   156  	}
   157  
   158  	// create tx spend the coinbase output in block 1
   159  	block, err := chain.GetBlockByHeight(1)
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  	tx1, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
   164  	if err != nil {
   165  		t.Fatal(err)
   166  	}
   167  
   168  	// create tx spend the coinbase output in block 1
   169  	tx2, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
   170  	if err != nil {
   171  		t.Fatal(err)
   172  	}
   173  
   174  	_, err = chain.ValidateTx(tx1)
   175  	if err != nil {
   176  		t.Fatal(err)
   177  	}
   178  	_, err = chain.ValidateTx(tx2)
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  
   183  	if !txPool.HaveTransaction(&tx1.ID) {
   184  		t.Fatalf("can't find tx in tx pool")
   185  	}
   186  	if !txPool.HaveTransaction(&tx2.ID) {
   187  		t.Fatalf("can't find tx in tx pool")
   188  	}
   189  
   190  	block, err = NewBlock(chain, []*types.Tx{tx1, tx2}, []byte{byte(vm.OP_TRUE)})
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  
   195  	if _, err := chain.ProcessBlock(block); err == nil {
   196  		t.Fatalf("process double spent tx success")
   197  	}
   198  }
   199  
   200  func TestTxPoolDependencyTx(t *testing.T) {
   201  	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
   202  	defer os.RemoveAll("tx_pool_test")
   203  	chain, _, txPool, err := MockChain(chainDB)
   204  	if err != nil {
   205  		t.Fatal(err)
   206  	}
   207  	if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil {
   208  		t.Fatal(err)
   209  	}
   210  
   211  	block, err := chain.GetBlockByHeight(1)
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  
   216  	tx, err := CreateTxFromTx(block.Transactions[0], 0, 5000000000, []byte{byte(vm.OP_TRUE)})
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  
   221  	outputAmount := uint64(5000000000)
   222  	txs := []*types.Tx{nil}
   223  	txs[0] = tx
   224  	for i := 1; i < 10; i++ {
   225  		outputAmount -= 50000000
   226  		tx, err := CreateTxFromTx(txs[i-1], 0, outputAmount, []byte{byte(vm.OP_TRUE)})
   227  		if err != nil {
   228  			t.Fatal(err)
   229  		}
   230  		txs = append(txs, tx)
   231  	}
   232  
   233  	// validate tx and put it into tx pool
   234  	for _, tx := range txs {
   235  		if _, err := chain.ValidateTx(tx); err != nil {
   236  			t.Fatal(err)
   237  		}
   238  		if !txPool.HaveTransaction(&tx.ID) {
   239  			t.Fatal("can't find tx in txpool")
   240  		}
   241  	}
   242  
   243  	block, err = NewBlock(chain, txs, []byte{byte(vm.OP_TRUE)})
   244  	if err != nil {
   245  		t.Fatal(err)
   246  	}
   247  
   248  	if _, err = chain.ProcessBlock(block); err != nil {
   249  		t.Fatal("process dependency tx failed")
   250  	}
   251  }
   252  
   253  func TestAddInvalidTxToTxPool(t *testing.T) {
   254  	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
   255  	defer os.RemoveAll("tx_pool_test")
   256  
   257  	chain, _, txPool, err := MockChain(chainDB)
   258  	if err != nil {
   259  		t.Fatal(err)
   260  	}
   261  
   262  	if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil {
   263  		t.Fatal(err)
   264  	}
   265  
   266  	block, err := chain.GetBlockByHeight(1)
   267  	if err != nil {
   268  		t.Fatal(err)
   269  	}
   270  
   271  	//invalid tx, output amount greater than input
   272  	tx, err := CreateTxFromTx(block.Transactions[0], 0, 60000000000, []byte{byte(vm.OP_TRUE)})
   273  	if err != nil {
   274  		t.Fatal(err)
   275  	}
   276  
   277  	if _, err := chain.ValidateTx(tx); err == nil {
   278  		t.Fatalf("add invalid tx to txpool success")
   279  	}
   280  
   281  	if txPool.IsTransactionInPool(&tx.ID) {
   282  		t.Fatalf("add invalid tx to txpool success")
   283  	}
   284  
   285  	if !txPool.IsTransactionInErrCache(&tx.ID) {
   286  		t.Fatalf("can't find invalid tx in txpool err cache")
   287  	}
   288  }