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 }