github.com/ava-labs/avalanchego@v1.11.11/vms/proposervm/pre_fork_block_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package proposervm 5 6 import ( 7 "bytes" 8 "context" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/require" 13 "go.uber.org/mock/gomock" 14 15 "github.com/ava-labs/avalanchego/database" 16 "github.com/ava-labs/avalanchego/ids" 17 "github.com/ava-labs/avalanchego/snow" 18 "github.com/ava-labs/avalanchego/snow/consensus/snowman" 19 "github.com/ava-labs/avalanchego/snow/consensus/snowman/snowmanmock" 20 "github.com/ava-labs/avalanchego/snow/consensus/snowman/snowmantest" 21 "github.com/ava-labs/avalanchego/snow/engine/snowman/block/blockmock" 22 "github.com/ava-labs/avalanchego/snow/snowtest" 23 "github.com/ava-labs/avalanchego/snow/validators/validatorsmock" 24 "github.com/ava-labs/avalanchego/utils/logging" 25 "github.com/ava-labs/avalanchego/utils/timer/mockable" 26 27 statelessblock "github.com/ava-labs/avalanchego/vms/proposervm/block" 28 ) 29 30 func TestOracle_PreForkBlkImplementsInterface(t *testing.T) { 31 require := require.New(t) 32 33 // setup 34 proBlk := preForkBlock{ 35 Block: snowmantest.BuildChild(snowmantest.Genesis), 36 } 37 38 // test 39 _, err := proBlk.Options(context.Background()) 40 require.Equal(snowman.ErrNotOracle, err) 41 42 // setup 43 proBlk = preForkBlock{ 44 Block: &TestOptionsBlock{}, 45 } 46 47 // test 48 _, err = proBlk.Options(context.Background()) 49 require.NoError(err) 50 } 51 52 func TestOracle_PreForkBlkCanBuiltOnPreForkOption(t *testing.T) { 53 require := require.New(t) 54 55 var ( 56 activationTime = mockable.MaxTime 57 durangoTime = activationTime 58 ) 59 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 60 defer func() { 61 require.NoError(proVM.Shutdown(context.Background())) 62 }() 63 64 // create pre fork oracle block ... 65 coreTestBlk := snowmantest.BuildChild(snowmantest.Genesis) 66 preferredTestBlk := snowmantest.BuildChild(coreTestBlk) 67 oracleCoreBlk := &TestOptionsBlock{ 68 Block: *coreTestBlk, 69 opts: [2]*snowmantest.Block{ 70 preferredTestBlk, 71 snowmantest.BuildChild(coreTestBlk), 72 }, 73 } 74 75 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 76 return oracleCoreBlk, nil 77 } 78 coreVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { 79 switch blkID { 80 case snowmantest.GenesisID: 81 return snowmantest.Genesis, nil 82 case oracleCoreBlk.ID(): 83 return oracleCoreBlk, nil 84 case oracleCoreBlk.opts[0].ID(): 85 return oracleCoreBlk.opts[0], nil 86 case oracleCoreBlk.opts[1].ID(): 87 return oracleCoreBlk.opts[1], nil 88 default: 89 return nil, database.ErrNotFound 90 } 91 } 92 93 parentBlk, err := proVM.BuildBlock(context.Background()) 94 require.NoError(err) 95 96 // retrieve options ... 97 require.IsType(&preForkBlock{}, parentBlk) 98 preForkOracleBlk := parentBlk.(*preForkBlock) 99 opts, err := preForkOracleBlk.Options(context.Background()) 100 require.NoError(err) 101 require.NoError(opts[0].Verify(context.Background())) 102 103 // ... show a block can be built on top of an option 104 require.NoError(proVM.SetPreference(context.Background(), opts[0].ID())) 105 106 lastCoreBlk := &TestOptionsBlock{ 107 Block: *snowmantest.BuildChild(preferredTestBlk), 108 } 109 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 110 return lastCoreBlk, nil 111 } 112 113 preForkChild, err := proVM.BuildBlock(context.Background()) 114 require.NoError(err) 115 require.IsType(&preForkBlock{}, preForkChild) 116 } 117 118 func TestOracle_PostForkBlkCanBuiltOnPreForkOption(t *testing.T) { 119 require := require.New(t) 120 121 var ( 122 activationTime = snowmantest.GenesisTimestamp.Add(10 * time.Second) 123 durangoTime = activationTime 124 ) 125 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 126 defer func() { 127 require.NoError(proVM.Shutdown(context.Background())) 128 }() 129 130 // create pre fork oracle block pre activation time... 131 coreTestBlk := snowmantest.BuildChild(snowmantest.Genesis) 132 coreTestBlk.TimestampV = activationTime.Add(-1 * time.Second) 133 134 // ... whose options are post activation time 135 preferredBlk := snowmantest.BuildChild(coreTestBlk) 136 preferredBlk.TimestampV = activationTime.Add(time.Second) 137 138 unpreferredBlk := snowmantest.BuildChild(coreTestBlk) 139 unpreferredBlk.TimestampV = activationTime.Add(time.Second) 140 141 oracleCoreBlk := &TestOptionsBlock{ 142 Block: *coreTestBlk, 143 opts: [2]*snowmantest.Block{ 144 preferredBlk, 145 unpreferredBlk, 146 }, 147 } 148 149 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 150 return oracleCoreBlk, nil 151 } 152 coreVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { 153 switch blkID { 154 case snowmantest.GenesisID: 155 return snowmantest.Genesis, nil 156 case oracleCoreBlk.ID(): 157 return oracleCoreBlk, nil 158 case oracleCoreBlk.opts[0].ID(): 159 return oracleCoreBlk.opts[0], nil 160 case oracleCoreBlk.opts[1].ID(): 161 return oracleCoreBlk.opts[1], nil 162 default: 163 return nil, database.ErrNotFound 164 } 165 } 166 167 parentBlk, err := proVM.BuildBlock(context.Background()) 168 require.NoError(err) 169 170 // retrieve options ... 171 require.IsType(&preForkBlock{}, parentBlk) 172 preForkOracleBlk := parentBlk.(*preForkBlock) 173 opts, err := preForkOracleBlk.Options(context.Background()) 174 require.NoError(err) 175 require.NoError(opts[0].Verify(context.Background())) 176 177 // ... show a block can be built on top of an option 178 require.NoError(proVM.SetPreference(context.Background(), opts[0].ID())) 179 180 lastCoreBlk := &TestOptionsBlock{ 181 Block: *snowmantest.BuildChild(preferredBlk), 182 } 183 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 184 return lastCoreBlk, nil 185 } 186 187 postForkChild, err := proVM.BuildBlock(context.Background()) 188 require.NoError(err) 189 require.IsType(&postForkBlock{}, postForkChild) 190 } 191 192 func TestBlockVerify_PreFork_ParentChecks(t *testing.T) { 193 require := require.New(t) 194 195 var ( 196 activationTime = snowmantest.GenesisTimestamp.Add(10 * time.Second) 197 durangoTime = activationTime 198 ) 199 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 200 defer func() { 201 require.NoError(proVM.Shutdown(context.Background())) 202 }() 203 204 // create parent block ... 205 parentCoreBlk := snowmantest.BuildChild(snowmantest.Genesis) 206 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 207 return parentCoreBlk, nil 208 } 209 coreVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { 210 switch blkID { 211 case snowmantest.GenesisID: 212 return snowmantest.Genesis, nil 213 case parentCoreBlk.ID(): 214 return parentCoreBlk, nil 215 default: 216 return nil, database.ErrNotFound 217 } 218 } 219 coreVM.ParseBlockF = func(_ context.Context, b []byte) (snowman.Block, error) { 220 switch { 221 case bytes.Equal(b, snowmantest.GenesisBytes): 222 return snowmantest.Genesis, nil 223 case bytes.Equal(b, parentCoreBlk.Bytes()): 224 return parentCoreBlk, nil 225 default: 226 return nil, database.ErrNotFound 227 } 228 } 229 230 parentBlk, err := proVM.BuildBlock(context.Background()) 231 require.NoError(err) 232 233 // .. create child block ... 234 childCoreBlk := snowmantest.BuildChild(parentCoreBlk) 235 childBlk := preForkBlock{ 236 Block: childCoreBlk, 237 vm: proVM, 238 } 239 240 { 241 // child block referring unknown parent does not verify 242 childCoreBlk.ParentV = ids.Empty 243 err = childBlk.Verify(context.Background()) 244 require.ErrorIs(err, database.ErrNotFound) 245 } 246 247 { 248 // child block referring known parent does verify 249 childCoreBlk.ParentV = parentBlk.ID() 250 require.NoError(childBlk.Verify(context.Background())) 251 } 252 } 253 254 func TestBlockVerify_BlocksBuiltOnPreForkGenesis(t *testing.T) { 255 require := require.New(t) 256 257 var ( 258 activationTime = snowmantest.GenesisTimestamp.Add(10 * time.Second) 259 durangoTime = activationTime 260 ) 261 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 262 defer func() { 263 require.NoError(proVM.Shutdown(context.Background())) 264 }() 265 266 preActivationTime := activationTime.Add(-1 * time.Second) 267 proVM.Set(preActivationTime) 268 269 coreBlk := snowmantest.BuildChild(snowmantest.Genesis) 270 coreBlk.TimestampV = preActivationTime 271 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 272 return coreBlk, nil 273 } 274 275 // preFork block verifies if parent is before fork activation time 276 preForkChild, err := proVM.BuildBlock(context.Background()) 277 require.NoError(err) 278 require.IsType(&preForkBlock{}, preForkChild) 279 280 require.NoError(preForkChild.Verify(context.Background())) 281 282 // postFork block does NOT verify if parent is before fork activation time 283 postForkStatelessChild, err := statelessblock.Build( 284 snowmantest.GenesisID, 285 coreBlk.Timestamp(), 286 0, // pChainHeight 287 proVM.StakingCertLeaf, 288 coreBlk.Bytes(), 289 proVM.ctx.ChainID, 290 proVM.StakingLeafSigner, 291 ) 292 require.NoError(err) 293 postForkChild := &postForkBlock{ 294 SignedBlock: postForkStatelessChild, 295 postForkCommonComponents: postForkCommonComponents{ 296 vm: proVM, 297 innerBlk: coreBlk, 298 }, 299 } 300 301 require.True(postForkChild.Timestamp().Before(activationTime)) 302 err = postForkChild.Verify(context.Background()) 303 require.ErrorIs(err, errProposersNotActivated) 304 305 // once activation time is crossed postForkBlock are produced 306 postActivationTime := activationTime.Add(time.Second) 307 proVM.Set(postActivationTime) 308 309 coreVM.SetPreferenceF = func(context.Context, ids.ID) error { 310 return nil 311 } 312 require.NoError(proVM.SetPreference(context.Background(), preForkChild.ID())) 313 314 secondCoreBlk := snowmantest.BuildChild(coreBlk) 315 secondCoreBlk.TimestampV = postActivationTime 316 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 317 return secondCoreBlk, nil 318 } 319 coreVM.GetBlockF = func(_ context.Context, id ids.ID) (snowman.Block, error) { 320 switch id { 321 case snowmantest.GenesisID: 322 return snowmantest.Genesis, nil 323 case coreBlk.ID(): 324 return coreBlk, nil 325 default: 326 require.FailNow("attempt to get unknown block") 327 return nil, nil 328 } 329 } 330 331 lastPreForkBlk, err := proVM.BuildBlock(context.Background()) 332 require.NoError(err) 333 require.IsType(&preForkBlock{}, lastPreForkBlk) 334 335 require.NoError(lastPreForkBlk.Verify(context.Background())) 336 337 require.NoError(proVM.SetPreference(context.Background(), lastPreForkBlk.ID())) 338 thirdCoreBlk := snowmantest.BuildChild(secondCoreBlk) 339 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 340 return thirdCoreBlk, nil 341 } 342 coreVM.GetBlockF = func(_ context.Context, id ids.ID) (snowman.Block, error) { 343 switch id { 344 case snowmantest.GenesisID: 345 return snowmantest.Genesis, nil 346 case coreBlk.ID(): 347 return coreBlk, nil 348 case secondCoreBlk.ID(): 349 return secondCoreBlk, nil 350 default: 351 require.FailNow("attempt to get unknown block") 352 return nil, nil 353 } 354 } 355 356 firstPostForkBlk, err := proVM.BuildBlock(context.Background()) 357 require.NoError(err) 358 require.IsType(&postForkBlock{}, firstPostForkBlk) 359 360 require.NoError(firstPostForkBlk.Verify(context.Background())) 361 } 362 363 func TestBlockVerify_BlocksBuiltOnPostForkGenesis(t *testing.T) { 364 require := require.New(t) 365 366 var ( 367 activationTime = snowmantest.GenesisTimestamp.Add(-1 * time.Second) 368 durangoTime = activationTime 369 ) 370 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 371 proVM.Set(activationTime) 372 defer func() { 373 require.NoError(proVM.Shutdown(context.Background())) 374 }() 375 376 // build parent block after fork activation time ... 377 coreBlock := snowmantest.BuildChild(snowmantest.Genesis) 378 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 379 return coreBlock, nil 380 } 381 382 // postFork block verifies if parent is after fork activation time 383 postForkChild, err := proVM.BuildBlock(context.Background()) 384 require.NoError(err) 385 require.IsType(&postForkBlock{}, postForkChild) 386 387 require.NoError(postForkChild.Verify(context.Background())) 388 389 // preFork block does NOT verify if parent is after fork activation time 390 preForkChild := preForkBlock{ 391 Block: coreBlock, 392 vm: proVM, 393 } 394 err = preForkChild.Verify(context.Background()) 395 require.ErrorIs(err, errUnexpectedBlockType) 396 } 397 398 func TestBlockAccept_PreFork_SetsLastAcceptedBlock(t *testing.T) { 399 require := require.New(t) 400 401 // setup 402 var ( 403 activationTime = mockable.MaxTime 404 durangoTime = activationTime 405 ) 406 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 407 defer func() { 408 require.NoError(proVM.Shutdown(context.Background())) 409 }() 410 411 coreBlk := snowmantest.BuildChild(snowmantest.Genesis) 412 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 413 return coreBlk, nil 414 } 415 coreVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { 416 switch blkID { 417 case snowmantest.GenesisID: 418 return snowmantest.Genesis, nil 419 case coreBlk.ID(): 420 return coreBlk, nil 421 default: 422 return nil, database.ErrNotFound 423 } 424 } 425 coreVM.ParseBlockF = func(_ context.Context, b []byte) (snowman.Block, error) { 426 switch { 427 case bytes.Equal(b, snowmantest.GenesisBytes): 428 return snowmantest.Genesis, nil 429 case bytes.Equal(b, coreBlk.Bytes()): 430 return coreBlk, nil 431 default: 432 return nil, errUnknownBlock 433 } 434 } 435 436 builtBlk, err := proVM.BuildBlock(context.Background()) 437 require.NoError(err) 438 439 // test 440 require.NoError(builtBlk.Accept(context.Background())) 441 442 coreVM.LastAcceptedF = snowmantest.MakeLastAcceptedBlockF( 443 []*snowmantest.Block{ 444 snowmantest.Genesis, 445 coreBlk, 446 }, 447 ) 448 acceptedID, err := proVM.LastAccepted(context.Background()) 449 require.NoError(err) 450 require.Equal(builtBlk.ID(), acceptedID) 451 } 452 453 // ProposerBlock.Reject tests section 454 func TestBlockReject_PreForkBlock_InnerBlockIsRejected(t *testing.T) { 455 require := require.New(t) 456 457 var ( 458 activationTime = mockable.MaxTime 459 durangoTime = activationTime 460 ) 461 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 462 defer func() { 463 require.NoError(proVM.Shutdown(context.Background())) 464 }() 465 466 coreBlk := snowmantest.BuildChild(snowmantest.Genesis) 467 coreVM.BuildBlockF = func(context.Context) (snowman.Block, error) { 468 return coreBlk, nil 469 } 470 471 sb, err := proVM.BuildBlock(context.Background()) 472 require.NoError(err) 473 require.IsType(&preForkBlock{}, sb) 474 proBlk := sb.(*preForkBlock) 475 476 require.NoError(proBlk.Reject(context.Background())) 477 require.Equal(snowtest.Rejected, coreBlk.Status) 478 } 479 480 func TestBlockVerify_ForkBlockIsOracleBlock(t *testing.T) { 481 require := require.New(t) 482 483 var ( 484 activationTime = snowmantest.GenesisTimestamp.Add(10 * time.Second) 485 durangoTime = activationTime 486 ) 487 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 488 defer func() { 489 require.NoError(proVM.Shutdown(context.Background())) 490 }() 491 492 postActivationTime := activationTime.Add(time.Second) 493 proVM.Set(postActivationTime) 494 495 coreTestBlk := snowmantest.BuildChild(snowmantest.Genesis) 496 coreTestBlk.TimestampV = postActivationTime 497 coreBlk := &TestOptionsBlock{ 498 Block: *coreTestBlk, 499 opts: [2]*snowmantest.Block{ 500 snowmantest.BuildChild(coreTestBlk), 501 snowmantest.BuildChild(coreTestBlk), 502 }, 503 } 504 505 coreVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { 506 switch blkID { 507 case snowmantest.GenesisID: 508 return snowmantest.Genesis, nil 509 case coreBlk.ID(): 510 return coreBlk, nil 511 case coreBlk.opts[0].ID(): 512 return coreBlk.opts[0], nil 513 case coreBlk.opts[1].ID(): 514 return coreBlk.opts[1], nil 515 default: 516 return nil, database.ErrNotFound 517 } 518 } 519 coreVM.ParseBlockF = func(_ context.Context, b []byte) (snowman.Block, error) { 520 switch { 521 case bytes.Equal(b, snowmantest.GenesisBytes): 522 return snowmantest.Genesis, nil 523 case bytes.Equal(b, coreBlk.Bytes()): 524 return coreBlk, nil 525 case bytes.Equal(b, coreBlk.opts[0].Bytes()): 526 return coreBlk.opts[0], nil 527 case bytes.Equal(b, coreBlk.opts[1].Bytes()): 528 return coreBlk.opts[1], nil 529 default: 530 return nil, errUnknownBlock 531 } 532 } 533 534 firstBlock, err := proVM.ParseBlock(context.Background(), coreBlk.Bytes()) 535 require.NoError(err) 536 537 require.NoError(firstBlock.Verify(context.Background())) 538 539 oracleBlock, ok := firstBlock.(snowman.OracleBlock) 540 require.True(ok) 541 542 options, err := oracleBlock.Options(context.Background()) 543 require.NoError(err) 544 545 require.NoError(options[0].Verify(context.Background())) 546 547 require.NoError(options[1].Verify(context.Background())) 548 } 549 550 func TestBlockVerify_ForkBlockIsOracleBlockButChildrenAreSigned(t *testing.T) { 551 require := require.New(t) 552 553 var ( 554 activationTime = snowmantest.GenesisTimestamp.Add(10 * time.Second) 555 durangoTime = activationTime 556 ) 557 coreVM, _, proVM, _ := initTestProposerVM(t, activationTime, durangoTime, 0) 558 defer func() { 559 require.NoError(proVM.Shutdown(context.Background())) 560 }() 561 562 postActivationTime := activationTime.Add(time.Second) 563 proVM.Set(postActivationTime) 564 565 coreTestBlk := snowmantest.BuildChild(snowmantest.Genesis) 566 coreTestBlk.TimestampV = postActivationTime 567 coreBlk := &TestOptionsBlock{ 568 Block: *coreTestBlk, 569 opts: [2]*snowmantest.Block{ 570 snowmantest.BuildChild(coreTestBlk), 571 snowmantest.BuildChild(coreTestBlk), 572 }, 573 } 574 575 coreVM.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { 576 switch blkID { 577 case snowmantest.GenesisID: 578 return snowmantest.Genesis, nil 579 case coreBlk.ID(): 580 return coreBlk, nil 581 case coreBlk.opts[0].ID(): 582 return coreBlk.opts[0], nil 583 case coreBlk.opts[1].ID(): 584 return coreBlk.opts[1], nil 585 default: 586 return nil, database.ErrNotFound 587 } 588 } 589 coreVM.ParseBlockF = func(_ context.Context, b []byte) (snowman.Block, error) { 590 switch { 591 case bytes.Equal(b, snowmantest.GenesisBytes): 592 return snowmantest.Genesis, nil 593 case bytes.Equal(b, coreBlk.Bytes()): 594 return coreBlk, nil 595 case bytes.Equal(b, coreBlk.opts[0].Bytes()): 596 return coreBlk.opts[0], nil 597 case bytes.Equal(b, coreBlk.opts[1].Bytes()): 598 return coreBlk.opts[1], nil 599 default: 600 return nil, errUnknownBlock 601 } 602 } 603 604 firstBlock, err := proVM.ParseBlock(context.Background(), coreBlk.Bytes()) 605 require.NoError(err) 606 607 require.NoError(firstBlock.Verify(context.Background())) 608 609 slb, err := statelessblock.Build( 610 firstBlock.ID(), // refer unknown parent 611 firstBlock.Timestamp(), 612 0, // pChainHeight, 613 proVM.StakingCertLeaf, 614 coreBlk.opts[0].Bytes(), 615 proVM.ctx.ChainID, 616 proVM.StakingLeafSigner, 617 ) 618 require.NoError(err) 619 620 invalidChild, err := proVM.ParseBlock(context.Background(), slb.Bytes()) 621 if err != nil { 622 // A failure to parse is okay here 623 return 624 } 625 626 err = invalidChild.Verify(context.Background()) 627 require.ErrorIs(err, errUnexpectedBlockType) 628 } 629 630 // Assert that when the underlying VM implements ChainVMWithBuildBlockContext 631 // and the proposervm is activated, we only call the VM's BuildBlockWithContext 632 // when a P-chain height can be correctly provided from the parent block. 633 func TestPreForkBlock_BuildBlockWithContext(t *testing.T) { 634 require := require.New(t) 635 ctrl := gomock.NewController(t) 636 637 pChainHeight := uint64(1337) 638 blkID := ids.GenerateTestID() 639 innerBlk := snowmanmock.NewBlock(ctrl) 640 innerBlk.EXPECT().ID().Return(blkID).AnyTimes() 641 innerBlk.EXPECT().Timestamp().Return(mockable.MaxTime) 642 builtBlk := snowmanmock.NewBlock(ctrl) 643 builtBlk.EXPECT().Bytes().Return([]byte{1, 2, 3}).AnyTimes() 644 builtBlk.EXPECT().ID().Return(ids.GenerateTestID()).AnyTimes() 645 builtBlk.EXPECT().Height().Return(pChainHeight).AnyTimes() 646 innerVM := blockmock.NewChainVM(ctrl) 647 innerVM.EXPECT().BuildBlock(gomock.Any()).Return(builtBlk, nil).AnyTimes() 648 vdrState := validatorsmock.NewState(ctrl) 649 vdrState.EXPECT().GetMinimumHeight(context.Background()).Return(pChainHeight, nil).AnyTimes() 650 651 vm := &VM{ 652 ChainVM: innerVM, 653 ctx: &snow.Context{ 654 ValidatorState: vdrState, 655 Log: logging.NoLog{}, 656 }, 657 } 658 659 blk := &preForkBlock{ 660 Block: innerBlk, 661 vm: vm, 662 } 663 664 // Should call BuildBlock since proposervm won't have a P-chain height 665 gotChild, err := blk.buildChild(context.Background()) 666 require.NoError(err) 667 require.Equal(builtBlk, gotChild.(*postForkBlock).innerBlk) 668 669 // Should call BuildBlock since proposervm is not activated 670 innerBlk.EXPECT().Timestamp().Return(time.Time{}) 671 vm.Upgrades.ApricotPhase4Time = mockable.MaxTime 672 673 gotChild, err = blk.buildChild(context.Background()) 674 require.NoError(err) 675 require.Equal(builtBlk, gotChild.(*preForkBlock).Block) 676 }