Golang implemented sidechain for Bytom
Revisión | 233b5c6cd4943c1215f93e55530061b3235bb586 (tree) |
---|---|
Tiempo | 2020-02-27 17:30:29 |
Autor | ipqhjjybj <250657661@qq.c...> |
Commiter | ipqhjjybj |
add rollback test
@@ -167,10 +167,12 @@ func TestSaveBlock(t *testing.T) { | ||
167 | 167 | } |
168 | 168 | |
169 | 169 | for i, c := range cases { |
170 | + trans := []*types.Tx{coinbaseTx} | |
170 | 171 | txs := []*bc.Tx{coinbaseTx.Tx} |
171 | 172 | for _, tx := range c.txData { |
172 | 173 | t := types.NewTx(*tx) |
173 | 174 | txs = append(txs, t.Tx) |
175 | + trans = append(trans, t) | |
174 | 176 | } |
175 | 177 | merkleRoot, _ := types.TxMerkleRoot(txs) |
176 | 178 | txStatusHash, _ := types.TxStatusMerkleRoot(c.txStatus.VerifyStatus) |
@@ -184,6 +186,7 @@ func TestSaveBlock(t *testing.T) { | ||
184 | 186 | TransactionStatusHash: txStatusHash, |
185 | 187 | }, |
186 | 188 | }, |
189 | + Transactions: trans, | |
187 | 190 | } |
188 | 191 | |
189 | 192 | if err := store.SaveBlock(block, c.txStatus); err != nil { |
@@ -196,8 +199,16 @@ func TestSaveBlock(t *testing.T) { | ||
196 | 199 | t.Fatal(err) |
197 | 200 | } |
198 | 201 | |
199 | - if !testutil.DeepEqual(gotBlock, block) { | |
200 | - t.Errorf("case %v: block mismatch: have %x, want %x", i, gotBlock, block) | |
202 | + for index, tx := range gotBlock.Transactions { | |
203 | + wantTx := types.NewTx(block.Transactions[index].TxData) | |
204 | + if tx.ID != wantTx.ID { | |
205 | + x1, _ := tx.MarshalText() | |
206 | + x2, _ := block.Transactions[index].MarshalText() | |
207 | + a1 := string(x1) | |
208 | + b1 := string(x2) | |
209 | + | |
210 | + t.Errorf("case %d: transaction %d: block mismatch: have %s, want %s", i, index, a1, b1) | |
211 | + } | |
201 | 212 | } |
202 | 213 | |
203 | 214 | gotStatus, err := store.GetTransactionStatus(&blockHash) |
@@ -1,12 +1,12 @@ | ||
1 | 1 | package database |
2 | 2 | |
3 | 3 | import ( |
4 | - "github.com/golang/protobuf/proto" | |
5 | 4 | dbm "github.com/bytom/vapor/database/leveldb" |
6 | 5 | "github.com/bytom/vapor/database/storage" |
7 | 6 | "github.com/bytom/vapor/errors" |
8 | 7 | "github.com/bytom/vapor/protocol/bc" |
9 | 8 | "github.com/bytom/vapor/protocol/state" |
9 | + "github.com/golang/protobuf/proto" | |
10 | 10 | ) |
11 | 11 | |
12 | 12 | const utxoPreFix = "UT:" |
@@ -1,6 +1,8 @@ | ||
1 | 1 | package protocol |
2 | 2 | |
3 | 3 | import ( |
4 | + "fmt" | |
5 | + | |
4 | 6 | log "github.com/sirupsen/logrus" |
5 | 7 | |
6 | 8 | "github.com/bytom/vapor/errors" |
@@ -223,6 +225,11 @@ func (c *Chain) Rollback(targetHeight uint64) error { | ||
223 | 225 | } |
224 | 226 | |
225 | 227 | startSeq := state.CalcVoteSeq(c.bestBlockHeader.Height) |
228 | + entries := utxoView.Entries | |
229 | + for prevout, entry := range entries { | |
230 | + fmt.Println("final prevout", prevout.String(), entry) | |
231 | + } | |
232 | + | |
226 | 233 | if err = c.setState(targetBlockHeader, setIrrBlockHeader, nil, utxoView, []*state.ConsensusResult{consensusResult.Fork()}); err != nil { |
227 | 234 | return err |
228 | 235 | } |
@@ -6,7 +6,6 @@ import ( | ||
6 | 6 | "testing" |
7 | 7 | |
8 | 8 | "github.com/bytom/vapor/application/mov" |
9 | - "github.com/bytom/vapor/application/mov/common" | |
10 | 9 | movDatabase "github.com/bytom/vapor/application/mov/database" |
11 | 10 | "github.com/bytom/vapor/consensus" |
12 | 11 | "github.com/bytom/vapor/database" |
@@ -36,7 +35,8 @@ func TestRollback(t *testing.T) { | ||
36 | 35 | wantBestBlockHeader *types.BlockHeader |
37 | 36 | wantLastIrrBlockHeader *types.BlockHeader |
38 | 37 | wantBestConsensusResult *state.ConsensusResult |
39 | - wantMovOrders []*common.Order | |
38 | + wantUtxoViewPoint *state.UtxoViewpoint | |
39 | + wantStoredConsensusResult []*state.ConsensusResult | |
40 | 40 | rollbackToTargetHeight uint64 |
41 | 41 | }{ |
42 | 42 | { |
@@ -56,11 +56,10 @@ func TestRollback(t *testing.T) { | ||
56 | 56 | wantLastIrrBlockHeader: &types.BlockHeader{ |
57 | 57 | Height: 0, |
58 | 58 | }, |
59 | - wantMovOrders: []*common.Order{}, | |
60 | 59 | beforeUtxoViewPoint: &state.UtxoViewpoint{ |
61 | 60 | Entries: map[bc.Hash]*storage.UtxoEntry{ |
62 | - testutil.MustDecodeHash("c094bdfd925b4f357a7cb373f8b9ec001181c9217fd7de8219ea1163a1bee93f"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: false}, | |
63 | - testutil.MustDecodeHash("82dc360aaee03b2d42f964befdaf8ab36930e1578d14547da9bd7d23062ecf3c"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true}, | |
61 | + testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true}, | |
62 | + testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true}, | |
64 | 63 | }, |
65 | 64 | }, |
66 | 65 | rollbackToTargetHeight: 0, |
@@ -70,16 +69,14 @@ func TestRollback(t *testing.T) { | ||
70 | 69 | Height: 0, |
71 | 70 | }, |
72 | 71 | Transactions: []*types.Tx{ |
73 | - { | |
74 | - TxData: types.TxData{ | |
75 | - Inputs: []*types.TxInput{ | |
76 | - types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}), | |
77 | - }, | |
78 | - Outputs: []*types.TxOutput{ | |
79 | - types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")), | |
80 | - }, | |
72 | + types.NewTx(types.TxData{ | |
73 | + Inputs: []*types.TxInput{ | |
74 | + types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}), | |
81 | 75 | }, |
82 | - }, | |
76 | + Outputs: []*types.TxOutput{ | |
77 | + types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")), | |
78 | + }, | |
79 | + }), | |
83 | 80 | }, |
84 | 81 | }, |
85 | 82 | { |
@@ -88,16 +85,14 @@ func TestRollback(t *testing.T) { | ||
88 | 85 | PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"), |
89 | 86 | }, |
90 | 87 | Transactions: []*types.Tx{ |
91 | - { | |
92 | - TxData: types.TxData{ | |
93 | - Inputs: []*types.TxInput{ | |
94 | - types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}), | |
95 | - }, | |
96 | - Outputs: []*types.TxOutput{ | |
97 | - types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")), | |
98 | - }, | |
88 | + types.NewTx(types.TxData{ | |
89 | + Inputs: []*types.TxInput{ | |
90 | + types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}), | |
91 | + }, | |
92 | + Outputs: []*types.TxOutput{ | |
93 | + types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")), | |
99 | 94 | }, |
100 | - }, | |
95 | + }), | |
101 | 96 | }, |
102 | 97 | }, |
103 | 98 | }, |
@@ -107,16 +102,14 @@ func TestRollback(t *testing.T) { | ||
107 | 102 | Height: 0, |
108 | 103 | }, |
109 | 104 | Transactions: []*types.Tx{ |
110 | - { | |
111 | - TxData: types.TxData{ | |
112 | - Inputs: []*types.TxInput{ | |
113 | - types.NewSpendInput(nil, bc.NewHash([32]byte{0, 1}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}), | |
114 | - }, | |
115 | - Outputs: []*types.TxOutput{ | |
116 | - types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")), | |
117 | - }, | |
105 | + types.NewTx(types.TxData{ | |
106 | + Inputs: []*types.TxInput{ | |
107 | + types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}), | |
108 | + }, | |
109 | + Outputs: []*types.TxOutput{ | |
110 | + types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")), | |
118 | 111 | }, |
119 | - }, | |
112 | + }), | |
120 | 113 | }, |
121 | 114 | }, |
122 | 115 | }, |
@@ -152,6 +145,23 @@ func TestRollback(t *testing.T) { | ||
152 | 145 | BlockHeight: 0, |
153 | 146 | CoinbaseReward: map[string]uint64{}, |
154 | 147 | }, |
148 | + wantUtxoViewPoint: &state.UtxoViewpoint{ | |
149 | + Entries: map[bc.Hash]*storage.UtxoEntry{ | |
150 | + testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true}, | |
151 | + }, | |
152 | + }, | |
153 | + wantStoredConsensusResult: []*state.ConsensusResult{ | |
154 | + { | |
155 | + Seq: 0, | |
156 | + NumOfVote: map[string]uint64{ | |
157 | + "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000, | |
158 | + "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000, | |
159 | + }, | |
160 | + BlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"), | |
161 | + BlockHeight: 0, | |
162 | + CoinbaseReward: map[string]uint64{}, | |
163 | + }, | |
164 | + }, | |
155 | 165 | }, |
156 | 166 | } |
157 | 167 |
@@ -165,25 +175,19 @@ func TestRollback(t *testing.T) { | ||
165 | 175 | |
166 | 176 | mainChainBlockHeaders := []*types.BlockHeader{} |
167 | 177 | for _, block := range c.beforeStoredBlocks { |
168 | - newTrans := []*types.Tx{} | |
169 | - status := bc.NewTransactionStatus() | |
170 | - for index, tx := range block.Transactions { | |
171 | - status.SetStatus(index, false) | |
172 | - byteData, err := tx.TxData.MarshalText() | |
173 | - if err != nil { | |
174 | - t.Fatal(err) | |
178 | + trans := block.Transactions | |
179 | + for _, tx := range trans { | |
180 | + for _, prevout := range tx.SpentOutputIDs { | |
181 | + fmt.Println(prevout.String()) | |
175 | 182 | } |
176 | - tx.TxData.SerializedSize = uint64(len(byteData)) | |
183 | + } | |
177 | 184 | |
178 | - tx := &types.Tx{TxData: tx.TxData, Tx: types.MapTx(&tx.TxData)} | |
179 | - newTrans = append(newTrans, tx) | |
185 | + status := bc.NewTransactionStatus() | |
186 | + for index := range block.Transactions { | |
187 | + status.SetStatus(index, false) | |
180 | 188 | } |
181 | - block.Transactions = newTrans | |
182 | 189 | store.SaveBlock(block, status) |
183 | 190 | |
184 | - hash := block.Hash() | |
185 | - block, _ := store.GetBlock(&hash) | |
186 | - | |
187 | 191 | mainChainBlockHeaders = append(mainChainBlockHeaders, &block.BlockHeader) |
188 | 192 | } |
189 | 193 |
@@ -217,55 +221,35 @@ func TestRollback(t *testing.T) { | ||
217 | 221 | t.Fatalf("wantBestConsensusResult is not right!") |
218 | 222 | } |
219 | 223 | |
220 | - nowBlocks := []*types.Block{} | |
221 | - for _, block := range c.beforeStoredBlocks { | |
222 | - if block.Height <= c.rollbackToTargetHeight { | |
223 | - gotBlock, err := chain.GetBlockByHeight(block.Height) | |
224 | - if err != nil { | |
225 | - t.Fatal(err) | |
226 | - } | |
227 | - nowBlocks = append(nowBlocks, gotBlock) | |
228 | - } else { | |
229 | - hash := block.Hash() | |
230 | - nowBlock, _ := store.GetBlock(&hash) | |
231 | - if nowBlock != nil { | |
232 | - t.Fatalf("this block height %d should not existed!", block.Height) | |
233 | - } | |
234 | - } | |
235 | - } | |
236 | - | |
237 | - transferBlocks := []*types.Block{} | |
238 | - fmt.Println(nowBlocks, len(nowBlocks)) | |
239 | - fmt.Println(c.wantStoredBlocks, len(c.wantStoredBlocks)) | |
240 | - | |
224 | + transOldTx := []*bc.Tx{} | |
241 | 225 | for _, block := range c.wantStoredBlocks { |
242 | - newTrans := []*types.Tx{} | |
226 | + hash := block.Hash() | |
243 | 227 | for _, tx := range block.Transactions { |
244 | - byteData, err := tx.TxData.MarshalText() | |
245 | - if err != nil { | |
246 | - t.Fatal(err) | |
247 | - } | |
248 | - tx.TxData.SerializedSize = uint64(len(byteData)) | |
228 | + transOldTx = append(transOldTx, tx.Tx) | |
229 | + } | |
230 | + gotBlock, err := store.GetBlock(&hash) | |
231 | + if err != nil { | |
232 | + t.Fatal(err) | |
233 | + } | |
249 | 234 | |
250 | - tx := &types.Tx{TxData: tx.TxData, Tx: types.MapTx(&tx.TxData)} | |
251 | - newTrans = append(newTrans, tx) | |
235 | + if !testutil.DeepEqual(block.BlockHeader, gotBlock.BlockHeader) { | |
236 | + t.Fatalf("this block height %d should existed!", block.Height) | |
252 | 237 | } |
253 | - block.Transactions = newTrans | |
238 | + } | |
254 | 239 | |
255 | - transferBlocks = append(transferBlocks, block) | |
240 | + nowUtxoViewPoint := state.NewUtxoViewpoint() | |
241 | + if err = store.GetTransactionsUtxo(nowUtxoViewPoint, transOldTx); err != nil { | |
242 | + t.Fatal(err) | |
256 | 243 | } |
257 | 244 | |
258 | - block1 := nowBlocks[0] | |
259 | - block2 := transferBlocks[0] | |
260 | - fmt.Println(block1) | |
261 | - fmt.Println(block2) | |
262 | - if !testutil.DeepEqual(nowBlocks, transferBlocks) { | |
263 | - t.Fatalf("blocks is not same") | |
245 | + if !testutil.DeepEqual(nowUtxoViewPoint, c.wantUtxoViewPoint) { | |
246 | + t.Fatal(err) | |
264 | 247 | } |
265 | 248 | |
266 | 249 | blockDB.Close() |
267 | 250 | os.RemoveAll("block_db") |
268 | 251 | movDB.Close() |
269 | 252 | os.RemoveAll("mov_db") |
253 | + | |
270 | 254 | } |
271 | 255 | } |
@@ -0,0 +1,363 @@ | ||
1 | +package test | |
2 | + | |
3 | +import ( | |
4 | + "fmt" | |
5 | + "os" | |
6 | + "testing" | |
7 | + | |
8 | + "github.com/stretchr/testify/require" | |
9 | + | |
10 | + "github.com/bytom/vapor/application/mov" | |
11 | + movDatabase "github.com/bytom/vapor/application/mov/database" | |
12 | + "github.com/bytom/vapor/consensus" | |
13 | + "github.com/bytom/vapor/database" | |
14 | + dbm "github.com/bytom/vapor/database/leveldb" | |
15 | + "github.com/bytom/vapor/database/storage" | |
16 | + "github.com/bytom/vapor/protocol" | |
17 | + "github.com/bytom/vapor/protocol/bc" | |
18 | + "github.com/bytom/vapor/protocol/bc/types" | |
19 | + "github.com/bytom/vapor/protocol/state" | |
20 | + "github.com/bytom/vapor/testutil" | |
21 | +) | |
22 | + | |
23 | +func compareDBSame(t *testing.T, dbA dbm.DB, dbB dbm.DB) bool { | |
24 | + iterA := dbA.Iterator() | |
25 | + iterB := dbB.Iterator() | |
26 | + | |
27 | + for iterA.Next() && iterB.Next() { | |
28 | + require.Equal(t, iterA.Key(), iterB.Key()) | |
29 | + require.Equal(t, iterA.Value(), iterB.Value()) | |
30 | + } | |
31 | + | |
32 | + if iterA.Next() || iterB.Next() { | |
33 | + t.Fatalf("why iterator is not finished") | |
34 | + } | |
35 | + | |
36 | + return true | |
37 | +} | |
38 | + | |
39 | +func ATestSmall(t *testing.T) { | |
40 | + wantStoredBlocks := []*types.Block{ | |
41 | + { | |
42 | + BlockHeader: types.BlockHeader{ | |
43 | + Height: 0, | |
44 | + }, | |
45 | + Transactions: []*types.Tx{ | |
46 | + types.NewTx(types.TxData{ | |
47 | + Inputs: []*types.TxInput{ | |
48 | + types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}), | |
49 | + }, | |
50 | + Outputs: []*types.TxOutput{ | |
51 | + types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")), | |
52 | + }, | |
53 | + }), | |
54 | + }, | |
55 | + }, | |
56 | + { | |
57 | + BlockHeader: types.BlockHeader{ | |
58 | + Height: 1, | |
59 | + }, | |
60 | + Transactions: []*types.Tx{ | |
61 | + types.NewTx(types.TxData{ | |
62 | + Inputs: []*types.TxInput{ | |
63 | + types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}), | |
64 | + }, | |
65 | + Outputs: []*types.TxOutput{ | |
66 | + types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")), | |
67 | + }, | |
68 | + }), | |
69 | + }, | |
70 | + }, | |
71 | + } | |
72 | + | |
73 | + dbA := dbm.NewDB("dba", "leveldb", "dba") | |
74 | + storeA := database.NewStore(dbA) | |
75 | + status := bc.NewTransactionStatus() | |
76 | + status.SetStatus(0, false) | |
77 | + | |
78 | + storeA.SaveBlock(wantStoredBlocks[0], status) | |
79 | + | |
80 | + //hash := wantStoredBlocks[0].Hash() | |
81 | + // block, _ := storeA.GetBlock(&hash) | |
82 | + // fmt.Println("!!!!!!!!!!", block) | |
83 | + // fmt.Println("????????", wantStoredBlocks[0]) | |
84 | + | |
85 | + //fmt.Println("amazing!") | |
86 | + | |
87 | + dbB := dbm.NewDB("dbb", "leveldb", "dbb") | |
88 | + storeB := database.NewStore(dbB) | |
89 | + storeB.SaveBlock(wantStoredBlocks[0], status) | |
90 | + storeB.SaveBlock(wantStoredBlocks[1], status) | |
91 | + | |
92 | + storeB.DeleteBlock(wantStoredBlocks[1]) | |
93 | + | |
94 | + compareDBSame(t, dbA, dbB) | |
95 | + dbA.Close() | |
96 | + dbB.Close() | |
97 | + os.RemoveAll("dba") | |
98 | + os.RemoveAll("dbb") | |
99 | +} | |
100 | + | |
101 | +func ATestRollback(t *testing.T) { | |
102 | + // 1-->0 | |
103 | + // 2-->0 | |
104 | + // 2-->1 | |
105 | + // 1200 个区块回滚 , 1201--> 1199 , 1201-->1200, 1200->1199 | |
106 | + cases := []struct { | |
107 | + desc string | |
108 | + movStartHeight uint64 | |
109 | + beforeBestBlockHeader *types.BlockHeader | |
110 | + beforeLastIrrBlockHeader *types.BlockHeader | |
111 | + beforeUtxoViewPoint *state.UtxoViewpoint | |
112 | + beforeStoredBlocks []*types.Block | |
113 | + beforeStoredConsensusResult []*state.ConsensusResult | |
114 | + wantStoredBlocks []*types.Block | |
115 | + wantBestBlockHeader *types.BlockHeader | |
116 | + wantLastIrrBlockHeader *types.BlockHeader | |
117 | + wantBestConsensusResult *state.ConsensusResult | |
118 | + wantUtxoViewPoint *state.UtxoViewpoint | |
119 | + wantStoredConsensusResult []*state.ConsensusResult | |
120 | + rollbackToTargetHeight uint64 | |
121 | + }{ | |
122 | + { | |
123 | + desc: "rollback from height 1 to 0", | |
124 | + movStartHeight: 10, | |
125 | + beforeBestBlockHeader: &types.BlockHeader{ | |
126 | + Height: 1, | |
127 | + PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"), | |
128 | + }, | |
129 | + wantBestBlockHeader: &types.BlockHeader{ | |
130 | + Height: 0, | |
131 | + }, | |
132 | + beforeLastIrrBlockHeader: &types.BlockHeader{ | |
133 | + Height: 1, | |
134 | + PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"), | |
135 | + }, | |
136 | + wantLastIrrBlockHeader: &types.BlockHeader{ | |
137 | + Height: 0, | |
138 | + }, | |
139 | + beforeUtxoViewPoint: &state.UtxoViewpoint{ | |
140 | + Entries: map[bc.Hash]*storage.UtxoEntry{ | |
141 | + testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: true}, | |
142 | + testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true}, | |
143 | + }, | |
144 | + }, | |
145 | + rollbackToTargetHeight: 0, | |
146 | + beforeStoredBlocks: []*types.Block{ | |
147 | + { | |
148 | + BlockHeader: types.BlockHeader{ | |
149 | + Height: 0, | |
150 | + }, | |
151 | + Transactions: []*types.Tx{ | |
152 | + types.NewTx(types.TxData{ | |
153 | + Inputs: []*types.TxInput{ | |
154 | + types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}), | |
155 | + }, | |
156 | + Outputs: []*types.TxOutput{ | |
157 | + types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")), | |
158 | + }, | |
159 | + }), | |
160 | + }, | |
161 | + }, | |
162 | + { | |
163 | + BlockHeader: types.BlockHeader{ | |
164 | + Height: 1, | |
165 | + PreviousBlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"), | |
166 | + }, | |
167 | + Transactions: []*types.Tx{ | |
168 | + types.NewTx(types.TxData{ | |
169 | + Inputs: []*types.TxInput{ | |
170 | + types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 2000, 0, []byte{0, 1}), | |
171 | + }, | |
172 | + Outputs: []*types.TxOutput{ | |
173 | + types.NewVoteOutput(*consensus.BTMAssetID, 2000, []byte{0, 1}, testutil.MustDecodeHexString("b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9")), | |
174 | + }, | |
175 | + }), | |
176 | + }, | |
177 | + }, | |
178 | + }, | |
179 | + wantStoredBlocks: []*types.Block{ | |
180 | + { | |
181 | + BlockHeader: types.BlockHeader{ | |
182 | + Height: 0, | |
183 | + }, | |
184 | + Transactions: []*types.Tx{ | |
185 | + types.NewTx(types.TxData{ | |
186 | + Inputs: []*types.TxInput{ | |
187 | + types.NewSpendInput(nil, bc.NewHash([32]byte{8}), *consensus.BTMAssetID, 1000, 0, []byte{0, 1}), | |
188 | + }, | |
189 | + Outputs: []*types.TxOutput{ | |
190 | + types.NewVoteOutput(*consensus.BTMAssetID, 1000, []byte{0, 1}, testutil.MustDecodeHexString("36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67")), | |
191 | + }, | |
192 | + }), | |
193 | + }, | |
194 | + }, | |
195 | + }, | |
196 | + beforeStoredConsensusResult: []*state.ConsensusResult{ | |
197 | + { | |
198 | + Seq: 1, | |
199 | + NumOfVote: map[string]uint64{ | |
200 | + "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100002000, | |
201 | + "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000, | |
202 | + }, | |
203 | + BlockHash: testutil.MustDecodeHash("52463075c66259098f2a1fa711288cf3b866d7c57b4a7a78cd22a1dcd69a0514"), | |
204 | + BlockHeight: 1, | |
205 | + CoinbaseReward: map[string]uint64{"0001": consensus.BlockSubsidy(1) + 10000000000}, | |
206 | + }, | |
207 | + { | |
208 | + Seq: 0, | |
209 | + NumOfVote: map[string]uint64{ | |
210 | + "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000, | |
211 | + "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000, | |
212 | + }, | |
213 | + BlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"), | |
214 | + BlockHeight: 0, | |
215 | + CoinbaseReward: map[string]uint64{}, | |
216 | + }, | |
217 | + }, | |
218 | + wantBestConsensusResult: &state.ConsensusResult{ | |
219 | + Seq: 0, | |
220 | + NumOfVote: map[string]uint64{ | |
221 | + "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000, | |
222 | + "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000, | |
223 | + }, | |
224 | + BlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"), | |
225 | + BlockHeight: 0, | |
226 | + CoinbaseReward: map[string]uint64{}, | |
227 | + }, | |
228 | + wantUtxoViewPoint: &state.UtxoViewpoint{ | |
229 | + Entries: map[bc.Hash]*storage.UtxoEntry{ | |
230 | + testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 1, Spent: false}, | |
231 | + testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba"): &storage.UtxoEntry{Type: storage.VoteUTXOType, BlockHeight: 0, Spent: true}, | |
232 | + }, | |
233 | + }, | |
234 | + wantStoredConsensusResult: []*state.ConsensusResult{ | |
235 | + { | |
236 | + Seq: 0, | |
237 | + NumOfVote: map[string]uint64{ | |
238 | + "b7f463446a31b3792cd168d52b7a89b3657bca3e25d6854db1488c389ab6fc8d538155c25c1ee6975cc7def19710908c7d9b7463ca34a22058b456b45e498db9": 100000000, | |
239 | + "36695997983028c279c3360ca345a90e3af1f9e3df2506119fca31cdc844be31630f9a421f4d1658e15d67a15ce29c36332dd45020d2a0147fcce4949ccd9a67": 100002000, | |
240 | + }, | |
241 | + BlockHash: testutil.MustDecodeHash("39dee75363127a2857f554d2ad2706eb876407a2e09fbe0338683ca4ad4c2f90"), | |
242 | + BlockHeight: 0, | |
243 | + CoinbaseReward: map[string]uint64{}, | |
244 | + }, | |
245 | + }, | |
246 | + }, | |
247 | + } | |
248 | + | |
249 | + for _, c := range cases { | |
250 | + movDB := dbm.NewDB("mov_db", "leveldb", "mov_db") | |
251 | + movStore := movDatabase.NewLevelDBMovStore(movDB) | |
252 | + | |
253 | + movCore := mov.NewMovCoreWithDB(movStore, c.movStartHeight) | |
254 | + blockDB := dbm.NewDB("block_db", "leveldb", "block_db") | |
255 | + store := database.NewStore(blockDB) | |
256 | + | |
257 | + compareDB := dbm.NewDB("compare_block_db", "leveldb", "compare_block_db") | |
258 | + compareStore := database.NewStore(compareDB) | |
259 | + | |
260 | + mainChainBlockHeaders := []*types.BlockHeader{} | |
261 | + for _, block := range c.beforeStoredBlocks { | |
262 | + trans := block.Transactions | |
263 | + for _, tx := range trans { | |
264 | + for _, prevout := range tx.SpentOutputIDs { | |
265 | + fmt.Println(prevout.String()) | |
266 | + } | |
267 | + } | |
268 | + | |
269 | + status := bc.NewTransactionStatus() | |
270 | + for index := range block.Transactions { | |
271 | + status.SetStatus(index, false) | |
272 | + } | |
273 | + store.SaveBlock(block, status) | |
274 | + | |
275 | + mainChainBlockHeaders = append(mainChainBlockHeaders, &block.BlockHeader) | |
276 | + } | |
277 | + | |
278 | + wantMainChainBlockHeaders := []*types.BlockHeader{} | |
279 | + for _, block := range c.wantStoredBlocks { | |
280 | + status := bc.NewTransactionStatus() | |
281 | + for index := range block.Transactions { | |
282 | + status.SetStatus(index, false) | |
283 | + } | |
284 | + compareStore.SaveBlock(block, status) | |
285 | + | |
286 | + wantMainChainBlockHeaders = append(wantMainChainBlockHeaders, &block.BlockHeader) | |
287 | + } | |
288 | + | |
289 | + if err := store.SaveChainStatus(c.beforeBestBlockHeader, c.beforeLastIrrBlockHeader, mainChainBlockHeaders, c.beforeUtxoViewPoint, c.beforeStoredConsensusResult); err != nil { | |
290 | + t.Fatal(err) | |
291 | + } | |
292 | + | |
293 | + if err := compareStore.SaveChainStatus(c.wantBestBlockHeader, c.wantLastIrrBlockHeader, wantMainChainBlockHeaders, c.wantUtxoViewPoint, c.wantStoredConsensusResult); err != nil { | |
294 | + t.Fatal(err) | |
295 | + } | |
296 | + | |
297 | + chain, err := protocol.NewChain(store, nil, []protocol.Protocoler{movCore}, nil) | |
298 | + if err != nil { | |
299 | + t.Fatal(err) | |
300 | + } | |
301 | + | |
302 | + if err := chain.Rollback(c.rollbackToTargetHeight); err != nil { | |
303 | + t.Fatal(err) | |
304 | + } | |
305 | + | |
306 | + hash := testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba") | |
307 | + utxo, err := store.GetUtxo(&hash) | |
308 | + fmt.Println("store e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba", utxo, err) | |
309 | + | |
310 | + hash = testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06") | |
311 | + utxo, err = store.GetUtxo(&hash) | |
312 | + fmt.Println("store 51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06", utxo, err) | |
313 | + | |
314 | + hash = testutil.MustDecodeHash("e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba") | |
315 | + utxo, err = compareStore.GetUtxo(&hash) | |
316 | + fmt.Println("compareStore e2370262a129b90174195a76c298d872a56af042eae17657e154bcc46d41b3ba", utxo, err) | |
317 | + | |
318 | + hash = testutil.MustDecodeHash("51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06") | |
319 | + utxo, err = compareStore.GetUtxo(&hash) | |
320 | + fmt.Println("compareStore 51f538be366172bed5359a016dce26b952024c9607caf6af609ad723982c2e06", utxo, err) | |
321 | + | |
322 | + if !testutil.DeepEqual(chain.LastIrreversibleHeader(), c.wantLastIrrBlockHeader) { | |
323 | + t.Fatalf("lastIrrBlockHeader is not right!") | |
324 | + } | |
325 | + | |
326 | + if !testutil.DeepEqual(chain.BestBlockHeader(), c.wantBestBlockHeader) { | |
327 | + t.Fatalf("wantBestBlockHeader is not right!") | |
328 | + } | |
329 | + | |
330 | + nowConsensusResult, err := chain.GetConsensusResultByHash(chain.BestBlockHash()) | |
331 | + if err != nil { | |
332 | + t.Fatal(err) | |
333 | + } | |
334 | + | |
335 | + if !testutil.DeepEqual(nowConsensusResult, c.wantBestConsensusResult) { | |
336 | + t.Fatalf("wantBestConsensusResult is not right!") | |
337 | + } | |
338 | + | |
339 | + if !compareDBSame(t, blockDB, compareDB) { | |
340 | + t.Fatalf("the db is not same") | |
341 | + } | |
342 | + | |
343 | + for _, block := range c.wantStoredBlocks { | |
344 | + hash := block.Hash() | |
345 | + gotBlock, err := store.GetBlock(&hash) | |
346 | + if err != nil { | |
347 | + t.Fatal(err) | |
348 | + } | |
349 | + | |
350 | + if !testutil.DeepEqual(block.BlockHeader, gotBlock.BlockHeader) { | |
351 | + t.Fatalf("this block height %d should existed!", block.Height) | |
352 | + } | |
353 | + } | |
354 | + | |
355 | + blockDB.Close() | |
356 | + os.RemoveAll("block_db") | |
357 | + movDB.Close() | |
358 | + os.RemoveAll("mov_db") | |
359 | + | |
360 | + compareDB.Close() | |
361 | + os.RemoveAll("compare_block_db") | |
362 | + } | |
363 | +} |