github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/state/diff_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 state 5 6 import ( 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/require" 11 "go.uber.org/mock/gomock" 12 13 "github.com/MetalBlockchain/metalgo/database" 14 "github.com/MetalBlockchain/metalgo/ids" 15 "github.com/MetalBlockchain/metalgo/utils" 16 "github.com/MetalBlockchain/metalgo/utils/constants" 17 "github.com/MetalBlockchain/metalgo/vms/components/avax" 18 "github.com/MetalBlockchain/metalgo/vms/platformvm/fx" 19 "github.com/MetalBlockchain/metalgo/vms/platformvm/status" 20 "github.com/MetalBlockchain/metalgo/vms/platformvm/txs" 21 ) 22 23 func TestDiffMissingState(t *testing.T) { 24 ctrl := gomock.NewController(t) 25 26 versions := NewMockVersions(ctrl) 27 28 parentID := ids.GenerateTestID() 29 versions.EXPECT().GetState(parentID).Times(1).Return(nil, false) 30 31 _, err := NewDiff(parentID, versions) 32 require.ErrorIs(t, err, ErrMissingParentState) 33 } 34 35 func TestDiffCreation(t *testing.T) { 36 require := require.New(t) 37 ctrl := gomock.NewController(t) 38 39 lastAcceptedID := ids.GenerateTestID() 40 state := newInitializedState(require) 41 versions := NewMockVersions(ctrl) 42 versions.EXPECT().GetState(lastAcceptedID).AnyTimes().Return(state, true) 43 44 d, err := NewDiff(lastAcceptedID, versions) 45 require.NoError(err) 46 assertChainsEqual(t, state, d) 47 } 48 49 func TestDiffCurrentSupply(t *testing.T) { 50 require := require.New(t) 51 ctrl := gomock.NewController(t) 52 53 lastAcceptedID := ids.GenerateTestID() 54 state := newInitializedState(require) 55 versions := NewMockVersions(ctrl) 56 versions.EXPECT().GetState(lastAcceptedID).AnyTimes().Return(state, true) 57 58 d, err := NewDiff(lastAcceptedID, versions) 59 require.NoError(err) 60 61 initialCurrentSupply, err := d.GetCurrentSupply(constants.PrimaryNetworkID) 62 require.NoError(err) 63 64 newCurrentSupply := initialCurrentSupply + 1 65 d.SetCurrentSupply(constants.PrimaryNetworkID, newCurrentSupply) 66 67 returnedNewCurrentSupply, err := d.GetCurrentSupply(constants.PrimaryNetworkID) 68 require.NoError(err) 69 require.Equal(newCurrentSupply, returnedNewCurrentSupply) 70 71 returnedBaseCurrentSupply, err := state.GetCurrentSupply(constants.PrimaryNetworkID) 72 require.NoError(err) 73 require.Equal(initialCurrentSupply, returnedBaseCurrentSupply) 74 } 75 76 func TestDiffCurrentValidator(t *testing.T) { 77 require := require.New(t) 78 ctrl := gomock.NewController(t) 79 80 lastAcceptedID := ids.GenerateTestID() 81 state := NewMockState(ctrl) 82 // Called in NewDiff 83 state.EXPECT().GetTimestamp().Return(time.Now()).Times(1) 84 85 states := NewMockVersions(ctrl) 86 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 87 88 d, err := NewDiff(lastAcceptedID, states) 89 require.NoError(err) 90 91 // Put a current validator 92 currentValidator := &Staker{ 93 TxID: ids.GenerateTestID(), 94 SubnetID: ids.GenerateTestID(), 95 NodeID: ids.GenerateTestNodeID(), 96 } 97 d.PutCurrentValidator(currentValidator) 98 99 // Assert that we get the current validator back 100 gotCurrentValidator, err := d.GetCurrentValidator(currentValidator.SubnetID, currentValidator.NodeID) 101 require.NoError(err) 102 require.Equal(currentValidator, gotCurrentValidator) 103 104 // Delete the current validator 105 d.DeleteCurrentValidator(currentValidator) 106 107 // Make sure the deletion worked 108 state.EXPECT().GetCurrentValidator(currentValidator.SubnetID, currentValidator.NodeID).Return(nil, database.ErrNotFound).Times(1) 109 _, err = d.GetCurrentValidator(currentValidator.SubnetID, currentValidator.NodeID) 110 require.ErrorIs(err, database.ErrNotFound) 111 } 112 113 func TestDiffPendingValidator(t *testing.T) { 114 require := require.New(t) 115 ctrl := gomock.NewController(t) 116 117 lastAcceptedID := ids.GenerateTestID() 118 state := NewMockState(ctrl) 119 // Called in NewDiff 120 state.EXPECT().GetTimestamp().Return(time.Now()).Times(1) 121 122 states := NewMockVersions(ctrl) 123 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 124 125 d, err := NewDiff(lastAcceptedID, states) 126 require.NoError(err) 127 128 // Put a pending validator 129 pendingValidator := &Staker{ 130 TxID: ids.GenerateTestID(), 131 SubnetID: ids.GenerateTestID(), 132 NodeID: ids.GenerateTestNodeID(), 133 } 134 d.PutPendingValidator(pendingValidator) 135 136 // Assert that we get the pending validator back 137 gotPendingValidator, err := d.GetPendingValidator(pendingValidator.SubnetID, pendingValidator.NodeID) 138 require.NoError(err) 139 require.Equal(pendingValidator, gotPendingValidator) 140 141 // Delete the pending validator 142 d.DeletePendingValidator(pendingValidator) 143 144 // Make sure the deletion worked 145 state.EXPECT().GetPendingValidator(pendingValidator.SubnetID, pendingValidator.NodeID).Return(nil, database.ErrNotFound).Times(1) 146 _, err = d.GetPendingValidator(pendingValidator.SubnetID, pendingValidator.NodeID) 147 require.ErrorIs(err, database.ErrNotFound) 148 } 149 150 func TestDiffCurrentDelegator(t *testing.T) { 151 require := require.New(t) 152 ctrl := gomock.NewController(t) 153 154 currentDelegator := &Staker{ 155 TxID: ids.GenerateTestID(), 156 SubnetID: ids.GenerateTestID(), 157 NodeID: ids.GenerateTestNodeID(), 158 } 159 160 state := NewMockState(ctrl) 161 // Called in NewDiff 162 state.EXPECT().GetTimestamp().Return(time.Now()).Times(1) 163 164 states := NewMockVersions(ctrl) 165 lastAcceptedID := ids.GenerateTestID() 166 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 167 168 d, err := NewDiff(lastAcceptedID, states) 169 require.NoError(err) 170 171 // Put a current delegator 172 d.PutCurrentDelegator(currentDelegator) 173 174 // Assert that we get the current delegator back 175 // Mock iterator for [state] returns no delegators. 176 stateCurrentDelegatorIter := NewMockStakerIterator(ctrl) 177 stateCurrentDelegatorIter.EXPECT().Next().Return(false).Times(2) 178 stateCurrentDelegatorIter.EXPECT().Release().Times(2) 179 state.EXPECT().GetCurrentDelegatorIterator( 180 currentDelegator.SubnetID, 181 currentDelegator.NodeID, 182 ).Return(stateCurrentDelegatorIter, nil).Times(2) 183 gotCurrentDelegatorIter, err := d.GetCurrentDelegatorIterator(currentDelegator.SubnetID, currentDelegator.NodeID) 184 require.NoError(err) 185 // The iterator should have the 1 delegator we put in [d] 186 require.True(gotCurrentDelegatorIter.Next()) 187 require.Equal(gotCurrentDelegatorIter.Value(), currentDelegator) 188 189 // Delete the current delegator 190 d.DeleteCurrentDelegator(currentDelegator) 191 192 // Make sure the deletion worked. 193 // The iterator should have no elements. 194 gotCurrentDelegatorIter, err = d.GetCurrentDelegatorIterator(currentDelegator.SubnetID, currentDelegator.NodeID) 195 require.NoError(err) 196 require.False(gotCurrentDelegatorIter.Next()) 197 } 198 199 func TestDiffPendingDelegator(t *testing.T) { 200 require := require.New(t) 201 ctrl := gomock.NewController(t) 202 203 pendingDelegator := &Staker{ 204 TxID: ids.GenerateTestID(), 205 SubnetID: ids.GenerateTestID(), 206 NodeID: ids.GenerateTestNodeID(), 207 } 208 209 state := NewMockState(ctrl) 210 // Called in NewDiff 211 state.EXPECT().GetTimestamp().Return(time.Now()).Times(1) 212 213 states := NewMockVersions(ctrl) 214 lastAcceptedID := ids.GenerateTestID() 215 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 216 217 d, err := NewDiff(lastAcceptedID, states) 218 require.NoError(err) 219 220 // Put a pending delegator 221 d.PutPendingDelegator(pendingDelegator) 222 223 // Assert that we get the pending delegator back 224 // Mock iterator for [state] returns no delegators. 225 statePendingDelegatorIter := NewMockStakerIterator(ctrl) 226 statePendingDelegatorIter.EXPECT().Next().Return(false).Times(2) 227 statePendingDelegatorIter.EXPECT().Release().Times(2) 228 state.EXPECT().GetPendingDelegatorIterator( 229 pendingDelegator.SubnetID, 230 pendingDelegator.NodeID, 231 ).Return(statePendingDelegatorIter, nil).Times(2) 232 gotPendingDelegatorIter, err := d.GetPendingDelegatorIterator(pendingDelegator.SubnetID, pendingDelegator.NodeID) 233 require.NoError(err) 234 // The iterator should have the 1 delegator we put in [d] 235 require.True(gotPendingDelegatorIter.Next()) 236 require.Equal(gotPendingDelegatorIter.Value(), pendingDelegator) 237 238 // Delete the pending delegator 239 d.DeletePendingDelegator(pendingDelegator) 240 241 // Make sure the deletion worked. 242 // The iterator should have no elements. 243 gotPendingDelegatorIter, err = d.GetPendingDelegatorIterator(pendingDelegator.SubnetID, pendingDelegator.NodeID) 244 require.NoError(err) 245 require.False(gotPendingDelegatorIter.Next()) 246 } 247 248 func TestDiffSubnet(t *testing.T) { 249 require := require.New(t) 250 ctrl := gomock.NewController(t) 251 252 state := newInitializedState(require) 253 254 // Initialize parent with one subnet 255 parentStateCreateSubnetTx := &txs.Tx{ 256 Unsigned: &txs.CreateSubnetTx{ 257 Owner: fx.NewMockOwner(ctrl), 258 }, 259 } 260 state.AddSubnet(parentStateCreateSubnetTx.ID()) 261 262 // Verify parent returns one subnet 263 subnetIDs, err := state.GetSubnetIDs() 264 require.NoError(err) 265 require.Equal([]ids.ID{ 266 parentStateCreateSubnetTx.ID(), 267 }, subnetIDs) 268 269 states := NewMockVersions(ctrl) 270 lastAcceptedID := ids.GenerateTestID() 271 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 272 273 diff, err := NewDiff(lastAcceptedID, states) 274 require.NoError(err) 275 276 // Put a subnet 277 createSubnetTx := &txs.Tx{ 278 Unsigned: &txs.CreateSubnetTx{ 279 Owner: fx.NewMockOwner(ctrl), 280 }, 281 } 282 diff.AddSubnet(createSubnetTx.ID()) 283 284 // Apply diff to parent state 285 require.NoError(diff.Apply(state)) 286 287 // Verify parent now returns two subnets 288 subnetIDs, err = state.GetSubnetIDs() 289 require.NoError(err) 290 require.Equal([]ids.ID{ 291 parentStateCreateSubnetTx.ID(), 292 createSubnetTx.ID(), 293 }, subnetIDs) 294 } 295 296 func TestDiffChain(t *testing.T) { 297 require := require.New(t) 298 ctrl := gomock.NewController(t) 299 300 state := newInitializedState(require) 301 subnetID := ids.GenerateTestID() 302 303 // Initialize parent with one chain 304 parentStateCreateChainTx := &txs.Tx{ 305 Unsigned: &txs.CreateChainTx{ 306 SubnetID: subnetID, 307 }, 308 } 309 state.AddChain(parentStateCreateChainTx) 310 311 // Verify parent returns one chain 312 chains, err := state.GetChains(subnetID) 313 require.NoError(err) 314 require.Equal([]*txs.Tx{ 315 parentStateCreateChainTx, 316 }, chains) 317 318 states := NewMockVersions(ctrl) 319 lastAcceptedID := ids.GenerateTestID() 320 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 321 322 diff, err := NewDiff(lastAcceptedID, states) 323 require.NoError(err) 324 325 // Put a chain 326 createChainTx := &txs.Tx{ 327 Unsigned: &txs.CreateChainTx{ 328 SubnetID: subnetID, // note this is the same subnet as [parentStateCreateChainTx] 329 }, 330 } 331 diff.AddChain(createChainTx) 332 333 // Apply diff to parent state 334 require.NoError(diff.Apply(state)) 335 336 // Verify parent now returns two chains 337 chains, err = state.GetChains(subnetID) 338 require.NoError(err) 339 require.Equal([]*txs.Tx{ 340 parentStateCreateChainTx, 341 createChainTx, 342 }, chains) 343 } 344 345 func TestDiffTx(t *testing.T) { 346 require := require.New(t) 347 ctrl := gomock.NewController(t) 348 349 state := NewMockState(ctrl) 350 // Called in NewDiff 351 state.EXPECT().GetTimestamp().Return(time.Now()).Times(1) 352 353 states := NewMockVersions(ctrl) 354 lastAcceptedID := ids.GenerateTestID() 355 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 356 357 d, err := NewDiff(lastAcceptedID, states) 358 require.NoError(err) 359 360 // Put a tx 361 subnetID := ids.GenerateTestID() 362 tx := &txs.Tx{ 363 Unsigned: &txs.CreateChainTx{ 364 SubnetID: subnetID, 365 }, 366 } 367 tx.SetBytes(utils.RandomBytes(16), utils.RandomBytes(16)) 368 d.AddTx(tx, status.Committed) 369 370 { 371 // Assert that we get the tx back 372 gotTx, gotStatus, err := d.GetTx(tx.ID()) 373 require.NoError(err) 374 require.Equal(status.Committed, gotStatus) 375 require.Equal(tx, gotTx) 376 } 377 378 { 379 // Assert that we can get a tx from the parent state 380 // [state] returns 1 tx. 381 parentTx := &txs.Tx{ 382 Unsigned: &txs.CreateChainTx{ 383 SubnetID: subnetID, 384 }, 385 } 386 parentTx.SetBytes(utils.RandomBytes(16), utils.RandomBytes(16)) 387 state.EXPECT().GetTx(parentTx.ID()).Return(parentTx, status.Committed, nil).Times(1) 388 gotParentTx, gotStatus, err := d.GetTx(parentTx.ID()) 389 require.NoError(err) 390 require.Equal(status.Committed, gotStatus) 391 require.Equal(parentTx, gotParentTx) 392 } 393 } 394 395 func TestDiffRewardUTXO(t *testing.T) { 396 require := require.New(t) 397 ctrl := gomock.NewController(t) 398 399 state := newInitializedState(require) 400 401 txID := ids.GenerateTestID() 402 403 // Initialize parent with one reward UTXO 404 parentRewardUTXO := &avax.UTXO{ 405 UTXOID: avax.UTXOID{TxID: txID}, 406 } 407 state.AddRewardUTXO(txID, parentRewardUTXO) 408 409 // Verify parent returns the reward UTXO 410 rewardUTXOs, err := state.GetRewardUTXOs(txID) 411 require.NoError(err) 412 require.Equal([]*avax.UTXO{ 413 parentRewardUTXO, 414 }, rewardUTXOs) 415 416 states := NewMockVersions(ctrl) 417 lastAcceptedID := ids.GenerateTestID() 418 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 419 420 diff, err := NewDiff(lastAcceptedID, states) 421 require.NoError(err) 422 423 // Put a reward UTXO 424 rewardUTXO := &avax.UTXO{ 425 UTXOID: avax.UTXOID{TxID: txID}, 426 } 427 diff.AddRewardUTXO(txID, rewardUTXO) 428 429 // Apply diff to parent state 430 require.NoError(diff.Apply(state)) 431 432 // Verify parent now returns two reward UTXOs 433 rewardUTXOs, err = state.GetRewardUTXOs(txID) 434 require.NoError(err) 435 require.Equal([]*avax.UTXO{ 436 parentRewardUTXO, 437 rewardUTXO, 438 }, rewardUTXOs) 439 } 440 441 func TestDiffUTXO(t *testing.T) { 442 require := require.New(t) 443 ctrl := gomock.NewController(t) 444 445 state := NewMockState(ctrl) 446 // Called in NewDiff 447 state.EXPECT().GetTimestamp().Return(time.Now()).Times(1) 448 449 states := NewMockVersions(ctrl) 450 lastAcceptedID := ids.GenerateTestID() 451 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 452 453 d, err := NewDiff(lastAcceptedID, states) 454 require.NoError(err) 455 456 // Put a UTXO 457 utxo := &avax.UTXO{ 458 UTXOID: avax.UTXOID{TxID: ids.GenerateTestID()}, 459 } 460 d.AddUTXO(utxo) 461 462 { 463 // Assert that we get the UTXO back 464 gotUTXO, err := d.GetUTXO(utxo.InputID()) 465 require.NoError(err) 466 require.Equal(utxo, gotUTXO) 467 } 468 469 { 470 // Assert that we can get a UTXO from the parent state 471 // [state] returns 1 UTXO. 472 parentUTXO := &avax.UTXO{ 473 UTXOID: avax.UTXOID{TxID: ids.GenerateTestID()}, 474 } 475 state.EXPECT().GetUTXO(parentUTXO.InputID()).Return(parentUTXO, nil).Times(1) 476 gotParentUTXO, err := d.GetUTXO(parentUTXO.InputID()) 477 require.NoError(err) 478 require.Equal(parentUTXO, gotParentUTXO) 479 } 480 481 { 482 // Delete the UTXO 483 d.DeleteUTXO(utxo.InputID()) 484 485 // Make sure it's gone 486 _, err = d.GetUTXO(utxo.InputID()) 487 require.ErrorIs(err, database.ErrNotFound) 488 } 489 } 490 491 func assertChainsEqual(t *testing.T, expected, actual Chain) { 492 require := require.New(t) 493 494 t.Helper() 495 496 expectedCurrentStakerIterator, expectedErr := expected.GetCurrentStakerIterator() 497 actualCurrentStakerIterator, actualErr := actual.GetCurrentStakerIterator() 498 require.Equal(expectedErr, actualErr) 499 if expectedErr == nil { 500 assertIteratorsEqual(t, expectedCurrentStakerIterator, actualCurrentStakerIterator) 501 } 502 503 expectedPendingStakerIterator, expectedErr := expected.GetPendingStakerIterator() 504 actualPendingStakerIterator, actualErr := actual.GetPendingStakerIterator() 505 require.Equal(expectedErr, actualErr) 506 if expectedErr == nil { 507 assertIteratorsEqual(t, expectedPendingStakerIterator, actualPendingStakerIterator) 508 } 509 510 require.Equal(expected.GetTimestamp(), actual.GetTimestamp()) 511 512 expectedCurrentSupply, err := expected.GetCurrentSupply(constants.PrimaryNetworkID) 513 require.NoError(err) 514 515 actualCurrentSupply, err := actual.GetCurrentSupply(constants.PrimaryNetworkID) 516 require.NoError(err) 517 518 require.Equal(expectedCurrentSupply, actualCurrentSupply) 519 } 520 521 func TestDiffSubnetOwner(t *testing.T) { 522 require := require.New(t) 523 ctrl := gomock.NewController(t) 524 525 state := newInitializedState(require) 526 527 states := NewMockVersions(ctrl) 528 lastAcceptedID := ids.GenerateTestID() 529 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 530 531 var ( 532 owner1 = fx.NewMockOwner(ctrl) 533 owner2 = fx.NewMockOwner(ctrl) 534 535 createSubnetTx = &txs.Tx{ 536 Unsigned: &txs.CreateSubnetTx{ 537 BaseTx: txs.BaseTx{}, 538 Owner: owner1, 539 }, 540 } 541 542 subnetID = createSubnetTx.ID() 543 ) 544 545 // Create subnet on base state 546 owner, err := state.GetSubnetOwner(subnetID) 547 require.ErrorIs(err, database.ErrNotFound) 548 require.Nil(owner) 549 550 state.AddSubnet(subnetID) 551 state.SetSubnetOwner(subnetID, owner1) 552 553 owner, err = state.GetSubnetOwner(subnetID) 554 require.NoError(err) 555 require.Equal(owner1, owner) 556 557 // Create diff and verify that subnet owner returns correctly 558 d, err := NewDiff(lastAcceptedID, states) 559 require.NoError(err) 560 561 owner, err = d.GetSubnetOwner(subnetID) 562 require.NoError(err) 563 require.Equal(owner1, owner) 564 565 // Transferring subnet ownership on diff should be reflected on diff not state 566 d.SetSubnetOwner(subnetID, owner2) 567 owner, err = d.GetSubnetOwner(subnetID) 568 require.NoError(err) 569 require.Equal(owner2, owner) 570 571 owner, err = state.GetSubnetOwner(subnetID) 572 require.NoError(err) 573 require.Equal(owner1, owner) 574 575 // State should reflect new subnet owner after diff is applied. 576 require.NoError(d.Apply(state)) 577 578 owner, err = state.GetSubnetOwner(subnetID) 579 require.NoError(err) 580 require.Equal(owner2, owner) 581 } 582 583 func TestDiffStacking(t *testing.T) { 584 require := require.New(t) 585 ctrl := gomock.NewController(t) 586 587 state := newInitializedState(require) 588 589 states := NewMockVersions(ctrl) 590 lastAcceptedID := ids.GenerateTestID() 591 states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() 592 593 var ( 594 owner1 = fx.NewMockOwner(ctrl) 595 owner2 = fx.NewMockOwner(ctrl) 596 owner3 = fx.NewMockOwner(ctrl) 597 598 createSubnetTx = &txs.Tx{ 599 Unsigned: &txs.CreateSubnetTx{ 600 BaseTx: txs.BaseTx{}, 601 Owner: owner1, 602 }, 603 } 604 605 subnetID = createSubnetTx.ID() 606 ) 607 608 // Create subnet on base state 609 owner, err := state.GetSubnetOwner(subnetID) 610 require.ErrorIs(err, database.ErrNotFound) 611 require.Nil(owner) 612 613 state.AddSubnet(subnetID) 614 state.SetSubnetOwner(subnetID, owner1) 615 616 owner, err = state.GetSubnetOwner(subnetID) 617 require.NoError(err) 618 require.Equal(owner1, owner) 619 620 // Create first diff and verify that subnet owner returns correctly 621 statesDiff, err := NewDiff(lastAcceptedID, states) 622 require.NoError(err) 623 624 owner, err = statesDiff.GetSubnetOwner(subnetID) 625 require.NoError(err) 626 require.Equal(owner1, owner) 627 628 // Transferring subnet ownership on first diff should be reflected on first diff not state 629 statesDiff.SetSubnetOwner(subnetID, owner2) 630 owner, err = statesDiff.GetSubnetOwner(subnetID) 631 require.NoError(err) 632 require.Equal(owner2, owner) 633 634 owner, err = state.GetSubnetOwner(subnetID) 635 require.NoError(err) 636 require.Equal(owner1, owner) 637 638 // Create a second diff on first diff and verify that subnet owner returns correctly 639 stackedDiff, err := NewDiffOn(statesDiff) 640 require.NoError(err) 641 owner, err = stackedDiff.GetSubnetOwner(subnetID) 642 require.NoError(err) 643 require.Equal(owner2, owner) 644 645 // Transfer ownership on stacked diff and verify it is only reflected on stacked diff 646 stackedDiff.SetSubnetOwner(subnetID, owner3) 647 owner, err = stackedDiff.GetSubnetOwner(subnetID) 648 require.NoError(err) 649 require.Equal(owner3, owner) 650 651 owner, err = statesDiff.GetSubnetOwner(subnetID) 652 require.NoError(err) 653 require.Equal(owner2, owner) 654 655 owner, err = state.GetSubnetOwner(subnetID) 656 require.NoError(err) 657 require.Equal(owner1, owner) 658 659 // Applying both diffs successively should work as expected. 660 require.NoError(stackedDiff.Apply(statesDiff)) 661 662 owner, err = statesDiff.GetSubnetOwner(subnetID) 663 require.NoError(err) 664 require.Equal(owner3, owner) 665 666 owner, err = state.GetSubnetOwner(subnetID) 667 require.NoError(err) 668 require.Equal(owner1, owner) 669 670 require.NoError(statesDiff.Apply(state)) 671 672 owner, err = state.GetSubnetOwner(subnetID) 673 require.NoError(err) 674 require.Equal(owner3, owner) 675 }