From 8c99fa21ccac75b3a8f88f240b01111f9bbf29cb Mon Sep 17 00:00:00 2001 From: evlekht <> Date: Fri, 10 Nov 2023 12:44:42 +0400 Subject: [PATCH] [PVM] Forbid to change AddressStateBitConsortium with addressStateTx --- vms/platformvm/camino_vm_test.go | 43 ++++++++++++--- .../txs/executor/camino_tx_executor.go | 17 ++++-- .../txs/executor/camino_tx_executor_test.go | 54 ++++++++++++------- 3 files changed, 85 insertions(+), 29 deletions(-) diff --git a/vms/platformvm/camino_vm_test.go b/vms/platformvm/camino_vm_test.go index d8ace4adf9ad..b0b0e47902e8 100644 --- a/vms/platformvm/camino_vm_test.go +++ b/vms/platformvm/camino_vm_test.go @@ -47,6 +47,8 @@ func TestRemoveDeferredValidator(t *testing.T) { nodeKey, nodeID := nodeid.GenerateCaminoNodeKeyAndID() + rootAdminKey := caminoPreFundedKeys[0] + adminProposerKey := caminoPreFundedKeys[0] consortiumMemberKey, err := testKeyFactory.NewPrivateKey() require.NoError(err) @@ -81,14 +83,28 @@ func TestRemoveDeferredValidator(t *testing.T) { // Set consortium member tx, err := vm.txBuilder.NewAddressStateTx( - consortiumMemberKey.Address(), + adminProposerKey.Address(), false, - as.AddressStateBitConsortium, - []*secp256k1.PrivateKey{caminoPreFundedKeys[0]}, + as.AddressStateBitAdminProposer, + []*secp256k1.PrivateKey{rootAdminKey}, outputOwners, ) require.NoError(err) _ = buildAndAcceptBlock(t, vm, tx) + proposalTx := buildAddMemberProposalTx( + t, + vm, + caminoPreFundedKeys[0], + vm.Config.CaminoConfig.DACProposalBondAmount, + defaultTxFee, + adminProposerKey, // AdminProposer + consortiumMemberKey.Address(), + vm.clock.Time(), + true, + ) + _, _, _, _ = makeProposalWithTx(t, vm, proposalTx) // add admin proposal + _ = buildAndAcceptBlock(t, vm, nil) // execute admin proposal + // Register node tx, err = vm.txBuilder.NewRegisterNodeTx( ids.EmptyNodeID, @@ -217,6 +233,8 @@ func TestRemoveReactivatedValidator(t *testing.T) { nodeKey, nodeID := nodeid.GenerateCaminoNodeKeyAndID() + rootAdminKey := caminoPreFundedKeys[0] + adminProposerKey := caminoPreFundedKeys[0] consortiumMemberKey, err := testKeyFactory.NewPrivateKey() require.NoError(err) @@ -251,14 +269,27 @@ func TestRemoveReactivatedValidator(t *testing.T) { // Set consortium member tx, err := vm.txBuilder.NewAddressStateTx( - consortiumMemberKey.Address(), + adminProposerKey.Address(), false, - as.AddressStateBitConsortium, - []*secp256k1.PrivateKey{caminoPreFundedKeys[0]}, + as.AddressStateBitAdminProposer, + []*secp256k1.PrivateKey{rootAdminKey}, outputOwners, ) require.NoError(err) _ = buildAndAcceptBlock(t, vm, tx) + proposalTx := buildAddMemberProposalTx( + t, + vm, + caminoPreFundedKeys[0], + vm.Config.CaminoConfig.DACProposalBondAmount, + defaultTxFee, + adminProposerKey, // AdminProposer + consortiumMemberKey.Address(), + vm.clock.Time(), + true, + ) + _, _, _, _ = makeProposalWithTx(t, vm, proposalTx) // add admin proposal + _ = buildAndAcceptBlock(t, vm, nil) // execute admin proposal // Register node tx, err = vm.txBuilder.NewRegisterNodeTx( diff --git a/vms/platformvm/txs/executor/camino_tx_executor.go b/vms/platformvm/txs/executor/camino_tx_executor.go index 0dcb5054b062..62c6f3bdc3c2 100644 --- a/vms/platformvm/txs/executor/camino_tx_executor.go +++ b/vms/platformvm/txs/executor/camino_tx_executor.go @@ -2149,8 +2149,11 @@ func (e *CaminoStandardTxExecutor) AddressStateTx(tx *txs.AddressStateTx) error roles := as.AddressStateEmpty creds := e.Tx.Creds + chainTime := e.State.GetTimestamp() + isAthensPhase := e.Config.IsAthensPhaseActivated(chainTime) + if tx.UpgradeVersionID.Version() > 0 { - if !e.Config.IsAthensPhaseActivated(e.State.GetTimestamp()) { + if !isAthensPhase { return errNotAthensPhase } if err = e.Backend.Fx.VerifyMultisigPermission( @@ -2199,9 +2202,15 @@ func (e *CaminoStandardTxExecutor) AddressStateTx(tx *txs.AddressStateTx) error } statesBit := as.AddressState(1) << tx.State - // Check for AthensPhase Bits if we time has not passed yet - if (statesBit&as.AddressStateAthensPhaseBits) != 0 && - !e.Config.IsAthensPhaseActivated(e.State.GetTimestamp()) { + // Check for bits that was affected or introduced in AthensPhase + if !isAthensPhase && statesBit&as.AddressStateAthensPhaseBits != 0 { + return errAddrStateNotPermitted + } + + // Check for bits that was affected or introduced in BerlinPhase + isBerlinPhase := e.Config.IsBerlinPhaseActivated(chainTime) + if !isBerlinPhase && statesBit&as.AddressStateBerlinPhaseBits != 0 || + isBerlinPhase && tx.State == as.AddressStateBitConsortium { // Berlin phase moved consortium handling to admin proposals return errAddrStateNotPermitted } diff --git a/vms/platformvm/txs/executor/camino_tx_executor_test.go b/vms/platformvm/txs/executor/camino_tx_executor_test.go index f9d1e079302d..3178784ec32b 100644 --- a/vms/platformvm/txs/executor/camino_tx_executor_test.go +++ b/vms/platformvm/txs/executor/camino_tx_executor_test.go @@ -1659,7 +1659,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { targetAddress: bob, txFlag: as.AddressStateBitRoleKYC, existingState: as.AddressStateRoleKYC, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, remove: false, }, // Bob has KYC role, and he is trying to give himself Admin role @@ -1668,7 +1668,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { targetAddress: bob, txFlag: as.AddressStateBitRoleAdmin, existingState: as.AddressStateRoleKYC, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, remove: false, }, // Bob has Admin role, and he is trying to give Alice Admin role @@ -1714,7 +1714,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { txFlag: as.AddressStateBitRoleAdmin, existingState: as.AddressStateRoleAdmin, expectedState: 0, - expectedErrs: []error{errAdminCannotBeDeleted, errAdminCannotBeDeleted}, + expectedErrs: []error{errAdminCannotBeDeleted, errAdminCannotBeDeleted, errAdminCannotBeDeleted}, remove: true, }, // Bob has Admin role, and he is trying to give Alice the KYC Verified state @@ -1743,6 +1743,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { existingState: as.AddressStateRoleAdmin, expectedState: as.AddressStateConsortiumMember, remove: false, + expectedErrs: []error{nil, nil, errAddrStateNotPermitted}, }, // Bob has KYC role, and he is trying to give Alice KYC Expired state "State: KYC, Flag: KYC Expired, Add, Different Address": { @@ -1768,7 +1769,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { targetAddress: alice, txFlag: as.AddressStateBitRoleAdmin, existingState: as.AddressStateRoleAdmin, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, remove: false, }, // An Empty Address has Admin role, and he is trying to give Alice Admin role @@ -1777,7 +1778,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { targetAddress: alice, txFlag: as.AddressStateBitRoleAdmin, existingState: as.AddressStateRoleAdmin, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, remove: false, }, // Bob has Admin role, and he is trying to give Admin role to an Empty Address @@ -1786,7 +1787,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { targetAddress: ids.ShortEmpty, txFlag: as.AddressStateBitRoleAdmin, existingState: as.AddressStateRoleAdmin, - expectedErrs: []error{txs.ErrEmptyAddress, txs.ErrEmptyAddress}, + expectedErrs: []error{txs.ErrEmptyAddress, txs.ErrEmptyAddress, txs.ErrEmptyAddress}, remove: false, }, // Bob has empty addr state, and he is trying to give Alice Admin role @@ -1796,7 +1797,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { txFlag: as.AddressStateBitRoleAdmin, existingState: as.AddressStateEmpty, remove: false, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, }, // Bob has empty addr state, and he is trying to remove Admin role from Alice "State: none, Flag: Admin role, Remove, Different Address": { @@ -1805,7 +1806,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { txFlag: as.AddressStateBitRoleAdmin, existingState: as.AddressStateEmpty, remove: true, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, }, // Bob has empty addr state, and he is trying to give Alice KYC role "State: none, Flag: KYC role, Add, Different Address": { @@ -1814,7 +1815,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { txFlag: as.AddressStateBitRoleKYC, existingState: as.AddressStateEmpty, remove: false, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, }, // Bob has empty addr state, and he is trying to remove KYC role from Alice "State: none, Flag: KYC role, Remove, Different Address": { @@ -1823,7 +1824,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { txFlag: as.AddressStateBitRoleKYC, existingState: as.AddressStateEmpty, remove: true, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, }, // Bob has empty addr state, and he is trying to give Alice KYC Verified state "State: none, Flag: KYC Verified, Add, Different Address": { @@ -1832,7 +1833,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { txFlag: as.AddressStateBitKYCVerified, existingState: as.AddressStateEmpty, remove: false, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, }, // Bob has empty addr state, and he is trying to remove KYC Verified state from Alice "State: none, Flag: KYC Verified, Remove, Different Address": { @@ -1841,7 +1842,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { txFlag: as.AddressStateBitKYCVerified, existingState: as.AddressStateEmpty, remove: true, - expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted}, + expectedErrs: []error{errAddrStateNotPermitted, errAddrStateNotPermitted, errAddrStateNotPermitted}, }, // Bob has KYC role, and he is trying to give Alice KYC Expired state "Upgrade: 1, State: KYC, Flag: KYC Expired, Add, Different Address": { @@ -1864,7 +1865,7 @@ func TestAddAddressStateTxExecutor(t *testing.T) { txFlag: as.AddressStateBitKYCExpired, existingState: as.AddressStateRoleKYC, expectedState: as.AddressStateKYCExpired, - expectedErrs: []error{errNotAthensPhase, errSignatureMissing}, + expectedErrs: []error{errNotAthensPhase, errSignatureMissing, errSignatureMissing}, remove: false, executor: alice, executorAuth: &secp256k1fx.Input{SigIndices: []uint32{0}}, @@ -1882,15 +1883,30 @@ func TestAddAddressStateTxExecutor(t *testing.T) { }, }} - athensPhaseTimes := []time.Time{ - env.state.GetTimestamp().Add(24 * time.Hour), // AthensPhase not yet active (> chainTime) - env.state.GetTimestamp(), // AthensPhase active (<= chainTime) + chainTime := env.state.GetTimestamp() + + fnSetPhaseTimes := []func() string{ + func() string { + env.config.AthensPhaseTime = chainTime.Add(1 * time.Second) // not yet active + env.config.BerlinPhaseTime = chainTime.Add(2 * time.Second) // not yet active + return "Sunrise" + }, + func() string { + env.config.AthensPhaseTime = chainTime // active + env.config.BerlinPhaseTime = chainTime.Add(1 * time.Second) // not yet active + return "Athens" + }, + func() string { + env.config.AthensPhaseTime = chainTime.Add(-1 * time.Second) // active + env.config.BerlinPhaseTime = chainTime // active + return "Berlin" + }, } - for phase := 0; phase < 2; phase++ { - env.config.AthensPhaseTime = athensPhaseTimes[phase] + for phase := 0; phase < 3; phase++ { + phaseName := fnSetPhaseTimes[phase]() for name, tt := range tests { - t.Run(fmt.Sprintf("Phase %d; %s", phase, name), func(t *testing.T) { + t.Run(fmt.Sprintf("%s; %s", phaseName, name), func(t *testing.T) { addressStateTx := &txs.AddressStateTx{ UpgradeVersionID: codec.BuildUpgradeVersionID(tt.UpgradeVersion), BaseTx: baseTx,