github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/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  	"github.com/bytom/bytom/protocol/bc/types"
    11  	"github.com/bytom/bytom/protocol/vm"
    12  	dbm "github.com/bytom/bytom/database/leveldb"
    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  	err = SolveAndUpdate(chain, newBlock)
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  
   130  	// create a double spent tx in another block
   131  	tx, err = CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
   132  	if err != nil {
   133  		t.Fatal(err)
   134  	}
   135  
   136  	if isOrphan, err := chain.ValidateTx(tx); isOrphan == false && err == nil {
   137  		t.Fatal("validate double spent tx success")
   138  	}
   139  	if txPool.HaveTransaction(&tx.ID) {
   140  		t.Fatalf("tx pool have double spent tx")
   141  	}
   142  }
   143  
   144  func TestDoubleSpentInSameBlock(t *testing.T) {
   145  	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
   146  	defer os.RemoveAll("tx_pool_test")
   147  	chain, _, txPool, err := MockChain(chainDB)
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  	if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil {
   152  		t.Fatal(err)
   153  	}
   154  
   155  	// create tx spend the coinbase output in block 1
   156  	block, err := chain.GetBlockByHeight(1)
   157  	if err != nil {
   158  		t.Fatal(err)
   159  	}
   160  	tx1, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  
   165  	// create tx spend the coinbase output in block 1
   166  	tx2, err := CreateTxFromTx(block.Transactions[0], 0, 10000, []byte{byte(vm.OP_TRUE)})
   167  	if err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	_, err = chain.ValidateTx(tx1)
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	_, err = chain.ValidateTx(tx2)
   176  	if err != nil {
   177  		t.Fatal(err)
   178  	}
   179  
   180  	if !txPool.HaveTransaction(&tx1.ID) {
   181  		t.Fatalf("can't find tx in tx pool")
   182  	}
   183  	if !txPool.HaveTransaction(&tx2.ID) {
   184  		t.Fatalf("can't find tx in tx pool")
   185  	}
   186  
   187  	block, err = NewBlock(chain, []*types.Tx{tx1, tx2}, []byte{byte(vm.OP_TRUE)})
   188  	if err != nil {
   189  		t.Fatal(err)
   190  	}
   191  
   192  	if err := SolveAndUpdate(chain, block); err == nil {
   193  		t.Fatalf("process double spent tx success")
   194  	}
   195  }
   196  
   197  func TestTxPoolDependencyTx(t *testing.T) {
   198  	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
   199  	defer os.RemoveAll("tx_pool_test")
   200  	chain, _, txPool, err := MockChain(chainDB)
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  	if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil {
   205  		t.Fatal(err)
   206  	}
   207  
   208  	block, err := chain.GetBlockByHeight(1)
   209  	if err != nil {
   210  		t.Fatal(err)
   211  	}
   212  
   213  	tx, err := CreateTxFromTx(block.Transactions[0], 0, 5000000000, []byte{byte(vm.OP_TRUE)})
   214  	if err != nil {
   215  		t.Fatal(err)
   216  	}
   217  
   218  	outputAmount := uint64(5000000000)
   219  	txs := []*types.Tx{nil}
   220  	txs[0] = tx
   221  	for i := 1; i < 10; i++ {
   222  		outputAmount -= 50000000
   223  		tx, err := CreateTxFromTx(txs[i-1], 0, outputAmount, []byte{byte(vm.OP_TRUE)})
   224  		if err != nil {
   225  			t.Fatal(err)
   226  		}
   227  		txs = append(txs, tx)
   228  	}
   229  
   230  	// validate tx and put it into tx pool
   231  	for _, tx := range txs {
   232  		if _, err := chain.ValidateTx(tx); err != nil {
   233  			t.Fatal(err)
   234  		}
   235  		if !txPool.HaveTransaction(&tx.ID) {
   236  			t.Fatal("can't find tx in txpool")
   237  		}
   238  	}
   239  
   240  	block, err = NewBlock(chain, txs, []byte{byte(vm.OP_TRUE)})
   241  	if err != nil {
   242  		t.Fatal(err)
   243  	}
   244  
   245  	if err := SolveAndUpdate(chain, block); err != nil {
   246  		t.Fatal("process dependency tx failed")
   247  	}
   248  }
   249  
   250  func TestAddInvalidTxToTxPool(t *testing.T) {
   251  	chainDB := dbm.NewDB("tx_pool_test", "leveldb", "tx_pool_test")
   252  	defer os.RemoveAll("tx_pool_test")
   253  
   254  	chain, _, txPool, err := MockChain(chainDB)
   255  	if err != nil {
   256  		t.Fatal(err)
   257  	}
   258  
   259  	if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil {
   260  		t.Fatal(err)
   261  	}
   262  
   263  	block, err := chain.GetBlockByHeight(1)
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  
   268  	//invalid tx, output amount greater than input
   269  	tx, err := CreateTxFromTx(block.Transactions[0], 0, 60000000000, []byte{byte(vm.OP_TRUE)})
   270  	if err != nil {
   271  		t.Fatal(err)
   272  	}
   273  
   274  	if _, err := chain.ValidateTx(tx); err == nil {
   275  		t.Fatalf("add invalid tx to txpool success")
   276  	}
   277  
   278  	if txPool.IsTransactionInPool(&tx.ID) {
   279  		t.Fatalf("add invalid tx to txpool success")
   280  	}
   281  
   282  	if !txPool.IsTransactionInErrCache(&tx.ID) {
   283  		t.Fatalf("can't find invalid tx in txpool err cache")
   284  	}
   285  }