github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/test/integration/block_integration_test.go (about) 1 package integration 2 3 import ( 4 "testing" 5 6 "time" 7 8 "github.com/bytom/bytom/config" 9 "github.com/bytom/bytom/consensus" 10 "github.com/bytom/bytom/database" 11 "github.com/bytom/bytom/database/storage" 12 "github.com/bytom/bytom/protocol" 13 "github.com/bytom/bytom/protocol/bc" 14 "github.com/bytom/bytom/protocol/bc/types" 15 "github.com/bytom/bytom/protocol/state" 16 "github.com/bytom/bytom/testutil" 17 ) 18 19 var blockMap map[int][]*attachBlock 20 21 type attachBlock struct { 22 block *types.Block 23 verifyResult []*bc.TxVerifyResult 24 } 25 26 func init() { 27 consensus.ActiveNetParams = consensus.SoloNetParams 28 29 blockMap = map[int][]*attachBlock{ 30 0: { 31 { 32 block: config.GenesisBlock(), 33 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}}, 34 }, 35 }, 36 1: { 37 { 38 block: &types.Block{ 39 BlockHeader: types.BlockHeader{ 40 Height: 1, 41 Version: 1, 42 Timestamp: 1556431597, 43 Nonce: 5, 44 Bits: 2305843009214532812, 45 PreviousBlockHash: testutil.MustDecodeHash("ce4fe9431cd0225b3a811f8f8ec922f2b07a921bb12a8dddae9a85540072c770"), 46 }, 47 Transactions: []*types.Tx{ 48 types.NewTx(types.TxData{ 49 Version: 1, 50 SerializedSize: 77, 51 TimeRange: 0, 52 Inputs: []*types.TxInput{ 53 types.NewCoinbaseInput(testutil.MustDecodeHexString("0031")), 54 }, 55 Outputs: []*types.TxOutput{ 56 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 57 }, 58 }), 59 }, 60 }, 61 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}}, 62 }, 63 { 64 block: &types.Block{ 65 BlockHeader: types.BlockHeader{ 66 Height: 1, 67 Version: 1, 68 Timestamp: 1556431697, 69 Nonce: 36, 70 Bits: 2305843009214532812, 71 PreviousBlockHash: testutil.MustDecodeHash("ce4fe9431cd0225b3a811f8f8ec922f2b07a921bb12a8dddae9a85540072c770"), 72 }, 73 Transactions: []*types.Tx{ 74 types.NewTx(types.TxData{ 75 Version: 1, 76 SerializedSize: 77, 77 TimeRange: 0, 78 Inputs: []*types.TxInput{ 79 types.NewCoinbaseInput(testutil.MustDecodeHexString("0031")), 80 }, 81 Outputs: []*types.TxOutput{ 82 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("00143d05e891b165b165afefa2e861e83a9745f80d8c")), 83 }, 84 }), 85 }, 86 }, 87 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}}, 88 }, 89 }, 90 2: { 91 // only has coinbase transaction 92 { 93 block: &types.Block{ 94 BlockHeader: types.BlockHeader{ 95 Height: 2, 96 Version: 1, 97 Timestamp: 1556431604, 98 Nonce: 0, 99 Bits: 2305843009214532812, 100 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"), 101 }, 102 Transactions: []*types.Tx{ 103 types.NewTx(types.TxData{ 104 Version: 1, 105 SerializedSize: 77, 106 TimeRange: 0, 107 Inputs: []*types.TxInput{ 108 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")), 109 }, 110 Outputs: []*types.TxOutput{ 111 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 112 }, 113 }), 114 }, 115 }, 116 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}}, 117 }, 118 // with spend btm transaction 119 { 120 block: &types.Block{ 121 BlockHeader: types.BlockHeader{ 122 Height: 2, 123 Version: 1, 124 Timestamp: 1556431604, 125 Nonce: 12, 126 Bits: 2305843009214532812, 127 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"), 128 }, 129 Transactions: []*types.Tx{ 130 types.NewTx(types.TxData{ 131 Version: 1, 132 SerializedSize: 77, 133 TimeRange: 0, 134 Inputs: []*types.TxInput{ 135 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")), 136 }, 137 Outputs: []*types.TxOutput{ 138 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 139 }, 140 }), 141 types.NewTx(types.TxData{ 142 Version: 1, 143 TimeRange: 0, 144 Inputs: []*types.TxInput{ 145 types.NewSpendInput( 146 [][]byte{ 147 testutil.MustDecodeHexString("7b4082c9d745c3f07dd07afb1f987960d2ef3ea2486741c3f3184751485f77d046df6670eba21020fcf9c7987c0c938384320dc21b0e116c62ae2597cb1fe109"), 148 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"), 149 }, 150 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"), 151 *consensus.BTMAssetID, 10000000000, 0, 152 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"), 153 ), 154 }, 155 Outputs: []*types.TxOutput{ 156 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("00143d05e891b165b165afefa2e861e83a9745f80d8c")), 157 }, 158 }), 159 }, 160 }, 161 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}}, 162 }, 163 // with btm retire transaction 164 { 165 block: &types.Block{ 166 BlockHeader: types.BlockHeader{ 167 Height: 2, 168 Version: 1, 169 Timestamp: 1556431607, 170 Nonce: 4, 171 Bits: 2305843009214532812, 172 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"), 173 }, 174 Transactions: []*types.Tx{ 175 types.NewTx(types.TxData{ 176 Version: 1, 177 SerializedSize: 77, 178 TimeRange: 0, 179 Inputs: []*types.TxInput{ 180 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")), 181 }, 182 Outputs: []*types.TxOutput{ 183 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 184 }, 185 }), 186 types.NewTx(types.TxData{ 187 Version: 1, 188 TimeRange: 0, 189 Inputs: []*types.TxInput{ 190 types.NewSpendInput( 191 [][]byte{ 192 testutil.MustDecodeHexString("302035b362d80419cfed12cfc7d33d2ff7638c589ee2cf6573eb14b4d8cb4a63d7d1302589666dd6d1cd08185dbb2842407f3980bc2564705eda15680c984c05"), 193 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"), 194 }, 195 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"), 196 *consensus.BTMAssetID, 10000000000, 0, 197 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"), 198 ), 199 }, 200 Outputs: []*types.TxOutput{ 201 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("6a")), // retire 202 }, 203 }), 204 }, 205 }, 206 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}}, 207 }, 208 // with issuance transaction 209 { 210 block: &types.Block{ 211 BlockHeader: types.BlockHeader{ 212 Height: 2, 213 Version: 1, 214 Timestamp: 1556431607, 215 Nonce: 17, 216 Bits: 2305843009214532812, 217 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"), 218 }, 219 Transactions: []*types.Tx{ 220 types.NewTx(types.TxData{ 221 Version: 1, 222 SerializedSize: 77, 223 TimeRange: 0, 224 Inputs: []*types.TxInput{ 225 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")), 226 }, 227 Outputs: []*types.TxOutput{ 228 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 229 }, 230 }), 231 types.NewTx(types.TxData{ 232 Version: 1, 233 TimeRange: 0, 234 Inputs: []*types.TxInput{ 235 types.NewSpendInput( 236 [][]byte{ 237 testutil.MustDecodeHexString("46cbb829b6a5bb9fc436c8e51bcbd9f0b3ed99ce97b2e0fac28879b4202c5a9eccaae39a4d18584f789a9427af3a2f09ff0360fb187e46ef172146a9b957ef0c"), 238 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"), 239 }, 240 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"), 241 *consensus.BTMAssetID, 10000000000, 0, 242 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"), 243 ), 244 types.NewIssuanceInput( 245 testutil.MustDecodeHexString("fd0aec4229deb281"), 246 10000000000, 247 testutil.MustDecodeHexString("ae20f25e8b73ffbc3a42300a43279fdf612d79e1936a6c614fc05a5adec9bba42dcd5151ad"), 248 [][]byte{testutil.MustDecodeHexString("df9fabf4636904e017eefb7cdf2b4f08e29efbd4cfc41fe5b01a453191f0913489b19ad74272145824e92bd4843e91140cc5d1a6256f84981d1437ed4566a60b")}, 249 testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), 250 ), 251 }, 252 Outputs: []*types.TxOutput{ 253 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 254 types.NewTxOutput(testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 255 }, 256 }), 257 }, 258 }, 259 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}}, 260 }, 261 // with issuance transaction but status fail is true 262 { 263 block: &types.Block{ 264 BlockHeader: types.BlockHeader{ 265 Height: 2, 266 Version: 1, 267 Timestamp: 1556431607, 268 Nonce: 4, 269 Bits: 2305843009214532812, 270 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"), 271 }, 272 Transactions: []*types.Tx{ 273 types.NewTx(types.TxData{ 274 Version: 1, 275 SerializedSize: 77, 276 TimeRange: 0, 277 Inputs: []*types.TxInput{ 278 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")), 279 }, 280 Outputs: []*types.TxOutput{ 281 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 282 }, 283 }), 284 types.NewTx(types.TxData{ 285 Version: 1, 286 TimeRange: 0, 287 Inputs: []*types.TxInput{ 288 types.NewSpendInput( 289 [][]byte{ 290 testutil.MustDecodeHexString("46cbb829b6a5bb9fc436c8e51bcbd9f0b3ed99ce97b2e0fac28879b4202c5a9eccaae39a4d18584f789a9427af3a2f09ff0360fb187e46ef172146a9b957ef0c"), 291 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"), 292 }, 293 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"), 294 *consensus.BTMAssetID, 10000000000, 0, 295 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"), 296 ), 297 types.NewIssuanceInput( 298 testutil.MustDecodeHexString("fd0aec4229deb281"), 299 10000000000, 300 testutil.MustDecodeHexString("ae20f25e8b73ffbc3a42300a43279fdf612d79e1936a6c614fc05a5adec9bba42dcd5151ad"), 301 // invalid signature 302 [][]byte{testutil.MustDecodeHexString("df9fabf4636904e017eefb7cdf2b4f08e29efbd4cfc41fe5b01a453191f0913489b19ad74272145824e92bd4843e91140cc5d1a6256f84981d1437ed4566a60c")}, 303 testutil.MustDecodeHexString("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"), 304 ), 305 }, 306 Outputs: []*types.TxOutput{ 307 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 308 types.NewTxOutput(testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 309 }, 310 }), 311 }, 312 }, 313 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: true}}, 314 }, 315 // with non btm transaction 316 { 317 block: &types.Block{ 318 BlockHeader: types.BlockHeader{ 319 Height: 2, 320 Version: 1, 321 Timestamp: 1556431607, 322 Nonce: 4, 323 Bits: 2305843009214532812, 324 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"), 325 }, 326 Transactions: []*types.Tx{ 327 types.NewTx(types.TxData{ 328 Version: 1, 329 SerializedSize: 77, 330 TimeRange: 0, 331 Inputs: []*types.TxInput{ 332 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")), 333 }, 334 Outputs: []*types.TxOutput{ 335 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 336 }, 337 }), 338 types.NewTx(types.TxData{ 339 Version: 1, 340 TimeRange: 0, 341 Inputs: []*types.TxInput{ 342 types.NewSpendInput( 343 [][]byte{ 344 testutil.MustDecodeHexString("afc4e24f0e0383e3fd78af3de189be3913faddbbd8cac8a8c9316bf9eb0866e83df3618cf4c7b4d091a79968a16377d422cbd8011f1f5e75ba201e173b68ad02"), 345 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"), 346 }, 347 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"), 348 *consensus.BTMAssetID, 10000000000, 0, 349 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"), 350 ), 351 types.NewSpendInput( 352 [][]byte{ 353 testutil.MustDecodeHexString("cd6fb451102db667341438f20dbeabd30b343ed08d89625a8e27e82478e89ddea9e7d51f8a4036e0cc2602ac5fae0bdbfda025a0e2c12e3ddc8100b62461670b"), 354 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"), 355 }, 356 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f22"), 357 testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, 1, 358 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"), 359 ), 360 }, 361 Outputs: []*types.TxOutput{ 362 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 363 types.NewTxOutput(testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 364 }, 365 }), 366 }, 367 }, 368 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: false}}, 369 }, 370 // with non btm transaction but status fail is true 371 { 372 block: &types.Block{ 373 BlockHeader: types.BlockHeader{ 374 Height: 2, 375 Version: 1, 376 Timestamp: 1556431607, 377 Nonce: 12, 378 Bits: 2305843009214532812, 379 PreviousBlockHash: testutil.MustDecodeHash("2eaf7f40b0a0d4a5025f3d5d9b8589d3db1634f7b55089ca59253a9c587266b2"), 380 }, 381 Transactions: []*types.Tx{ 382 types.NewTx(types.TxData{ 383 Version: 1, 384 SerializedSize: 77, 385 TimeRange: 0, 386 Inputs: []*types.TxInput{ 387 types.NewCoinbaseInput(testutil.MustDecodeHexString("0032")), 388 }, 389 Outputs: []*types.TxOutput{ 390 types.NewTxOutput(*consensus.BTMAssetID, 41350000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 391 }, 392 }), 393 types.NewTx(types.TxData{ 394 Version: 1, 395 TimeRange: 0, 396 Inputs: []*types.TxInput{ 397 types.NewSpendInput( 398 [][]byte{ 399 testutil.MustDecodeHexString("afc4e24f0e0383e3fd78af3de189be3913faddbbd8cac8a8c9316bf9eb0866e83df3618cf4c7b4d091a79968a16377d422cbd8011f1f5e75ba201e173b68ad02"), 400 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"), 401 }, 402 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f21"), 403 *consensus.BTMAssetID, 10000000000, 0, 404 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"), 405 ), 406 types.NewSpendInput( 407 // invalid signature 408 [][]byte{ 409 testutil.MustDecodeHexString("cd6fb451102db667341438f20dbeabd30b343ed08d89625a8e27e82478e89ddea9e7d51f8a4036e0cc2602ac5fae0bdbfda025a0e2c12e3ddc8100b62461670c"), 410 testutil.MustDecodeHexString("33b05e00e19cb2bdbc8a6a67b4f1e03fc265534bcfc7641b305c8204fb486f79"), 411 }, 412 testutil.MustDecodeHash("28b7b53d8dc90006bf97e0a4eaae2a72ec3d869873188698b694beaf20789f22"), 413 testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, 1, 414 testutil.MustDecodeHexString("0014cade6dd7cbe2ea2b8ab90dfb8756dda4ba1624bc"), 415 ), 416 }, 417 Outputs: []*types.TxOutput{ 418 types.NewTxOutput(*consensus.BTMAssetID, 9900000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 419 types.NewTxOutput(testutil.MustDecodeAsset("641ccb49dd38df9921a55e020d40a2323589c36ab5557f8a249ee01cc09d1836"), 10000000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 420 }, 421 }), 422 }, 423 }, 424 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}, {StatusFail: true}}, 425 }, 426 }, 427 3: { 428 // the previous block is blockMap[2][0] 429 { 430 block: &types.Block{ 431 BlockHeader: types.BlockHeader{ 432 Height: 3, 433 Version: 1, 434 Timestamp: 1556431640, 435 Nonce: 0, 436 Bits: 2305843009214532812, 437 PreviousBlockHash: testutil.MustDecodeHash("09c6064f4f1e7325440c45df03e97f97dbfbb66033315a384308256038af6c30"), 438 }, 439 Transactions: []*types.Tx{ 440 types.NewTx(types.TxData{ 441 Version: 1, 442 SerializedSize: 77, 443 TimeRange: 0, 444 Inputs: []*types.TxInput{ 445 types.NewCoinbaseInput(testutil.MustDecodeHexString("0033")), 446 }, 447 Outputs: []*types.TxOutput{ 448 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 449 }, 450 }), 451 }, 452 }, 453 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}}, 454 }, 455 // the previous block is blockMap[2][2] 456 { 457 block: &types.Block{ 458 BlockHeader: types.BlockHeader{ 459 Height: 3, 460 Version: 1, 461 Timestamp: 1556431640, 462 Nonce: 5, 463 Bits: 2305843009214532812, 464 PreviousBlockHash: testutil.MustDecodeHash("33f56264283cc12e3b232068caa13c1fd052c21b231a94e8c0a40bac25629f88"), 465 }, 466 Transactions: []*types.Tx{ 467 types.NewTx(types.TxData{ 468 Version: 1, 469 SerializedSize: 77, 470 TimeRange: 0, 471 Inputs: []*types.TxInput{ 472 types.NewCoinbaseInput(testutil.MustDecodeHexString("0033")), 473 }, 474 Outputs: []*types.TxOutput{ 475 types.NewTxOutput(*consensus.BTMAssetID, 41250000000, testutil.MustDecodeHexString("0014024bb9bfc639bdac292ff9ceb41b5c6f5a970eab")), 476 }, 477 }), 478 }, 479 }, 480 verifyResult: []*bc.TxVerifyResult{{StatusFail: false}}, 481 }, 482 }, 483 } 484 485 mustPostProcessBlock() 486 } 487 488 func TestProcessBlock(t *testing.T) { 489 cases := []*processBlockTestCase{ 490 { 491 desc: "process a invalid block", 492 newBlock: &types.Block{ 493 BlockHeader: types.BlockHeader{ 494 Height: 1, 495 Version: 1, 496 Bits: 2305843009214532812, 497 PreviousBlockHash: blockMap[0][0].block.Hash(), 498 }, 499 }, 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), 504 }, 505 []*state.BlockNode{ 506 mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil), 507 }, 508 ), 509 wantOrphanManage: protocol.NewOrphanManage(), 510 wantError: true, 511 }, 512 { 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), 519 }, 520 []*state.BlockNode{ 521 mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil), 522 }, 523 ), 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())}}, 527 ), 528 wantIsOrphan: true, 529 wantError: false, 530 }, 531 { 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), 539 }, 540 []*state.BlockNode{ 541 mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil), 542 mustNewBlockNode(&blockMap[1][0].block.BlockHeader, mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil)), 543 }, 544 ), 545 wantOrphanManage: protocol.NewOrphanManage(), 546 wantIsOrphan: false, 547 wantError: false, 548 }, 549 { 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), 558 }, 559 []*state.BlockNode{ 560 mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil), 561 mustNewBlockNode(&blockMap[1][0].block.BlockHeader, mustNewBlockNode(&blockMap[0][0].block.BlockHeader, nil)), 562 }, 563 ), 564 wantOrphanManage: protocol.NewOrphanManage(), 565 wantIsOrphan: false, 566 wantError: false, 567 }, 568 { 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), 579 }, 580 []*state.BlockNode{ 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), 584 }, 585 ), 586 wantOrphanManage: protocol.NewOrphanManage(), 587 wantIsOrphan: false, 588 wantError: false, 589 }, 590 { 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}, 596 }), 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}, 600 }), 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), 606 }, 607 []*state.BlockNode{ 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), 611 }, 612 ), 613 wantOrphanManage: protocol.NewOrphanManage(), 614 wantIsOrphan: false, 615 wantError: false, 616 }, 617 { 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}, 623 }), 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}, 627 }), 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), 633 }, 634 []*state.BlockNode{ 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), 638 }, 639 ), 640 wantOrphanManage: protocol.NewOrphanManage(), 641 wantIsOrphan: false, 642 wantError: false, 643 }, 644 { 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}, 650 }), 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}, 654 }), 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), 660 }, 661 []*state.BlockNode{ 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), 665 }, 666 ), 667 wantOrphanManage: protocol.NewOrphanManage(), 668 wantIsOrphan: false, 669 wantError: false, 670 }, 671 { 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}, 677 }), 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}, 681 }), 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), 687 }, 688 []*state.BlockNode{ 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), 692 }, 693 ), 694 wantOrphanManage: protocol.NewOrphanManage(), 695 wantIsOrphan: false, 696 wantError: false, 697 }, 698 { 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}, 704 }, &storeItem{ 705 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))), 706 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false}, 707 }), 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}, 711 }, &storeItem{ 712 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))), 713 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false}, 714 }), 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), 720 }, 721 []*state.BlockNode{ 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), 725 }, 726 ), 727 wantOrphanManage: protocol.NewOrphanManage(), 728 wantIsOrphan: false, 729 wantError: false, 730 }, 731 { 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}, 737 }, &storeItem{ 738 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))), 739 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false}, 740 }), 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}, 744 }, &storeItem{ 745 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("c93b687f98d039046cd2afd514c62f5d1c2c3b0804e4845b00a33e736ef48a33"))), 746 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false}, 747 }), 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), 753 }, 754 []*state.BlockNode{ 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), 758 }, 759 ), 760 wantOrphanManage: protocol.NewOrphanManage(), 761 wantIsOrphan: false, 762 wantError: false, 763 }, 764 { 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), 775 }, 776 []*state.BlockNode{ 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), 780 }, 781 ), 782 wantOrphanManage: protocol.NewOrphanManage(), 783 wantIsOrphan: false, 784 wantError: false, 785 }, 786 { 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}, 792 }), 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}, 796 }), 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), 804 }, 805 []*state.BlockNode{ 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), 810 }, 811 ), 812 wantOrphanManage: protocol.NewOrphanManage(), 813 wantIsOrphan: false, 814 wantError: false, 815 }, 816 { 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}, 822 }), 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}, 826 }), 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), 834 }, 835 []*state.BlockNode{ 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), 840 }, 841 ), 842 wantOrphanManage: protocol.NewOrphanManage(), 843 wantIsOrphan: false, 844 wantError: false, 845 }, 846 { 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}, 852 }), 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}, 856 }), 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), 864 }, 865 []*state.BlockNode{ 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), 870 }, 871 ), 872 wantOrphanManage: protocol.NewOrphanManage(), 873 wantIsOrphan: false, 874 wantError: false, 875 }, 876 { 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}, 882 }, &storeItem{ 883 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))), 884 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false}, 885 }), 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}, 889 }, &storeItem{ 890 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))), 891 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false}, 892 }), 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), 900 }, 901 []*state.BlockNode{ 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), 906 }, 907 ), 908 wantOrphanManage: protocol.NewOrphanManage(), 909 wantIsOrphan: false, 910 wantError: false, 911 }, 912 { 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}, 918 }, &storeItem{ 919 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))), 920 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false}, 921 }), 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}, 925 }, &storeItem{ 926 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))), 927 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false}, 928 }), 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), 936 }, 937 []*state.BlockNode{ 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), 942 }, 943 ), 944 wantOrphanManage: protocol.NewOrphanManage(), 945 wantIsOrphan: false, 946 wantError: false, 947 }, 948 { 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)), 955 }, 956 map[bc.Hash][]*bc.Hash{blockMap[2][0].block.PreviousBlockHash: {hashPtr(blockMap[2][0].block.Hash())}}, 957 ), 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), 965 }, 966 []*state.BlockNode{ 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), 970 }, 971 ), 972 wantOrphanManage: protocol.NewOrphanManage(), 973 wantIsOrphan: false, 974 wantError: false, 975 }, 976 { 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}, 982 }), 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)), 986 }, 987 map[bc.Hash][]*bc.Hash{blockMap[3][0].block.PreviousBlockHash: {hashPtr(blockMap[3][0].block.Hash())}}, 988 ), 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}, 992 }), 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), 1000 }, 1001 []*state.BlockNode{ 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), 1006 }, 1007 ), 1008 wantOrphanManage: protocol.NewOrphanManage(), 1009 wantIsOrphan: false, 1010 wantError: false, 1011 }, 1012 { 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}, 1018 }), 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)), 1022 }, 1023 map[bc.Hash][]*bc.Hash{blockMap[3][0].block.PreviousBlockHash: {hashPtr(blockMap[3][0].block.Hash())}}, 1024 ), 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}, 1028 }), 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), 1036 }, 1037 []*state.BlockNode{ 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), 1042 }, 1043 ), 1044 wantOrphanManage: protocol.NewOrphanManage(), 1045 wantIsOrphan: false, 1046 wantError: false, 1047 }, 1048 { 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}, 1054 }), 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)), 1058 }, 1059 map[bc.Hash][]*bc.Hash{blockMap[3][0].block.PreviousBlockHash: {hashPtr(blockMap[3][0].block.Hash())}}, 1060 ), 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}, 1064 }), 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), 1072 }, 1073 []*state.BlockNode{ 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), 1078 }, 1079 ), 1080 wantOrphanManage: protocol.NewOrphanManage(), 1081 wantIsOrphan: false, 1082 wantError: false, 1083 }, 1084 { 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}, 1090 }, &storeItem{ 1091 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))), 1092 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 1, Spent: false}, 1093 }), 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)), 1097 }, 1098 map[bc.Hash][]*bc.Hash{blockMap[3][0].block.PreviousBlockHash: {hashPtr(blockMap[3][0].block.Hash())}}, 1099 ), 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}, 1103 }, &storeItem{ 1104 key: database.CalcUtxoKey(hashPtr(testutil.MustDecodeHash("be164edbce8bcd1d890c1164541b8418fdcb257499757d3b88561bca06e97e29"))), 1105 val: &storage.UtxoEntry{IsCoinBase: false, BlockHeight: 0, Spent: false}, 1106 }), 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), 1114 }, 1115 []*state.BlockNode{ 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), 1120 }, 1121 ), 1122 wantOrphanManage: protocol.NewOrphanManage(), 1123 wantIsOrphan: false, 1124 wantError: false, 1125 }, 1126 } 1127 1128 for _, c := range cases { 1129 if err := c.Run(); err != nil { 1130 panic(err) 1131 } 1132 } 1133 } 1134 1135 func createStoreItems(mainChainIndexes []int, attachBlocks []*attachBlock, extralItem ...*storeItem) storeItems { 1136 var items storeItems 1137 for _, item := range extralItem { 1138 items = append(items, item) 1139 } 1140 1141 mainChainIndexMap := make(map[int]interface{}) 1142 for _, index := range mainChainIndexes { 1143 mainChainIndexMap[index] = nil 1144 } 1145 1146 for i, attachBlock := range attachBlocks { 1147 block := attachBlock.block 1148 blockHash := block.Hash() 1149 items = append(items, &storeItem{ 1150 key: database.CalcBlockKey(&blockHash), 1151 val: block, 1152 }) 1153 1154 items = append(items, &storeItem{ 1155 key: database.CalcTxStatusKey(&blockHash), 1156 val: &bc.TransactionStatus{Version: 1, VerifyStatus: attachBlock.verifyResult}, 1157 }) 1158 items = append(items, &storeItem{ 1159 key: database.CalcBlockHeaderKey(block.Height, &blockHash), 1160 val: block.BlockHeader, 1161 }) 1162 1163 if _, ok := mainChainIndexMap[i]; !ok { 1164 continue 1165 } 1166 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 { 1171 continue 1172 } 1173 1174 if _, ok := input.TypedInput.(*types.SpendInput); !ok { 1175 continue 1176 } 1177 spendOutputID, err := input.SpentOutputID() 1178 if err != nil { 1179 panic(err) 1180 } 1181 index := spendUTXO(spendOutputID, items, block.Height) 1182 items = append(items[0:index], items[index+1:]...) 1183 } 1184 for j, output := range tx.Outputs { 1185 if statusFail && *tx.Outputs[j].AssetId != *consensus.BTMAssetID { 1186 continue 1187 } 1188 if output.ControlProgram[0] == 0x6a { 1189 continue 1190 } 1191 items = append(items, &storeItem{key: database.CalcUtxoKey(tx.Tx.ResultIds[j]), 1192 val: &storage.UtxoEntry{IsCoinBase: i == 0, BlockHeight: block.Height, Spent: false}, 1193 }) 1194 } 1195 } 1196 } 1197 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}, 1204 }) 1205 return items 1206 } 1207 1208 func hashPtr(hash bc.Hash) *bc.Hash { 1209 return &hash 1210 } 1211 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) 1216 } 1217 return mustNewBlockNode(header, parentNode) 1218 } 1219 1220 func mustPostProcessBlock() { 1221 for _, blocks := range blockMap { 1222 for _, attachBlock := range blocks { 1223 mustCalcMerkleRootHash(attachBlock) 1224 mustFillTransactionSize(attachBlock.block) 1225 sortSpendOutputID(attachBlock.block) 1226 } 1227 } 1228 } 1229 1230 func mustCalcMerkleRootHash(attachBlock *attachBlock) { 1231 bcBlock := types.MapBlock(attachBlock.block) 1232 txStatusHash, err := types.TxStatusMerkleRoot(attachBlock.verifyResult) 1233 if err != nil { 1234 panic("fail on calc genesis tx status merkle root") 1235 } 1236 1237 merkleRoot, err := types.TxMerkleRoot(bcBlock.Transactions) 1238 if err != nil { 1239 panic("fail on calc genesis tx merkel root") 1240 } 1241 1242 attachBlock.block.TransactionStatusHash = txStatusHash 1243 attachBlock.block.TransactionsMerkleRoot = merkleRoot 1244 } 1245 1246 func mustFillTransactionSize(block *types.Block) { 1247 for _, tx := range block.Transactions { 1248 bytes, err := tx.MarshalText() 1249 if err != nil { 1250 panic(err) 1251 } 1252 tx.TxData.SerializedSize = uint64(len(bytes) / 2) 1253 tx.Tx.SerializedSize = uint64(len(bytes) / 2) 1254 } 1255 } 1256 1257 func mustNewBlockNode(h *types.BlockHeader, parent *state.BlockNode) *state.BlockNode { 1258 node, err := state.NewBlockNode(h, parent) 1259 if err != nil { 1260 panic(err) 1261 } 1262 return node 1263 } 1264 1265 func spendUTXO(spendOutputID bc.Hash, items storeItems, blockHeight uint64) int { 1266 for i, item := range items { 1267 utxo, ok := item.val.(*storage.UtxoEntry) 1268 if !ok { 1269 continue 1270 } 1271 if string(database.CalcUtxoKey(&spendOutputID)) != string(item.key) { 1272 continue 1273 } 1274 if utxo.Spent || (utxo.IsCoinBase && utxo.BlockHeight+consensus.CoinbasePendingBlockNumber > blockHeight) { 1275 panic("utxo can not be use") 1276 } 1277 utxo.Spent = true 1278 return i 1279 } 1280 panic("can not find available utxo") 1281 }