OSDN Git Service

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