8 "github.com/bytom/config"
9 "github.com/bytom/consensus"
10 "github.com/bytom/database"
11 "github.com/bytom/database/storage"
12 "github.com/bytom/protocol"
13 "github.com/bytom/protocol/bc"
14 "github.com/bytom/protocol/bc/types"
15 "github.com/bytom/protocol/state"
16 "github.com/bytom/testutil"
19 var blockMap map[int][]*attachBlock
21 type attachBlock struct {
23 verifyResult []*bc.TxVerifyResult
27 consensus.ActiveNetParams = consensus.SoloNetParams
29 blockMap = map[int][]*attachBlock{
32 block: config.GenesisBlock(),
33 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}},
39 BlockHeader: types.BlockHeader{
42 Timestamp: 1556431597,
44 Bits: 2305843009214532812,
45 PreviousBlockHash: testutil.MustDecodeHash("ce4fe9431cd0225b3a811f8f8ec922f2b07a921bb12a8dddae9a85540072c770"),
47 Transactions: []*types.Tx{
48 types.NewTx(types.TxData{
52 Inputs: []*types.TxInput{
53 types.NewCoinbaseInput(testutil.MustDecodeHexString("0031")),
55 Outputs: []*types.TxOutput{
56 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
61 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}},
65 BlockHeader: types.BlockHeader{
68 Timestamp: 1556431697,
70 Bits: 2305843009214532812,
71 PreviousBlockHash: testutil.MustDecodeHash("ce4fe9431cd0225b3a811f8f8ec922f2b07a921bb12a8dddae9a85540072c770"),
73 Transactions: []*types.Tx{
74 types.NewTx(types.TxData{
78 Inputs: []*types.TxInput{
79 types.NewCoinbaseInput(testutil.MustDecodeHexString("0031")),
81 Outputs: []*types.TxOutput{
82 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("00143d05e891b165b165afefa2e861e83a9745f80d8c")),
87 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}},
91 // only has coinbase transaction
94 BlockHeader: types.BlockHeader{
97 Timestamp: 1556431604,
99 Bits: 2305843009214532812,
100 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"),
102 Transactions: []*types.Tx{
103 types.NewTx(types.TxData{
107 Inputs: []*types.TxInput{
108 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")),
110 Outputs: []*types.TxOutput{
111 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
116 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}},
118 // with spend btm transaction
121 BlockHeader: types.BlockHeader{
124 Timestamp: 1556431604,
126 Bits: 2305843009214532812,
127 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"),
129 Transactions: []*types.Tx{
130 types.NewTx(types.TxData{
134 Inputs: []*types.TxInput{
135 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")),
137 Outputs: []*types.TxOutput{
138 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
141 types.NewTx(types.TxData{
144 Inputs: []*types.TxInput{
147 testutil.MustDecodeHexString("7b4082c9d745c3f07dd07afb1f987960d2ef3ea2486741c3f3184751485f77d046df6670eba21020fcf9c7987c0c938384320dc21b0e116c62ae2597cb1fe109"),
148 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"),
150 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"),
151 *consensus.BTMAssetID, 10000000000, 0,
152 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"),
155 Outputs: []*types.TxOutput{
156 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("00143d05e891b165b165afefa2e861e83a9745f80d8c")),
161 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}},
163 // with btm retire transaction
166 BlockHeader: types.BlockHeader{
169 Timestamp: 1556431607,
171 Bits: 2305843009214532812,
172 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"),
174 Transactions: []*types.Tx{
175 types.NewTx(types.TxData{
179 Inputs: []*types.TxInput{
180 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")),
182 Outputs: []*types.TxOutput{
183 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
186 types.NewTx(types.TxData{
189 Inputs: []*types.TxInput{
192 testutil.MustDecodeHexString("302035b362d80419cfed12cfc7d33d2ff7638c589ee2cf6573eb14b4d8cb4a63d7d1302589666dd6d1cd08185dbb2842407f3980bc2564705eda15680c984c05"),
193 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"),
195 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"),
196 *consensus.BTMAssetID, 10000000000, 0,
197 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"),
200 Outputs: []*types.TxOutput{
201 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("6a")), // retire
206 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}},
208 // with issuance transaction
211 BlockHeader: types.BlockHeader{
214 Timestamp: 1556431607,
216 Bits: 2305843009214532812,
217 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"),
219 Transactions: []*types.Tx{
220 types.NewTx(types.TxData{
224 Inputs: []*types.TxInput{
225 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")),
227 Outputs: []*types.TxOutput{
228 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
231 types.NewTx(types.TxData{
234 Inputs: []*types.TxInput{
237 testutil.MustDecodeHexString("46cbb829b6a5bb9fc436c8e51bcbd9f0b3ed99ce97b2e0fac28879b4202c5a9eccaae39a4d18584f789a9427af3a2f09ff0360fb187e46ef172146a9b957ef0c"),
238 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"),
240 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"),
241 *consensus.BTMAssetID, 10000000000, 0,
242 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"),
244 types.NewIssuanceInput(
245 testutil.MustDecodeHexString("fd0aec4229deb281"),
247 testutil.MustDecodeHexString("ae20f25e8b73ffbc3a42300a43279fdf612d79e1936a6c614fc05a5adec9bba42dcd5151ad"),
248 [][]byte{testutil.MustDecodeHexString("df9fabf4636904e017eefb7cdf2b4f08e29efbd4cfc41fe5b01a453191f0913489b19ad74272145824e92bd4843e91140cc5d1a6256f84981d1437ed4566a60b")},
249 testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
252 Outputs: []*types.TxOutput{
253 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
254 types.NewTxOutput(testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
259 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}},
261 // with issuance transaction but status fail is true
264 BlockHeader: types.BlockHeader{
267 Timestamp: 1556431607,
269 Bits: 2305843009214532812,
270 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"),
272 Transactions: []*types.Tx{
273 types.NewTx(types.TxData{
277 Inputs: []*types.TxInput{
278 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")),
280 Outputs: []*types.TxOutput{
281 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
284 types.NewTx(types.TxData{
287 Inputs: []*types.TxInput{
290 testutil.MustDecodeHexString("46cbb829b6a5bb9fc436c8e51bcbd9f0b3ed99ce97b2e0fac28879b4202c5a9eccaae39a4d18584f789a9427af3a2f09ff0360fb187e46ef172146a9b957ef0c"),
291 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"),
293 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"),
294 *consensus.BTMAssetID, 10000000000, 0,
295 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"),
297 types.NewIssuanceInput(
298 testutil.MustDecodeHexString("fd0aec4229deb281"),
300 testutil.MustDecodeHexString("ae20f25e8b73ffbc3a42300a43279fdf612d79e1936a6c614fc05a5adec9bba42dcd5151ad"),
302 [][]byte{testutil.MustDecodeHexString("df9fabf4636904e017eefb7cdf2b4f08e29efbd4cfc41fe5b01a453191f0913489b19ad74272145824e92bd4843e91140cc5d1a6256f84981d1437ed4566a60c")},
303 testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"),
306 Outputs: []*types.TxOutput{
307 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
308 types.NewTxOutput(testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
313 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: true}},
315 // with non btm transaction
318 BlockHeader: types.BlockHeader{
321 Timestamp: 1556431607,
323 Bits: 2305843009214532812,
324 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"),
326 Transactions: []*types.Tx{
327 types.NewTx(types.TxData{
331 Inputs: []*types.TxInput{
332 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")),
334 Outputs: []*types.TxOutput{
335 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
338 types.NewTx(types.TxData{
341 Inputs: []*types.TxInput{
344 testutil.MustDecodeHexString("afc4e24f0e0383e3fd78af3de189be3913faddbbd8cac8a8c9316bf9eb0866e83df3618cf4c7b4d091a79968a16377d422cbd8011f1f5e75ba201e173b68ad02"),
345 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"),
347 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"),
348 *consensus.BTMAssetID, 10000000000, 0,
349 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"),
353 testutil.MustDecodeHexString("cd6fb451102db667341438f20dbeabd30b343ed08d89625a8e27e82478e89ddea9e7d51f8a4036e0cc2602ac5fae0bdbfda025a0e2c12e3ddc8100b62461670b"),
354 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"),
356 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f22"),
357 testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, 1,
358 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"),
361 Outputs: []*types.TxOutput{
362 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
363 types.NewTxOutput(testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
368 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}},
370 // with non btm transaction but status fail is true
373 BlockHeader: types.BlockHeader{
376 Timestamp: 1556431607,
378 Bits: 2305843009214532812,
379 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"),
381 Transactions: []*types.Tx{
382 types.NewTx(types.TxData{
386 Inputs: []*types.TxInput{
387 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")),
389 Outputs: []*types.TxOutput{
390 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
393 types.NewTx(types.TxData{
396 Inputs: []*types.TxInput{
399 testutil.MustDecodeHexString("afc4e24f0e0383e3fd78af3de189be3913faddbbd8cac8a8c9316bf9eb0866e83df3618cf4c7b4d091a79968a16377d422cbd8011f1f5e75ba201e173b68ad02"),
400 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"),
402 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"),
403 *consensus.BTMAssetID, 10000000000, 0,
404 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"),
409 testutil.MustDecodeHexString("cd6fb451102db667341438f20dbeabd30b343ed08d89625a8e27e82478e89ddea9e7d51f8a4036e0cc2602ac5fae0bdbfda025a0e2c12e3ddc8100b62461670c"),
410 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"),
412 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f22"),
413 testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, 1,
414 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"),
417 Outputs: []*types.TxOutput{
418 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
419 types.NewTxOutput(testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
424 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: true}},
428 // the previous block is blockMap[2][0]
431 BlockHeader: types.BlockHeader{
434 Timestamp: 1556431640,
436 Bits: 2305843009214532812,
437 PreviousBlockHash: testutil.MustDecodeHash("09c6064f4f1e7325440c45df03e97f97dbfbb66033315a384308256038af6c30"),
439 Transactions: []*types.Tx{
440 types.NewTx(types.TxData{
444 Inputs: []*types.TxInput{
445 types.NewCoinbaseInput(testutil.MustDecodeHexString("0033")),
447 Outputs: []*types.TxOutput{
448 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
453 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}},
455 // the previous block is blockMap[2][2]
458 BlockHeader: types.BlockHeader{
461 Timestamp: 1556431640,
463 Bits: 2305843009214532812,
464 PreviousBlockHash: testutil.MustDecodeHash("33f56264283cc12e3b232068caa13c1fd052c21b231a94e8c0a40bac25629f88"),
466 Transactions: []*types.Tx{
467 types.NewTx(types.TxData{
471 Inputs: []*types.TxInput{
472 types.NewCoinbaseInput(testutil.MustDecodeHexString("0033")),
474 Outputs: []*types.TxOutput{
475 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")),
480 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}},
485 mustPostProcessBlock()
488 func TestProcessBlock(t *testing.T) {
489 cases := []*processBlockTestCase{
491 desc: "process a invalid block",
492 newBlock: &types.Block{
493 BlockHeader: types.BlockHeader{
496 Bits: 2305843009214532812,
497 PreviousBlockHash: blockMap[0][0].block.Hash(),
500 wantStore: createStoreItems([]int{0}, []*attachBlock{blockMap[0][0]}),
501 wantBlockIndex: state.NewBlockIndexWithData(
502 map[bc.Hash]*state.BlockNode{
503 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
506 mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil),
509 wantOrphanManage: protocol.NewOrphanManage(),
513 desc: "process a orphan block normally",
514 newBlock: blockMap[2][0].block,
515 wantStore: createStoreItems([]int{0}, []*attachBlock{blockMap[0][0]}),
516 wantBlockIndex: state.NewBlockIndexWithData(
517 map[bc.Hash]*state.BlockNode{
518 blockMap[0][0].block.Hash(): mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil),
521 mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil),
524 wantOrphanManage: protocol.NewOrphanManageWithData(
525 map[bc.Hash]*protocol.OrphanBlock{blockMap[2][0].block.Hash(): {Block: blockMap[2][0].block}},
526 map[bc.Hash][]*bc.Hash{blockMap[2][0].block.PreviousBlockHash: {hashPtr(blockMap[2][0].block.Hash())}},
532 desc: "attach a block normally",
533 newBlock: blockMap[1][0].block,
534 wantStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0]}),
535 wantBlockIndex: state.NewBlockIndexWithData(
536 map[bc.Hash]*state.BlockNode{
537 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
538 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
541 mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil),
542 mustNewBlockNode(&blockMap[1][0].block.BlockHeader, mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil)),
545 wantOrphanManage: protocol.NewOrphanManage(),
550 desc: "init genesis block from db",
551 newBlock: blockMap[1][0].block,
552 initStore: createStoreItems([]int{0}, []*attachBlock{blockMap[0][0]}),
553 wantStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0]}),
554 wantBlockIndex: state.NewBlockIndexWithData(
555 map[bc.Hash]*state.BlockNode{
556 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
557 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
560 mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil),
561 mustNewBlockNode(&blockMap[1][0].block.BlockHeader, mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil)),
564 wantOrphanManage: protocol.NewOrphanManage(),
569 desc: "attach a block to fork chain normally, not rollback",
570 newBlock: blockMap[2][0].block,
571 initStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[1][1]}),
572 wantStore: createStoreItems([]int{0, 1, 3}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[1][1], blockMap[2][0]}),
573 wantBlockIndex: state.NewBlockIndexWithData(
574 map[bc.Hash]*state.BlockNode{
575 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
576 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
577 blockMap[1][1].block.Hash(): mustCreateBlockNode(&blockMap[1][1].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
578 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
581 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
582 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
583 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
586 wantOrphanManage: protocol.NewOrphanManage(),
591 desc: "attach a block with btm transaction normally",
592 newBlock: blockMap[2][1].block,
593 initStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0]}, &storeItem{
594 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
595 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
597 wantStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][1]}, &storeItem{
598 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
599 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
601 wantBlockIndex: state.NewBlockIndexWithData(
602 map[bc.Hash]*state.BlockNode{
603 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
604 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
605 blockMap[2][1].block.Hash(): mustCreateBlockNode(&blockMap[2][1].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
608 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
609 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
610 mustCreateBlockNode(&blockMap[2][1].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
613 wantOrphanManage: protocol.NewOrphanManage(),
618 desc: "attach a block with retire transaction normally",
619 newBlock: blockMap[2][2].block,
620 initStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0]}, &storeItem{
621 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
622 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
624 wantStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][2]}, &storeItem{
625 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
626 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
628 wantBlockIndex: state.NewBlockIndexWithData(
629 map[bc.Hash]*state.BlockNode{
630 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
631 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
632 blockMap[2][2].block.Hash(): mustCreateBlockNode(&blockMap[2][2].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
635 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
636 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
637 mustCreateBlockNode(&blockMap[2][2].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
640 wantOrphanManage: protocol.NewOrphanManage(),
645 desc: "attach a block with issuance transaction normally",
646 newBlock: blockMap[2][3].block,
647 initStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0]}, &storeItem{
648 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
649 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
651 wantStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][3]}, &storeItem{
652 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
653 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
655 wantBlockIndex: state.NewBlockIndexWithData(
656 map[bc.Hash]*state.BlockNode{
657 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
658 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
659 blockMap[2][3].block.Hash(): mustCreateBlockNode(&blockMap[2][3].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
662 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
663 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
664 mustCreateBlockNode(&blockMap[2][3].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
667 wantOrphanManage: protocol.NewOrphanManage(),
672 desc: "attach a block with issuance transaction but status fail is true",
673 newBlock: blockMap[2][4].block,
674 initStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0]}, &storeItem{
675 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
676 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
678 wantStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][4]}, &storeItem{
679 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
680 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
682 wantBlockIndex: state.NewBlockIndexWithData(
683 map[bc.Hash]*state.BlockNode{
684 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
685 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
686 blockMap[2][4].block.Hash(): mustCreateBlockNode(&blockMap[2][4].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
689 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
690 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
691 mustCreateBlockNode(&blockMap[2][4].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
694 wantOrphanManage: protocol.NewOrphanManage(),
699 desc: "attach a block with non btm transaction",
700 newBlock: blockMap[2][5].block,
701 initStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0]}, &storeItem{
702 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
703 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
705 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
706 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
708 wantStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][5]}, &storeItem{
709 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
710 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
712 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
713 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
715 wantBlockIndex: state.NewBlockIndexWithData(
716 map[bc.Hash]*state.BlockNode{
717 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
718 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
719 blockMap[2][5].block.Hash(): mustCreateBlockNode(&blockMap[2][5].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
722 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
723 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
724 mustCreateBlockNode(&blockMap[2][5].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
727 wantOrphanManage: protocol.NewOrphanManage(),
732 desc: "attach a block with non btm transaction but status fail is true",
733 newBlock: blockMap[2][6].block,
734 initStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][0]}, &storeItem{
735 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
736 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
738 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
739 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
741 wantStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][6]}, &storeItem{
742 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
743 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
745 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
746 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
748 wantBlockIndex: state.NewBlockIndexWithData(
749 map[bc.Hash]*state.BlockNode{
750 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
751 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
752 blockMap[2][6].block.Hash(): mustCreateBlockNode(&blockMap[2][6].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
755 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
756 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
757 mustCreateBlockNode(&blockMap[2][6].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
760 wantOrphanManage: protocol.NewOrphanManage(),
765 desc: "rollback a block only has coinbase transaction",
766 newBlock: blockMap[2][0].block,
767 initStore: createStoreItems([]int{0, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[1][1]}),
768 wantStore: createStoreItems([]int{0, 1, 3}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[1][1], blockMap[2][0]}),
769 wantBlockIndex: state.NewBlockIndexWithData(
770 map[bc.Hash]*state.BlockNode{
771 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
772 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
773 blockMap[1][1].block.Hash(): mustCreateBlockNode(&blockMap[1][1].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
774 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
777 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
778 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
779 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
782 wantOrphanManage: protocol.NewOrphanManage(),
787 desc: "rollback a block has spend btm transaction",
788 newBlock: blockMap[3][0].block,
789 initStore: createStoreItems([]int{0, 1, 3}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][1]}, &storeItem{
790 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
791 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
793 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][1], blockMap[3][0]}, &storeItem{
794 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
795 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
797 wantBlockIndex: state.NewBlockIndexWithData(
798 map[bc.Hash]*state.BlockNode{
799 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
800 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
801 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
802 blockMap[2][1].block.Hash(): mustCreateBlockNode(&blockMap[2][1].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
803 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
806 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
807 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
808 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
809 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
812 wantOrphanManage: protocol.NewOrphanManage(),
817 desc: "rollback a block has issuance transaction",
818 newBlock: blockMap[3][0].block,
819 initStore: createStoreItems([]int{0, 1, 3}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][3]}, &storeItem{
820 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
821 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
823 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][3], blockMap[3][0]}, &storeItem{
824 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
825 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
827 wantBlockIndex: state.NewBlockIndexWithData(
828 map[bc.Hash]*state.BlockNode{
829 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
830 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
831 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
832 blockMap[2][3].block.Hash(): mustCreateBlockNode(&blockMap[2][3].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
833 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
836 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
837 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
838 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
839 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
842 wantOrphanManage: protocol.NewOrphanManage(),
847 desc: "rollback a block has issuance transaction but status fail is true",
848 newBlock: blockMap[3][0].block,
849 initStore: createStoreItems([]int{0, 1, 3}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][4]}, &storeItem{
850 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
851 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
853 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][4], blockMap[3][0]}, &storeItem{
854 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
855 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
857 wantBlockIndex: state.NewBlockIndexWithData(
858 map[bc.Hash]*state.BlockNode{
859 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
860 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
861 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
862 blockMap[2][4].block.Hash(): mustCreateBlockNode(&blockMap[2][4].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
863 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
866 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
867 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
868 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
869 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
872 wantOrphanManage: protocol.NewOrphanManage(),
877 desc: "rollback a block has spend non btm",
878 newBlock: blockMap[3][0].block,
879 initStore: createStoreItems([]int{0, 1, 3}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][5]}, &storeItem{
880 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
881 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
883 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
884 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
886 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][5], blockMap[3][0]}, &storeItem{
887 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
888 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
890 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
891 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
893 wantBlockIndex: state.NewBlockIndexWithData(
894 map[bc.Hash]*state.BlockNode{
895 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
896 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
897 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
898 blockMap[2][5].block.Hash(): mustCreateBlockNode(&blockMap[2][5].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
899 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
902 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
903 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
904 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
905 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
908 wantOrphanManage: protocol.NewOrphanManage(),
913 desc: "rollback a block has spend non btm but status fail is true",
914 newBlock: blockMap[3][0].block,
915 initStore: createStoreItems([]int{0, 1, 3}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][6]}, &storeItem{
916 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
917 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
919 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
920 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
922 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][6], blockMap[3][0]}, &storeItem{
923 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
924 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
926 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
927 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
929 wantBlockIndex: state.NewBlockIndexWithData(
930 map[bc.Hash]*state.BlockNode{
931 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
932 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
933 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
934 blockMap[2][6].block.Hash(): mustCreateBlockNode(&blockMap[2][6].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
935 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
938 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
939 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
940 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
941 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
944 wantOrphanManage: protocol.NewOrphanManage(),
949 desc: "rollback a block only has coinbase tx, and from orphan manage",
950 newBlock: blockMap[1][0].block,
951 initStore: createStoreItems([]int{0, 1}, []*attachBlock{blockMap[0][0], blockMap[1][1]}),
952 initOrphanManage: protocol.NewOrphanManageWithData(
953 map[bc.Hash]*protocol.OrphanBlock{
954 blockMap[2][0].block.Hash(): protocol.NewOrphanBlock(blockMap[2][0].block, time.Now().Add(time.Minute*60)),
956 map[bc.Hash][]*bc.Hash{blockMap[2][0].block.PreviousBlockHash: {hashPtr(blockMap[2][0].block.Hash())}},
958 wantStore: createStoreItems([]int{0, 1, 3}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[1][1], blockMap[2][0]}),
959 wantBlockIndex: state.NewBlockIndexWithData(
960 map[bc.Hash]*state.BlockNode{
961 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
962 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
963 blockMap[1][1].block.Hash(): mustCreateBlockNode(&blockMap[1][1].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
964 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
967 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
968 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
969 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
972 wantOrphanManage: protocol.NewOrphanManage(),
977 desc: "rollback a block has spend btm tx, and from orphan manage",
978 newBlock: blockMap[2][0].block,
979 initStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][1]}, &storeItem{
980 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
981 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
983 initOrphanManage: protocol.NewOrphanManageWithData(
984 map[bc.Hash]*protocol.OrphanBlock{
985 blockMap[3][0].block.Hash(): protocol.NewOrphanBlock(blockMap[3][0].block, time.Now().Add(time.Minute*60)),
987 map[bc.Hash][]*bc.Hash{blockMap[3][0].block.PreviousBlockHash: {hashPtr(blockMap[3][0].block.Hash())}},
989 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][1], blockMap[3][0]}, &storeItem{
990 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
991 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
993 wantBlockIndex: state.NewBlockIndexWithData(
994 map[bc.Hash]*state.BlockNode{
995 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
996 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
997 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
998 blockMap[2][1].block.Hash(): mustCreateBlockNode(&blockMap[2][1].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
999 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1002 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
1003 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1004 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1005 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1008 wantOrphanManage: protocol.NewOrphanManage(),
1009 wantIsOrphan: false,
1013 desc: "rollback a block has retire tx, and from orphan manage",
1014 newBlock: blockMap[2][0].block,
1015 initStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][2]}, &storeItem{
1016 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
1017 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
1019 initOrphanManage: protocol.NewOrphanManageWithData(
1020 map[bc.Hash]*protocol.OrphanBlock{
1021 blockMap[3][0].block.Hash(): protocol.NewOrphanBlock(blockMap[3][0].block, time.Now().Add(time.Minute*60)),
1023 map[bc.Hash][]*bc.Hash{blockMap[3][0].block.PreviousBlockHash: {hashPtr(blockMap[3][0].block.Hash())}},
1025 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][2], blockMap[3][0]}, &storeItem{
1026 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
1027 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
1029 wantBlockIndex: state.NewBlockIndexWithData(
1030 map[bc.Hash]*state.BlockNode{
1031 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
1032 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1033 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1034 blockMap[2][2].block.Hash(): mustCreateBlockNode(&blockMap[2][2].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1035 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1038 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
1039 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1040 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1041 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1044 wantOrphanManage: protocol.NewOrphanManage(),
1045 wantIsOrphan: false,
1049 desc: "rollback a block has issuance tx, and from orphan manage",
1050 newBlock: blockMap[2][0].block,
1051 initStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][3]}, &storeItem{
1052 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
1053 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
1055 initOrphanManage: protocol.NewOrphanManageWithData(
1056 map[bc.Hash]*protocol.OrphanBlock{
1057 blockMap[3][0].block.Hash(): protocol.NewOrphanBlock(blockMap[3][0].block, time.Now().Add(time.Minute*60)),
1059 map[bc.Hash][]*bc.Hash{blockMap[3][0].block.PreviousBlockHash: {hashPtr(blockMap[3][0].block.Hash())}},
1061 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][3], blockMap[3][0]}, &storeItem{
1062 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
1063 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
1065 wantBlockIndex: state.NewBlockIndexWithData(
1066 map[bc.Hash]*state.BlockNode{
1067 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
1068 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1069 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1070 blockMap[2][3].block.Hash(): mustCreateBlockNode(&blockMap[2][3].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1071 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1074 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
1075 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1076 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1077 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1080 wantOrphanManage: protocol.NewOrphanManage(),
1081 wantIsOrphan: false,
1085 desc: "rollback a block has non btm tx, and from orphan manage",
1086 newBlock: blockMap[2][0].block,
1087 initStore: createStoreItems([]int{0, 1, 2}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][5]}, &storeItem{
1088 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
1089 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
1091 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
1092 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false},
1094 initOrphanManage: protocol.NewOrphanManageWithData(
1095 map[bc.Hash]*protocol.OrphanBlock{
1096 blockMap[3][0].block.Hash(): protocol.NewOrphanBlock(blockMap[3][0].block, time.Now().Add(time.Minute*60)),
1098 map[bc.Hash][]*bc.Hash{blockMap[3][0].block.PreviousBlockHash: {hashPtr(blockMap[3][0].block.Hash())}},
1100 wantStore: createStoreItems([]int{0, 1, 2, 4}, []*attachBlock{blockMap[0][0], blockMap[1][0], blockMap[2][0], blockMap[2][5], blockMap[3][0]}, &storeItem{
1101 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))),
1102 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
1104 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))),
1105 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false},
1107 wantBlockIndex: state.NewBlockIndexWithData(
1108 map[bc.Hash]*state.BlockNode{
1109 blockMap[0][0].block.Hash(): mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
1110 blockMap[1][0].block.Hash(): mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1111 blockMap[2][0].block.Hash(): mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1112 blockMap[2][5].block.Hash(): mustCreateBlockNode(&blockMap[2][5].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1113 blockMap[3][0].block.Hash(): mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1116 mustCreateBlockNode(&blockMap[0][0].block.BlockHeader),
1117 mustCreateBlockNode(&blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1118 mustCreateBlockNode(&blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1119 mustCreateBlockNode(&blockMap[3][0].block.BlockHeader, &blockMap[2][0].block.BlockHeader, &blockMap[1][0].block.BlockHeader, &blockMap[0][0].block.BlockHeader),
1122 wantOrphanManage: protocol.NewOrphanManage(),
1123 wantIsOrphan: false,
1128 for _, c := range cases {
1129 if err := c.Run(); err != nil {
1135 func createStoreItems(mainChainIndexes []int, attachBlocks []*attachBlock, extralItem ...*storeItem) storeItems {
1136 var items storeItems
1137 for _, item := range extralItem {
1138 items = append(items, item)
1141 mainChainIndexMap := make(map[int]interface{})
1142 for _, index := range mainChainIndexes {
1143 mainChainIndexMap[index] = nil
1146 for i, attachBlock := range attachBlocks {
1147 block := attachBlock.block
1148 blockHash := block.Hash()
1149 items = append(items, &storeItem{
1150 key: database.CalcBlockKey(&blockHash),
1154 items = append(items, &storeItem{
1155 key: database.CalcTxStatusKey(&blockHash),
1156 val: &bc.TransactionStatus{Version: 1, VerifyStatus: attachBlock.verifyResult},
1158 items = append(items, &storeItem{
1159 key: database.CalcBlockHeaderKey(block.Height, &blockHash),
1160 val: block.BlockHeader,
1163 if _, ok := mainChainIndexMap[i]; !ok {
1167 for i, tx := range block.Transactions {
1168 statusFail := attachBlock.verifyResult[i].StatusFail
1169 for _, input := range tx.Inputs {
1170 if statusFail && input.AssetID() != *consensus.BTMAssetID {
1174 if _, ok := input.TypedInput.(*types.SpendInput); !ok {
1177 spendOutputID, err := input.SpentOutputID()
1181 index := spendUTXO(spendOutputID, items, block.Height)
1182 items = append(items[0:index], items[index+1:]...)
1184 for j, output := range tx.Outputs {
1185 if statusFail && *tx.Outputs[j].AssetId != *consensus.BTMAssetID {
1188 if output.ControlProgram[0] == 0x6a {
1191 items = append(items, &storeItem{key: database.CalcUtxoKey(tx.Tx.ResultIds[j]),
1192 val: &storage.UtxoEntry{IsCoinBase: i == 0, BlockHeight: block.Height, Spent: false},
1198 lastIndex := mainChainIndexes[len(mainChainIndexes)-1]
1199 betBlock := attachBlocks[lastIndex].block
1200 bestBlockHash := betBlock.Hash()
1201 items = append(items, &storeItem{
1202 key: database.BlockStoreKey,
1203 val: &protocol.BlockStoreState{Height: betBlock.Height, Hash: &bestBlockHash},
1208 func hashPtr(hash bc.Hash) *bc.Hash {
1212 func mustCreateBlockNode(header *types.BlockHeader, parents ...*types.BlockHeader) *state.BlockNode {
1213 var parentNode *state.BlockNode
1214 for i := len(parents) - 1; i >= 0; i-- {
1215 parentNode = mustNewBlockNode(parents[i], parentNode)
1217 return mustNewBlockNode(header, parentNode)
1220 func mustPostProcessBlock() {
1221 for _, blocks := range blockMap {
1222 for _, attachBlock := range blocks {
1223 mustCalcMerkleRootHash(attachBlock)
1224 mustFillTransactionSize(attachBlock.block)
1225 sortSpendOutputID(attachBlock.block)
1230 func mustCalcMerkleRootHash(attachBlock *attachBlock) {
1231 bcBlock := types.MapBlock(attachBlock.block)
1232 txStatusHash, err := types.TxStatusMerkleRoot(attachBlock.verifyResult)
1234 panic("fail on calc genesis tx status merkle root")
1237 merkleRoot, err := types.TxMerkleRoot(bcBlock.Transactions)
1239 panic("fail on calc genesis tx merkel root")
1242 attachBlock.block.TransactionStatusHash = txStatusHash
1243 attachBlock.block.TransactionsMerkleRoot = merkleRoot
1246 func mustFillTransactionSize(block *types.Block) {
1247 for _, tx := range block.Transactions {
1248 bytes, err := tx.MarshalText()
1252 tx.TxData.SerializedSize = uint64(len(bytes) / 2)
1253 tx.Tx.SerializedSize = uint64(len(bytes) / 2)
1257 func mustNewBlockNode(h *types.BlockHeader, parent *state.BlockNode) *state.BlockNode {
1258 node, err := state.NewBlockNode(h, parent)
1265 func spendUTXO(spendOutputID bc.Hash, items storeItems, blockHeight uint64) int {
1266 for i, item := range items {
1267 utxo, ok := item.val.(*storage.UtxoEntry)
1271 if string(database.CalcUtxoKey(&spendOutputID)) != string(item.key) {
1274 if utxo.Spent || (utxo.IsCoinBase && utxo.BlockHeight+consensus.CoinbasePendingBlockNumber > blockHeight) {
1275 panic("utxo can not be use")
1280 panic("can not find available utxo")