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 }