OSDN Git Service

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