From dfb74b946d11a0322b4642c21fd5143ca15f0d3a Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 6 Dec 2023 11:54:57 +0100 Subject: [PATCH 01/14] introduced stakers cold attributes --- .../block/executor/proposal_block_test.go | 1 + vms/platformvm/state/diff.go | 25 ++++++++ vms/platformvm/state/mock_state.go | 45 ++++++++++++++ vms/platformvm/state/staker.go | 22 +++++++ vms/platformvm/state/state.go | 27 ++++++++ .../txs/executor/proposal_tx_executor.go | 61 ++++++++----------- 6 files changed, 146 insertions(+), 35 deletions(-) diff --git a/vms/platformvm/block/executor/proposal_block_test.go b/vms/platformvm/block/executor/proposal_block_test.go index 77c36c08dec3..addf807e3696 100644 --- a/vms/platformvm/block/executor/proposal_block_test.go +++ b/vms/platformvm/block/executor/proposal_block_test.go @@ -96,6 +96,7 @@ func TestApricotProposalBlockTimeVerification(t *testing.T) { StartTime: utx.StartTime(), NextTime: chainTime, EndTime: chainTime, + Priority: utx.CurrentPriority(), }).Times(2) currentStakersIt.EXPECT().Release() onParentAccept.EXPECT().GetCurrentStakerIterator().Return(currentStakersIt, nil) diff --git a/vms/platformvm/state/diff.go b/vms/platformvm/state/diff.go index d509fa69e0dd..05a758371335 100644 --- a/vms/platformvm/state/diff.go +++ b/vms/platformvm/state/diff.go @@ -194,6 +194,31 @@ func (d *diff) GetCurrentStakerIterator() (StakerIterator, error) { return d.currentStakerDiffs.GetStakerIterator(parentIterator), nil } +func (d *diff) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) { + stakerTx, _, err := d.GetTx(stakerID) + if err != nil { + return nil, fmt.Errorf("failed to get next staker %s: %w", stakerID, err) + } + switch uStakerTx := stakerTx.Unsigned.(type) { + case txs.ValidatorTx: + return &StakerColdAttributes{ + Stake: uStakerTx.Stake(), + Outputs: uStakerTx.Outputs(), + Shares: uStakerTx.Shares(), + ValidationRewardsOwner: uStakerTx.ValidationRewardsOwner(), + DelegationRewardsOwner: uStakerTx.DelegationRewardsOwner(), + }, nil + case txs.DelegatorTx: + return &StakerColdAttributes{ + Stake: uStakerTx.Stake(), + Outputs: uStakerTx.Outputs(), + RewardsOwner: uStakerTx.RewardsOwner(), + }, nil + default: + return nil, fmt.Errorf("unexpected stakerTx type %T", uStakerTx) + } +} + func (d *diff) GetPendingValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error) { // If the validator was modified in this diff, return the modified // validator. diff --git a/vms/platformvm/state/mock_state.go b/vms/platformvm/state/mock_state.go index 8a3aac7d81f1..beeb99e388f0 100644 --- a/vms/platformvm/state/mock_state.go +++ b/vms/platformvm/state/mock_state.go @@ -300,6 +300,21 @@ func (mr *MockChainMockRecorder) GetPendingValidator(arg0, arg1 interface{}) *go return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingValidator", reflect.TypeOf((*MockChain)(nil).GetPendingValidator), arg0, arg1) } +// GetStakerColdAttributes mocks base method. +func (m *MockChain) GetStakerColdAttributes(arg0 ids.ID) (*StakerColdAttributes, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetStakerColdAttributes", arg0) + ret0, _ := ret[0].(*StakerColdAttributes) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetStakerColdAttributes indicates an expected call of GetStakerColdAttributes. +func (mr *MockChainMockRecorder) GetStakerColdAttributes(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerColdAttributes", reflect.TypeOf((*MockChain)(nil).GetStakerColdAttributes), arg0) +} + // GetSubnetOwner mocks base method. func (m *MockChain) GetSubnetOwner(arg0 ids.ID) (fx.Owner, error) { m.ctrl.T.Helper() @@ -762,6 +777,21 @@ func (mr *MockDiffMockRecorder) GetPendingValidator(arg0, arg1 interface{}) *gom return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingValidator", reflect.TypeOf((*MockDiff)(nil).GetPendingValidator), arg0, arg1) } +// GetStakerColdAttributes mocks base method. +func (m *MockDiff) GetStakerColdAttributes(arg0 ids.ID) (*StakerColdAttributes, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetStakerColdAttributes", arg0) + ret0, _ := ret[0].(*StakerColdAttributes) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetStakerColdAttributes indicates an expected call of GetStakerColdAttributes. +func (mr *MockDiffMockRecorder) GetStakerColdAttributes(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerColdAttributes", reflect.TypeOf((*MockDiff)(nil).GetStakerColdAttributes), arg0) +} + // GetSubnetOwner mocks base method. func (m *MockDiff) GetSubnetOwner(arg0 ids.ID) (fx.Owner, error) { m.ctrl.T.Helper() @@ -1378,6 +1408,21 @@ func (mr *MockStateMockRecorder) GetRewardUTXOs(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRewardUTXOs", reflect.TypeOf((*MockState)(nil).GetRewardUTXOs), arg0) } +// GetStakerColdAttributes mocks base method. +func (m *MockState) GetStakerColdAttributes(arg0 ids.ID) (*StakerColdAttributes, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetStakerColdAttributes", arg0) + ret0, _ := ret[0].(*StakerColdAttributes) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetStakerColdAttributes indicates an expected call of GetStakerColdAttributes. +func (mr *MockStateMockRecorder) GetStakerColdAttributes(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerColdAttributes", reflect.TypeOf((*MockState)(nil).GetStakerColdAttributes), arg0) +} + // GetStartTime mocks base method. func (m *MockState) GetStartTime(arg0 ids.NodeID, arg1 ids.ID) (time.Time, error) { m.ctrl.T.Helper() diff --git a/vms/platformvm/state/staker.go b/vms/platformvm/state/staker.go index 37bc512e36cb..9ce952e9a705 100644 --- a/vms/platformvm/state/staker.go +++ b/vms/platformvm/state/staker.go @@ -11,6 +11,8 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/fx" "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) @@ -121,3 +123,23 @@ func NewPendingStaker(txID ids.ID, staker txs.Staker) (*Staker, error) { Priority: staker.PendingPriority(), }, nil } + +// While Staker object contains a staker's hot attributes, likely to be used pretty often +// StakerColdAttributes contains a staker's cold attributes, rarely used, mostly when rewarding it. +// Note that both Staker and StakerAttribute content comes from the stakerTx creating the staker. +// In state.State we do have StakerMetadata information as well, which contains data about the stakers +// that are generated during staker's activity (mostly uptimes) +// TODO: consider moving delegatees reward here, out of StakersMetadata. +type StakerColdAttributes struct { + // common attributes + Stake []*avax.TransferableOutput + Outputs []*avax.TransferableOutput + + // validators specific attributes + Shares uint32 + ValidationRewardsOwner fx.Owner + DelegationRewardsOwner fx.Owner + + // delegators specific attributes + RewardsOwner fx.Owner +} diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 82ff0107762a..dc9952b92fd8 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -118,6 +118,8 @@ type Chain interface { AddChain(createChainTx *txs.Tx) + GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) + GetTx(txID ids.ID) (*txs.Tx, status.Status, error) AddTx(tx *txs.Tx, status status.Status) } @@ -733,6 +735,31 @@ func (s *state) GetCurrentStakerIterator() (StakerIterator, error) { return s.currentStakers.GetStakerIterator(), nil } +func (s *state) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) { + stakerTx, _, err := s.GetTx(stakerID) + if err != nil { + return nil, fmt.Errorf("failed to get next staker %s: %w", stakerID, err) + } + switch uStakerTx := stakerTx.Unsigned.(type) { + case txs.ValidatorTx: + return &StakerColdAttributes{ + Stake: uStakerTx.Stake(), + Outputs: uStakerTx.Outputs(), + Shares: uStakerTx.Shares(), + ValidationRewardsOwner: uStakerTx.ValidationRewardsOwner(), + DelegationRewardsOwner: uStakerTx.DelegationRewardsOwner(), + }, nil + case txs.DelegatorTx: + return &StakerColdAttributes{ + Stake: uStakerTx.Stake(), + Outputs: uStakerTx.Outputs(), + RewardsOwner: uStakerTx.RewardsOwner(), + }, nil + default: + return nil, fmt.Errorf("unexpected stakerTx type %T", uStakerTx) + } +} + func (s *state) GetPendingValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error) { return s.pendingStakers.GetValidator(subnetID, nodeID) } diff --git a/vms/platformvm/txs/executor/proposal_tx_executor.go b/vms/platformvm/txs/executor/proposal_tx_executor.go index bd329b3f2576..8c96abbf4661 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor.go @@ -363,24 +363,28 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error return err } - stakerTx, _, err := e.OnCommitState.GetTx(stakerToReward.TxID) + stakerAttributes, err := e.OnCommitState.GetStakerColdAttributes(stakerToReward.TxID) if err != nil { - return fmt.Errorf("failed to get next removed staker tx: %w", err) + return fmt.Errorf("failed to get attributes for staker %d: %w", stakerToReward.TxID, err) } - // Invariant: A [txs.DelegatorTx] does not also implement the - // [txs.ValidatorTx] interface. - switch uStakerTx := stakerTx.Unsigned.(type) { - case txs.ValidatorTx: - if err := e.rewardValidatorTx(uStakerTx, stakerToReward); err != nil { + switch { + case stakerToReward.Priority.IsPermissionedValidator(): + // Invariant: Permissioned stakers are removed by the advancement of + // time and the current chain timestamp is == this staker's + // EndTime. This means only permissionless stakers should be + // left in the staker set. + return ErrShouldBePermissionlessStaker + case stakerToReward.Priority.IsCurrentValidator(): + if err := e.rewardValidatorTx(stakerToReward, stakerAttributes); err != nil { return err } // Handle staker lifecycle. e.OnCommitState.DeleteCurrentValidator(stakerToReward) e.OnAbortState.DeleteCurrentValidator(stakerToReward) - case txs.DelegatorTx: - if err := e.rewardDelegatorTx(uStakerTx, stakerToReward); err != nil { + case stakerToReward.Priority.IsCurrentDelegator(): + if err := e.rewardDelegatorTx(stakerToReward, stakerAttributes); err != nil { return err } @@ -388,11 +392,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error e.OnCommitState.DeleteCurrentDelegator(stakerToReward) e.OnAbortState.DeleteCurrentDelegator(stakerToReward) default: - // Invariant: Permissioned stakers are removed by the advancement of - // time and the current chain timestamp is == this staker's - // EndTime. This means only permissionless stakers should be - // left in the staker set. - return ErrShouldBePermissionlessStaker + return errors.New("unexpected staker type") } // If the reward is aborted, then the current supply should be decreased. @@ -411,11 +411,11 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error return err } -func (e *ProposalTxExecutor) rewardValidatorTx(uValidatorTx txs.ValidatorTx, validator *state.Staker) error { +func (e *ProposalTxExecutor) rewardValidatorTx(validator *state.Staker, valAttributes *state.StakerColdAttributes) error { var ( txID = validator.TxID - stake = uValidatorTx.Stake() - outputs = uValidatorTx.Outputs() + stake = valAttributes.Stake + outputs = valAttributes.Outputs // Invariant: The staked asset must be equal to the reward asset. stakeAsset = stake[0].Asset ) @@ -440,7 +440,7 @@ func (e *ProposalTxExecutor) rewardValidatorTx(uValidatorTx txs.ValidatorTx, val // Provide the reward here reward := validator.PotentialReward if reward > 0 { - validationRewardsOwner := uValidatorTx.ValidationRewardsOwner() + validationRewardsOwner := valAttributes.ValidationRewardsOwner outIntf, err := e.Fx.CreateOutput(reward, validationRewardsOwner) if err != nil { return fmt.Errorf("failed to create output: %w", err) @@ -477,7 +477,7 @@ func (e *ProposalTxExecutor) rewardValidatorTx(uValidatorTx txs.ValidatorTx, val return nil } - delegationRewardsOwner := uValidatorTx.DelegationRewardsOwner() + delegationRewardsOwner := valAttributes.DelegationRewardsOwner outIntf, err := e.Fx.CreateOutput(delegateeReward, delegationRewardsOwner) if err != nil { return fmt.Errorf("failed to create output: %w", err) @@ -513,11 +513,11 @@ func (e *ProposalTxExecutor) rewardValidatorTx(uValidatorTx txs.ValidatorTx, val return nil } -func (e *ProposalTxExecutor) rewardDelegatorTx(uDelegatorTx txs.DelegatorTx, delegator *state.Staker) error { +func (e *ProposalTxExecutor) rewardDelegatorTx(delegator *state.Staker, delAttributes *state.StakerColdAttributes) error { var ( txID = delegator.TxID - stake = uDelegatorTx.Stake() - outputs = uDelegatorTx.Outputs() + stake = delAttributes.Stake + outputs = delAttributes.Outputs // Invariant: The staked asset must be equal to the reward asset. stakeAsset = stake[0].Asset ) @@ -544,29 +544,20 @@ func (e *ProposalTxExecutor) rewardDelegatorTx(uDelegatorTx txs.DelegatorTx, del return fmt.Errorf("failed to get whether %s is a validator: %w", delegator.NodeID, err) } - vdrTxIntf, _, err := e.OnCommitState.GetTx(validator.TxID) + valAttributes, err := e.OnCommitState.GetStakerColdAttributes(validator.TxID) if err != nil { return fmt.Errorf("failed to get whether %s is a validator: %w", delegator.NodeID, err) } - // Invariant: Delegators must only be able to reference validator - // transactions that implement [txs.ValidatorTx]. All - // validator transactions implement this interface except the - // AddSubnetValidatorTx. - vdrTx, ok := vdrTxIntf.Unsigned.(txs.ValidatorTx) - if !ok { - return ErrWrongTxType - } - // Calculate split of reward between delegator/delegatee - delegateeReward, delegatorReward := reward.Split(delegator.PotentialReward, vdrTx.Shares()) + delegateeReward, delegatorReward := reward.Split(delegator.PotentialReward, valAttributes.Shares) utxosOffset := 0 // Reward the delegator here reward := delegatorReward if reward > 0 { - rewardsOwner := uDelegatorTx.RewardsOwner() + rewardsOwner := delAttributes.RewardsOwner outIntf, err := e.Fx.CreateOutput(reward, rewardsOwner) if err != nil { return fmt.Errorf("failed to create output: %w", err) @@ -622,7 +613,7 @@ func (e *ProposalTxExecutor) rewardDelegatorTx(uDelegatorTx txs.DelegatorTx, del } else { // For any validators who started prior to [CortinaTime], we issue the // [delegateeReward] immediately. - delegationRewardsOwner := vdrTx.DelegationRewardsOwner() + delegationRewardsOwner := valAttributes.DelegationRewardsOwner outIntf, err := e.Fx.CreateOutput(delegateeReward, delegationRewardsOwner) if err != nil { return fmt.Errorf("failed to create output: %w", err) From a1fa20da1bdde118bf848d00ba4c11385fc1e05a Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 6 Dec 2023 12:27:39 +0100 Subject: [PATCH 02/14] some more consolidation --- vms/platformvm/service.go | 56 ++++++---------------------------- vms/platformvm/service_test.go | 2 +- vms/platformvm/state/diff.go | 9 ++++++ vms/platformvm/state/staker.go | 2 ++ vms/platformvm/state/state.go | 9 ++++++ vms/platformvm/vm.go | 2 +- 6 files changed, 32 insertions(+), 48 deletions(-) diff --git a/vms/platformvm/service.go b/vms/platformvm/service.go index fe9fa66f7b4c..fdb015cb43dc 100644 --- a/vms/platformvm/service.go +++ b/vms/platformvm/service.go @@ -32,9 +32,7 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/keystore" - "github.com/ava-labs/avalanchego/vms/platformvm/fx" "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/stakeable" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/status" @@ -86,16 +84,7 @@ var ( type Service struct { vm *VM addrManager avax.AddressManager - stakerAttributesCache *cache.LRU[ids.ID, *stakerAttributes] -} - -// All attributes are optional and may not be filled for each stakerTx. -type stakerAttributes struct { - shares uint32 - rewardsOwner fx.Owner - validationRewardsOwner fx.Owner - delegationRewardsOwner fx.Owner - proofOfPossession *signer.ProofOfPossession + stakerAttributesCache *cache.LRU[ids.ID, *state.StakerColdAttributes] } // GetHeight returns the height of the last accepted block @@ -726,7 +715,7 @@ type GetCurrentValidatorsReply struct { Validators []interface{} `json:"validators"` } -func (s *Service) loadStakerTxAttributes(txID ids.ID) (*stakerAttributes, error) { +func (s *Service) loadStakerTxAttributes(txID ids.ID) (*state.StakerColdAttributes, error) { // Lookup tx from the cache first. attr, found := s.stakerAttributesCache.Get(txID) if found { @@ -734,36 +723,11 @@ func (s *Service) loadStakerTxAttributes(txID ids.ID) (*stakerAttributes, error) } // Tx not available in cache; pull it from disk and populate the cache. - tx, _, err := s.vm.state.GetTx(txID) + attr, err := s.vm.state.GetStakerColdAttributes(txID) if err != nil { return nil, err } - switch stakerTx := tx.Unsigned.(type) { - case txs.ValidatorTx: - var pop *signer.ProofOfPossession - if staker, ok := stakerTx.(*txs.AddPermissionlessValidatorTx); ok { - if s, ok := staker.Signer.(*signer.ProofOfPossession); ok { - pop = s - } - } - - attr = &stakerAttributes{ - shares: stakerTx.Shares(), - validationRewardsOwner: stakerTx.ValidationRewardsOwner(), - delegationRewardsOwner: stakerTx.DelegationRewardsOwner(), - proofOfPossession: pop, - } - - case txs.DelegatorTx: - attr = &stakerAttributes{ - rewardsOwner: stakerTx.RewardsOwner(), - } - - default: - return nil, fmt.Errorf("unexpected staker tx type %T", tx.Unsigned) - } - s.stakerAttributesCache.Put(txID, attr) return attr, nil } @@ -856,7 +820,7 @@ func (s *Service) GetCurrentValidators(_ *http.Request, args *GetCurrentValidato return err } - shares := attr.shares + shares := attr.Shares delegationFee := json.Float32(100 * float32(shares) / float32(reward.PercentDenominator)) uptime, err := s.getAPIUptime(currentStaker) @@ -869,14 +833,14 @@ func (s *Service) GetCurrentValidators(_ *http.Request, args *GetCurrentValidato validationRewardOwner *platformapi.Owner delegationRewardOwner *platformapi.Owner ) - validationOwner, ok := attr.validationRewardsOwner.(*secp256k1fx.OutputOwners) + validationOwner, ok := attr.ValidationRewardsOwner.(*secp256k1fx.OutputOwners) if ok { validationRewardOwner, err = s.getAPIOwner(validationOwner) if err != nil { return err } } - delegationOwner, ok := attr.delegationRewardsOwner.(*secp256k1fx.OutputOwners) + delegationOwner, ok := attr.DelegationRewardsOwner.(*secp256k1fx.OutputOwners) if ok { delegationRewardOwner, err = s.getAPIOwner(delegationOwner) if err != nil { @@ -894,7 +858,7 @@ func (s *Service) GetCurrentValidators(_ *http.Request, args *GetCurrentValidato ValidationRewardOwner: validationRewardOwner, DelegationRewardOwner: delegationRewardOwner, DelegationFee: delegationFee, - Signer: attr.proofOfPossession, + Signer: attr.ProofOfPossession, } reply.Validators = append(reply.Validators, vdr) @@ -907,7 +871,7 @@ func (s *Service) GetCurrentValidators(_ *http.Request, args *GetCurrentValidato if err != nil { return err } - owner, ok := attr.rewardsOwner.(*secp256k1fx.OutputOwners) + owner, ok := attr.RewardsOwner.(*secp256k1fx.OutputOwners) if ok { rewardOwner, err = s.getAPIOwner(owner) if err != nil { @@ -1064,7 +1028,7 @@ func (s *Service) GetPendingValidators(_ *http.Request, args *GetPendingValidato return err } - shares := attr.shares + shares := attr.Shares delegationFee := json.Float32(100 * float32(shares) / float32(reward.PercentDenominator)) connected := s.vm.uptimeManager.IsConnected(nodeID, args.SubnetID) @@ -1072,7 +1036,7 @@ func (s *Service) GetPendingValidators(_ *http.Request, args *GetPendingValidato Staker: apiStaker, DelegationFee: delegationFee, Connected: connected, - Signer: attr.proofOfPossession, + Signer: attr.ProofOfPossession, } reply.Validators = append(reply.Validators, vdr) diff --git a/vms/platformvm/service_test.go b/vms/platformvm/service_test.go index 8e2cc3790fc3..96eda95ff09d 100644 --- a/vms/platformvm/service_test.go +++ b/vms/platformvm/service_test.go @@ -83,7 +83,7 @@ func defaultService(t *testing.T) (*Service, *mutableSharedMemory) { return &Service{ vm: vm, addrManager: avax.NewAddressManager(vm.ctx), - stakerAttributesCache: &cache.LRU[ids.ID, *stakerAttributes]{ + stakerAttributesCache: &cache.LRU[ids.ID, *state.StakerColdAttributes]{ Size: stakerAttributesCacheSize, }, }, mutableSharedMemory diff --git a/vms/platformvm/state/diff.go b/vms/platformvm/state/diff.go index 05a758371335..bf36113f6ed8 100644 --- a/vms/platformvm/state/diff.go +++ b/vms/platformvm/state/diff.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/fx" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) @@ -201,12 +202,20 @@ func (d *diff) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, } switch uStakerTx := stakerTx.Unsigned.(type) { case txs.ValidatorTx: + var pop *signer.ProofOfPossession + if staker, ok := uStakerTx.(*txs.AddPermissionlessValidatorTx); ok { + if s, ok := staker.Signer.(*signer.ProofOfPossession); ok { + pop = s + } + } + return &StakerColdAttributes{ Stake: uStakerTx.Stake(), Outputs: uStakerTx.Outputs(), Shares: uStakerTx.Shares(), ValidationRewardsOwner: uStakerTx.ValidationRewardsOwner(), DelegationRewardsOwner: uStakerTx.DelegationRewardsOwner(), + ProofOfPossession: pop, }, nil case txs.DelegatorTx: return &StakerColdAttributes{ diff --git a/vms/platformvm/state/staker.go b/vms/platformvm/state/staker.go index 9ce952e9a705..6273fcc89e32 100644 --- a/vms/platformvm/state/staker.go +++ b/vms/platformvm/state/staker.go @@ -13,6 +13,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/fx" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) @@ -139,6 +140,7 @@ type StakerColdAttributes struct { Shares uint32 ValidationRewardsOwner fx.Owner DelegationRewardsOwner fx.Owner + ProofOfPossession *signer.ProofOfPossession // delegators specific attributes RewardsOwner fx.Owner diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index dc9952b92fd8..7de41c9fa778 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -42,6 +42,7 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/genesis" "github.com/ava-labs/avalanchego/vms/platformvm/metrics" "github.com/ava-labs/avalanchego/vms/platformvm/reward" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/platformvm/txs" @@ -742,12 +743,20 @@ func (s *state) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, } switch uStakerTx := stakerTx.Unsigned.(type) { case txs.ValidatorTx: + var pop *signer.ProofOfPossession + if staker, ok := uStakerTx.(*txs.AddPermissionlessValidatorTx); ok { + if s, ok := staker.Signer.(*signer.ProofOfPossession); ok { + pop = s + } + } + return &StakerColdAttributes{ Stake: uStakerTx.Stake(), Outputs: uStakerTx.Outputs(), Shares: uStakerTx.Shares(), ValidationRewardsOwner: uStakerTx.ValidationRewardsOwner(), DelegationRewardsOwner: uStakerTx.DelegationRewardsOwner(), + ProofOfPossession: pop, }, nil case txs.DelegatorTx: return &StakerColdAttributes{ diff --git a/vms/platformvm/vm.go b/vms/platformvm/vm.go index d9898b873137..da66ddb06b15 100644 --- a/vms/platformvm/vm.go +++ b/vms/platformvm/vm.go @@ -420,7 +420,7 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { service := &Service{ vm: vm, addrManager: avax.NewAddressManager(vm.ctx), - stakerAttributesCache: &cache.LRU[ids.ID, *stakerAttributes]{ + stakerAttributesCache: &cache.LRU[ids.ID, *state.StakerColdAttributes]{ Size: stakerAttributesCacheSize, }, } From e88b5b0aa34e1c666b38074d93199b785906cf7e Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 6 Dec 2023 13:02:02 +0100 Subject: [PATCH 03/14] some more consolidation --- vms/platformvm/service.go | 20 +++---------- vms/platformvm/state/diff.go | 16 ++++++++++ vms/platformvm/state/mock_state.go | 45 ++++++++++++++++++++++++++++ vms/platformvm/state/state.go | 17 +++++++++++ vms/platformvm/validators/manager.go | 19 ++---------- 5 files changed, 84 insertions(+), 33 deletions(-) diff --git a/vms/platformvm/service.go b/vms/platformvm/service.go index fdb015cb43dc..2a9edb381c42 100644 --- a/vms/platformvm/service.go +++ b/vms/platformvm/service.go @@ -1921,17 +1921,12 @@ func (s *Service) GetBlockchainStatus(r *http.Request, args *GetBlockchainStatus } func (s *Service) nodeValidates(blockchainID ids.ID) bool { - chainTx, _, err := s.vm.state.GetTx(blockchainID) + subnetID, err := s.vm.state.GetChainSubnet(blockchainID) if err != nil { return false } - chain, ok := chainTx.Unsigned.(*txs.CreateChainTx) - if !ok { - return false - } - - _, isValidator := s.vm.Validators.GetValidator(chain.SubnetID, s.vm.ctx.NodeID) + _, isValidator := s.vm.Validators.GetValidator(subnetID, s.vm.ctx.NodeID) return isValidator } @@ -1948,15 +1943,8 @@ func (s *Service) chainExists(ctx context.Context, blockID ids.ID, chainID ids.I } } - tx, _, err := state.GetTx(chainID) - if err == database.ErrNotFound { - return false, nil - } - if err != nil { - return false, err - } - _, ok = tx.Unsigned.(*txs.CreateChainTx) - return ok, nil + _, err := state.GetChainSubnet(chainID) + return err == nil, err } // ValidatedByArgs is the arguments for calling ValidatedBy diff --git a/vms/platformvm/state/diff.go b/vms/platformvm/state/diff.go index bf36113f6ed8..fcf35e8513f2 100644 --- a/vms/platformvm/state/diff.go +++ b/vms/platformvm/state/diff.go @@ -349,6 +349,22 @@ func (d *diff) AddChain(createChainTx *txs.Tx) { } } +func (d *diff) GetChainSubnet(chainID ids.ID) (ids.ID, error) { + chainTx, _, err := d.GetTx(chainID) + if err != nil { + return ids.Empty, fmt.Errorf( + "problem retrieving blockchain %q: %w", + chainID, + err, + ) + } + chain, ok := chainTx.Unsigned.(*txs.CreateChainTx) + if !ok { + return ids.Empty, fmt.Errorf("%q is not a blockchain", chainID) + } + return chain.SubnetID, nil +} + func (d *diff) GetTx(txID ids.ID) (*txs.Tx, status.Status, error) { if tx, exists := d.addedTxs[txID]; exists { return tx.tx, tx.status, nil diff --git a/vms/platformvm/state/mock_state.go b/vms/platformvm/state/mock_state.go index beeb99e388f0..dceff53e3f5d 100644 --- a/vms/platformvm/state/mock_state.go +++ b/vms/platformvm/state/mock_state.go @@ -180,6 +180,21 @@ func (mr *MockChainMockRecorder) DeleteUTXO(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUTXO", reflect.TypeOf((*MockChain)(nil).DeleteUTXO), arg0) } +// GetChainSubnet mocks base method. +func (m *MockChain) GetChainSubnet(arg0 ids.ID) (ids.ID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetChainSubnet", arg0) + ret0, _ := ret[0].(ids.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetChainSubnet indicates an expected call of GetChainSubnet. +func (mr *MockChainMockRecorder) GetChainSubnet(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChainSubnet", reflect.TypeOf((*MockChain)(nil).GetChainSubnet), arg0) +} + // GetCurrentDelegatorIterator mocks base method. func (m *MockChain) GetCurrentDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { m.ctrl.T.Helper() @@ -657,6 +672,21 @@ func (mr *MockDiffMockRecorder) DeleteUTXO(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUTXO", reflect.TypeOf((*MockDiff)(nil).DeleteUTXO), arg0) } +// GetChainSubnet mocks base method. +func (m *MockDiff) GetChainSubnet(arg0 ids.ID) (ids.ID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetChainSubnet", arg0) + ret0, _ := ret[0].(ids.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetChainSubnet indicates an expected call of GetChainSubnet. +func (mr *MockDiffMockRecorder) GetChainSubnet(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChainSubnet", reflect.TypeOf((*MockDiff)(nil).GetChainSubnet), arg0) +} + // GetCurrentDelegatorIterator mocks base method. func (m *MockDiff) GetCurrentDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { m.ctrl.T.Helper() @@ -1244,6 +1274,21 @@ func (mr *MockStateMockRecorder) GetBlockIDAtHeight(arg0 interface{}) *gomock.Ca return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockIDAtHeight", reflect.TypeOf((*MockState)(nil).GetBlockIDAtHeight), arg0) } +// GetChainSubnet mocks base method. +func (m *MockState) GetChainSubnet(arg0 ids.ID) (ids.ID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetChainSubnet", arg0) + ret0, _ := ret[0].(ids.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetChainSubnet indicates an expected call of GetChainSubnet. +func (mr *MockStateMockRecorder) GetChainSubnet(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChainSubnet", reflect.TypeOf((*MockState)(nil).GetChainSubnet), arg0) +} + // GetChains mocks base method. func (m *MockState) GetChains(arg0 ids.ID) ([]*txs.Tx, error) { m.ctrl.T.Helper() diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 7de41c9fa778..13cccf385fec 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -118,6 +118,7 @@ type Chain interface { AddSubnetTransformation(transformSubnetTx *txs.Tx) AddChain(createChainTx *txs.Tx) + GetChainSubnet(chainID ids.ID) (ids.ID, error) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) @@ -995,6 +996,22 @@ func (s *state) AddChain(createChainTxIntf *txs.Tx) { } } +func (s *state) GetChainSubnet(chainID ids.ID) (ids.ID, error) { + chainTx, _, err := s.GetTx(chainID) + if err != nil { + return ids.Empty, fmt.Errorf( + "problem retrieving blockchain %q: %w", + chainID, + err, + ) + } + chain, ok := chainTx.Unsigned.(*txs.CreateChainTx) + if !ok { + return ids.Empty, fmt.Errorf("%q is not a blockchain", chainID) + } + return chain.SubnetID, nil +} + func (s *state) getChainDB(subnetID ids.ID) linkeddb.LinkedDB { if chainDB, cached := s.chainDBCache.Get(subnetID); cached { return chainDB diff --git a/vms/platformvm/validators/manager.go b/vms/platformvm/validators/manager.go index a4c5c87a3040..22c67f6da43c 100644 --- a/vms/platformvm/validators/manager.go +++ b/vms/platformvm/validators/manager.go @@ -5,7 +5,6 @@ package validators import ( "context" - "fmt" "time" "github.com/ava-labs/avalanchego/cache" @@ -19,8 +18,6 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/block" "github.com/ava-labs/avalanchego/vms/platformvm/config" "github.com/ava-labs/avalanchego/vms/platformvm/metrics" - "github.com/ava-labs/avalanchego/vms/platformvm/status" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) const ( @@ -43,7 +40,7 @@ type Manager interface { } type State interface { - GetTx(txID ids.ID) (*txs.Tx, status.Status, error) + GetChainSubnet(chainID ids.ID) (ids.ID, error) GetLastAccepted() ids.ID GetStatelessBlock(blockID ids.ID) (block.Block, error) @@ -353,19 +350,7 @@ func (m *manager) GetSubnetID(_ context.Context, chainID ids.ID) (ids.ID, error) return constants.PrimaryNetworkID, nil } - chainTx, _, err := m.state.GetTx(chainID) - if err != nil { - return ids.Empty, fmt.Errorf( - "problem retrieving blockchain %q: %w", - chainID, - err, - ) - } - chain, ok := chainTx.Unsigned.(*txs.CreateChainTx) - if !ok { - return ids.Empty, fmt.Errorf("%q is not a blockchain", chainID) - } - return chain.SubnetID, nil + return m.state.GetChainSubnet(chainID) } func (m *manager) OnAcceptedBlockID(blkID ids.ID) { From 146e4d2ca12dd11469c040d9514ccdc992921b7e Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 6 Dec 2023 13:23:46 +0100 Subject: [PATCH 04/14] removed code duplication --- vms/platformvm/state/diff.go | 46 +------------------- vms/platformvm/state/state.go | 46 +------------------- vms/platformvm/state/state_helpers.go | 61 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 88 deletions(-) create mode 100644 vms/platformvm/state/state_helpers.go diff --git a/vms/platformvm/state/diff.go b/vms/platformvm/state/diff.go index fcf35e8513f2..a515de360e1d 100644 --- a/vms/platformvm/state/diff.go +++ b/vms/platformvm/state/diff.go @@ -12,7 +12,6 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/fx" - "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) @@ -196,36 +195,7 @@ func (d *diff) GetCurrentStakerIterator() (StakerIterator, error) { } func (d *diff) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) { - stakerTx, _, err := d.GetTx(stakerID) - if err != nil { - return nil, fmt.Errorf("failed to get next staker %s: %w", stakerID, err) - } - switch uStakerTx := stakerTx.Unsigned.(type) { - case txs.ValidatorTx: - var pop *signer.ProofOfPossession - if staker, ok := uStakerTx.(*txs.AddPermissionlessValidatorTx); ok { - if s, ok := staker.Signer.(*signer.ProofOfPossession); ok { - pop = s - } - } - - return &StakerColdAttributes{ - Stake: uStakerTx.Stake(), - Outputs: uStakerTx.Outputs(), - Shares: uStakerTx.Shares(), - ValidationRewardsOwner: uStakerTx.ValidationRewardsOwner(), - DelegationRewardsOwner: uStakerTx.DelegationRewardsOwner(), - ProofOfPossession: pop, - }, nil - case txs.DelegatorTx: - return &StakerColdAttributes{ - Stake: uStakerTx.Stake(), - Outputs: uStakerTx.Outputs(), - RewardsOwner: uStakerTx.RewardsOwner(), - }, nil - default: - return nil, fmt.Errorf("unexpected stakerTx type %T", uStakerTx) - } + return getStakerColdAttributes(d, stakerID) } func (d *diff) GetPendingValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error) { @@ -350,19 +320,7 @@ func (d *diff) AddChain(createChainTx *txs.Tx) { } func (d *diff) GetChainSubnet(chainID ids.ID) (ids.ID, error) { - chainTx, _, err := d.GetTx(chainID) - if err != nil { - return ids.Empty, fmt.Errorf( - "problem retrieving blockchain %q: %w", - chainID, - err, - ) - } - chain, ok := chainTx.Unsigned.(*txs.CreateChainTx) - if !ok { - return ids.Empty, fmt.Errorf("%q is not a blockchain", chainID) - } - return chain.SubnetID, nil + return getChainSubnet(d, chainID) } func (d *diff) GetTx(txID ids.ID) (*txs.Tx, status.Status, error) { diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 13cccf385fec..1811d97c7cc5 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -42,7 +42,6 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/genesis" "github.com/ava-labs/avalanchego/vms/platformvm/metrics" "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/signer" "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/platformvm/txs" @@ -738,36 +737,7 @@ func (s *state) GetCurrentStakerIterator() (StakerIterator, error) { } func (s *state) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) { - stakerTx, _, err := s.GetTx(stakerID) - if err != nil { - return nil, fmt.Errorf("failed to get next staker %s: %w", stakerID, err) - } - switch uStakerTx := stakerTx.Unsigned.(type) { - case txs.ValidatorTx: - var pop *signer.ProofOfPossession - if staker, ok := uStakerTx.(*txs.AddPermissionlessValidatorTx); ok { - if s, ok := staker.Signer.(*signer.ProofOfPossession); ok { - pop = s - } - } - - return &StakerColdAttributes{ - Stake: uStakerTx.Stake(), - Outputs: uStakerTx.Outputs(), - Shares: uStakerTx.Shares(), - ValidationRewardsOwner: uStakerTx.ValidationRewardsOwner(), - DelegationRewardsOwner: uStakerTx.DelegationRewardsOwner(), - ProofOfPossession: pop, - }, nil - case txs.DelegatorTx: - return &StakerColdAttributes{ - Stake: uStakerTx.Stake(), - Outputs: uStakerTx.Outputs(), - RewardsOwner: uStakerTx.RewardsOwner(), - }, nil - default: - return nil, fmt.Errorf("unexpected stakerTx type %T", uStakerTx) - } + return getStakerColdAttributes(s, stakerID) } func (s *state) GetPendingValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error) { @@ -997,19 +967,7 @@ func (s *state) AddChain(createChainTxIntf *txs.Tx) { } func (s *state) GetChainSubnet(chainID ids.ID) (ids.ID, error) { - chainTx, _, err := s.GetTx(chainID) - if err != nil { - return ids.Empty, fmt.Errorf( - "problem retrieving blockchain %q: %w", - chainID, - err, - ) - } - chain, ok := chainTx.Unsigned.(*txs.CreateChainTx) - if !ok { - return ids.Empty, fmt.Errorf("%q is not a blockchain", chainID) - } - return chain.SubnetID, nil + return getChainSubnet(s, chainID) } func (s *state) getChainDB(subnetID ids.ID) linkeddb.LinkedDB { diff --git a/vms/platformvm/state/state_helpers.go b/vms/platformvm/state/state_helpers.go new file mode 100644 index 000000000000..ef7c108b28b5 --- /dev/null +++ b/vms/platformvm/state/state_helpers.go @@ -0,0 +1,61 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package state + +import ( + "fmt" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" +) + +func getStakerColdAttributes(chain Chain, stakerID ids.ID) (*StakerColdAttributes, error) { + stakerTx, _, err := chain.GetTx(stakerID) + if err != nil { + return nil, fmt.Errorf("failed to get next staker %s: %w", stakerID, err) + } + switch uStakerTx := stakerTx.Unsigned.(type) { + case txs.ValidatorTx: + var pop *signer.ProofOfPossession + if staker, ok := uStakerTx.(*txs.AddPermissionlessValidatorTx); ok { + if s, ok := staker.Signer.(*signer.ProofOfPossession); ok { + pop = s + } + } + + return &StakerColdAttributes{ + Stake: uStakerTx.Stake(), + Outputs: uStakerTx.Outputs(), + Shares: uStakerTx.Shares(), + ValidationRewardsOwner: uStakerTx.ValidationRewardsOwner(), + DelegationRewardsOwner: uStakerTx.DelegationRewardsOwner(), + ProofOfPossession: pop, + }, nil + case txs.DelegatorTx: + return &StakerColdAttributes{ + Stake: uStakerTx.Stake(), + Outputs: uStakerTx.Outputs(), + RewardsOwner: uStakerTx.RewardsOwner(), + }, nil + default: + return nil, fmt.Errorf("unexpected stakerTx type %T", uStakerTx) + } +} + +func getChainSubnet(chain Chain, chainID ids.ID) (ids.ID, error) { + chainTx, _, err := chain.GetTx(chainID) + if err != nil { + return ids.Empty, fmt.Errorf( + "problem retrieving blockchain %q: %w", + chainID, + err, + ) + } + blockChain, ok := chainTx.Unsigned.(*txs.CreateChainTx) + if !ok { + return ids.Empty, fmt.Errorf("%q is not a blockchain", chainID) + } + return blockChain.SubnetID, nil +} From 82759680de332a2ed3ffba2c52ce267e75402f02 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 13 Dec 2023 11:42:39 +0100 Subject: [PATCH 05/14] fix regression --- vms/platformvm/service.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/service.go b/vms/platformvm/service.go index 2a9edb381c42..5133d87f6434 100644 --- a/vms/platformvm/service.go +++ b/vms/platformvm/service.go @@ -1943,8 +1943,14 @@ func (s *Service) chainExists(ctx context.Context, blockID ids.ID, chainID ids.I } } - _, err := state.GetChainSubnet(chainID) - return err == nil, err + switch _, err := state.GetChainSubnet(chainID); { + case err == nil: + return true, nil + case errors.Is(err, database.ErrNotFound): + return false, nil + default: + return false, err + } } // ValidatedByArgs is the arguments for calling ValidatedBy From 54287cc1e13eedc5629a4a638d0e52cfb740fe7e Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 20 Dec 2023 13:24:37 +0100 Subject: [PATCH 06/14] adding UTs for getStakerColdAttributes --- vms/platformvm/state/state_helpers.go | 5 +- vms/platformvm/state/state_helpers_test.go | 231 +++++++++++++++++++++ 2 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 vms/platformvm/state/state_helpers_test.go diff --git a/vms/platformvm/state/state_helpers.go b/vms/platformvm/state/state_helpers.go index ef7c108b28b5..cca0a4f84d09 100644 --- a/vms/platformvm/state/state_helpers.go +++ b/vms/platformvm/state/state_helpers.go @@ -4,6 +4,7 @@ package state import ( + "errors" "fmt" "github.com/ava-labs/avalanchego/ids" @@ -11,6 +12,8 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) +var errUnexpectedStakerTx = errors.New("unexpected stakerTx type ") + func getStakerColdAttributes(chain Chain, stakerID ids.ID) (*StakerColdAttributes, error) { stakerTx, _, err := chain.GetTx(stakerID) if err != nil { @@ -40,7 +43,7 @@ func getStakerColdAttributes(chain Chain, stakerID ids.ID) (*StakerColdAttribute RewardsOwner: uStakerTx.RewardsOwner(), }, nil default: - return nil, fmt.Errorf("unexpected stakerTx type %T", uStakerTx) + return nil, fmt.Errorf("%w, txType %T", errUnexpectedStakerTx, uStakerTx) } } diff --git a/vms/platformvm/state/state_helpers_test.go b/vms/platformvm/state/state_helpers_test.go new file mode 100644 index 000000000000..509cf407326b --- /dev/null +++ b/vms/platformvm/state/state_helpers_test.go @@ -0,0 +1,231 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package state + +import ( + "testing" + + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/bls" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" + "github.com/ava-labs/avalanchego/vms/platformvm/stakeable" + "github.com/ava-labs/avalanchego/vms/platformvm/status" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +func TestGetStakerColdAttributes(t *testing.T) { + type test struct { + name string + chainF func(*gomock.Controller) Chain + expectedAttributes *StakerColdAttributes + expectedErr error + } + + var ( + stakerID = ids.GenerateTestID() + shares = uint32(2024) + avaxAssetID = ids.GenerateTestID() + addr = ids.GenerateTestShortID() + outputs = []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{ + addr, + }, + }, + }, + }, + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &stakeable.LockOut{ + Locktime: 87654321, + TransferableOut: &secp256k1fx.TransferOutput{ + Amt: 1, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 12345678, + Threshold: 0, + Addrs: []ids.ShortID{}, + }, + }, + }, + }, + } + stakeOutputs = []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: 2 * units.KiloAvax, + OutputOwners: secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{ + addr, + }, + }, + }, + }, + } + anOwner = &secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 1, + Addrs: []ids.ShortID{ + addr, + }, + } + anotherOwner = &secp256k1fx.OutputOwners{ + Locktime: 0, + Threshold: 2, + Addrs: []ids.ShortID{ + addr, + }, + } + ) + sk, err := bls.NewSecretKey() + require.NoError(t, err) + pop := signer.NewProofOfPossession(sk) + + tests := []test{ + { + name: "permissionless validator tx type", + chainF: func(c *gomock.Controller) Chain { + chain := NewMockChain(c) + validatorTx := &txs.Tx{ + Unsigned: &txs.AddPermissionlessValidatorTx{ + BaseTx: txs.BaseTx{ + BaseTx: avax.BaseTx{ + Outs: outputs, + }, + }, + StakeOuts: stakeOutputs, + ValidatorRewardsOwner: anOwner, + DelegatorRewardsOwner: anotherOwner, + DelegationShares: shares, + Signer: pop, + }, + } + chain.EXPECT().GetTx(stakerID).Return(validatorTx, status.Committed, nil) + return chain + }, + expectedAttributes: &StakerColdAttributes{ + Stake: stakeOutputs, + Outputs: outputs, + Shares: shares, + ValidationRewardsOwner: anOwner, + DelegationRewardsOwner: anotherOwner, + ProofOfPossession: pop, + }, + expectedErr: nil, + }, + { + name: "non permissionless validator tx type", + chainF: func(c *gomock.Controller) Chain { + chain := NewMockChain(c) + validatorTx := &txs.Tx{ + Unsigned: &txs.AddValidatorTx{ + BaseTx: txs.BaseTx{ + BaseTx: avax.BaseTx{ + Outs: outputs, + }, + }, + StakeOuts: stakeOutputs, + RewardsOwner: anOwner, + DelegationShares: shares, + }, + } + chain.EXPECT().GetTx(stakerID).Return(validatorTx, status.Committed, nil) + return chain + }, + expectedAttributes: &StakerColdAttributes{ + Stake: stakeOutputs, + Outputs: outputs, + Shares: shares, + ValidationRewardsOwner: anOwner, + DelegationRewardsOwner: anOwner, + ProofOfPossession: nil, + }, + expectedErr: nil, + }, + { + name: "delegator tx type", + chainF: func(c *gomock.Controller) Chain { + chain := NewMockChain(c) + delegatorTx := &txs.Tx{ + Unsigned: &txs.AddPermissionlessDelegatorTx{ + BaseTx: txs.BaseTx{ + BaseTx: avax.BaseTx{ + Outs: outputs, + }, + }, + StakeOuts: stakeOutputs, + DelegationRewardsOwner: anOwner, + }, + } + chain.EXPECT().GetTx(stakerID).Return(delegatorTx, status.Committed, nil) + return chain + }, + expectedAttributes: &StakerColdAttributes{ + Stake: stakeOutputs, + Outputs: outputs, + RewardsOwner: anOwner, + }, + expectedErr: nil, + }, + { + name: "missing tx", + chainF: func(c *gomock.Controller) Chain { + chain := NewMockChain(c) + chain.EXPECT().GetTx(stakerID).Return(nil, status.Unknown, database.ErrNotFound) + return chain + }, + expectedAttributes: nil, + expectedErr: database.ErrNotFound, + }, + { + name: "unexpected tx type", + chainF: func(c *gomock.Controller) Chain { + chain := NewMockChain(c) + wrongTxType := &txs.Tx{ + Unsigned: &txs.CreateChainTx{}, + } + chain.EXPECT().GetTx(stakerID).Return(wrongTxType, status.Committed, nil) + return chain + }, + expectedAttributes: nil, + expectedErr: errUnexpectedStakerTx, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + + chain := tt.chainF(ctrl) + attributes, err := getStakerColdAttributes(chain, stakerID) + require.ErrorIs(err, tt.expectedErr) + if tt.expectedErr != nil { + return + } + require.Equal(tt.expectedAttributes, attributes) + }) + } +} From e8305e27852bf257f6285ec9285b9717a36e6383 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 20 Dec 2023 14:23:08 +0100 Subject: [PATCH 07/14] some more UTs --- vms/platformvm/state/state_helpers.go | 7 ++- vms/platformvm/state/state_helpers_test.go | 71 ++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/state/state_helpers.go b/vms/platformvm/state/state_helpers.go index cca0a4f84d09..839ebfe4b3ba 100644 --- a/vms/platformvm/state/state_helpers.go +++ b/vms/platformvm/state/state_helpers.go @@ -12,7 +12,10 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) -var errUnexpectedStakerTx = errors.New("unexpected stakerTx type ") +var ( + errUnexpectedStakerTx = errors.New("unexpected stakerTx type ") + errNotABlockchain = errors.New("tx does not created a blockchain") +) func getStakerColdAttributes(chain Chain, stakerID ids.ID) (*StakerColdAttributes, error) { stakerTx, _, err := chain.GetTx(stakerID) @@ -58,7 +61,7 @@ func getChainSubnet(chain Chain, chainID ids.ID) (ids.ID, error) { } blockChain, ok := chainTx.Unsigned.(*txs.CreateChainTx) if !ok { - return ids.Empty, fmt.Errorf("%q is not a blockchain", chainID) + return ids.Empty, fmt.Errorf("%w, txID %q", errNotABlockchain, chainID) } return blockChain.SubnetID, nil } diff --git a/vms/platformvm/state/state_helpers_test.go b/vms/platformvm/state/state_helpers_test.go index 509cf407326b..d025f7ca58eb 100644 --- a/vms/platformvm/state/state_helpers_test.go +++ b/vms/platformvm/state/state_helpers_test.go @@ -229,3 +229,74 @@ func TestGetStakerColdAttributes(t *testing.T) { }) } } + +func TestGetChainSubnet(t *testing.T) { + type test struct { + name string + chainF func(*gomock.Controller) Chain + expectedSubnetID ids.ID + expectedErr error + } + + var ( + chainID = ids.GenerateTestID() + subnetID = ids.GenerateTestID() + ) + + tests := []test{ + { + name: "subnet from existing chain", + chainF: func(c *gomock.Controller) Chain { + chain := NewMockChain(c) + createChainTx := &txs.Tx{ + Unsigned: &txs.CreateChainTx{ + SubnetID: subnetID, + }, + TxID: chainID, + } + chain.EXPECT().GetTx(chainID).Return(createChainTx, status.Committed, nil) + return chain + }, + expectedSubnetID: subnetID, + expectedErr: nil, + }, + { + name: "missing tx", + chainF: func(c *gomock.Controller) Chain { + chain := NewMockChain(c) + chain.EXPECT().GetTx(chainID).Return(nil, status.Unknown, database.ErrNotFound) + return chain + }, + expectedSubnetID: ids.Empty, + expectedErr: database.ErrNotFound, + }, + { + name: "unexpected tx type", + chainF: func(c *gomock.Controller) Chain { + chain := NewMockChain(c) + wrongTxType := &txs.Tx{ + Unsigned: &txs.CreateSubnetTx{}, + } + chain.EXPECT().GetTx(chainID).Return(wrongTxType, status.Committed, nil) + return chain + }, + expectedSubnetID: ids.Empty, + expectedErr: errNotABlockchain, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + + chain := tt.chainF(ctrl) + subnetID, err := getChainSubnet(chain, chainID) + require.ErrorIs(err, tt.expectedErr) + if tt.expectedErr != nil { + return + } + require.Equal(tt.expectedSubnetID, subnetID) + }) + } +} From c311437fc601851441c1420bd8da0f570b5f63fb Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 20 Dec 2023 14:29:49 +0100 Subject: [PATCH 08/14] renamed cold attributes to reward attributes --- vms/platformvm/service.go | 6 +-- vms/platformvm/service_test.go | 2 +- vms/platformvm/state/diff.go | 4 +- vms/platformvm/state/mock_state.go | 42 +++++++++---------- vms/platformvm/state/staker.go | 5 +-- vms/platformvm/state/state.go | 6 +-- vms/platformvm/state/state_helpers.go | 6 +-- vms/platformvm/state/state_helpers_test.go | 12 +++--- .../txs/executor/proposal_tx_executor.go | 8 ++-- vms/platformvm/vm.go | 2 +- 10 files changed, 46 insertions(+), 47 deletions(-) diff --git a/vms/platformvm/service.go b/vms/platformvm/service.go index 5133d87f6434..7a7b1d893aa8 100644 --- a/vms/platformvm/service.go +++ b/vms/platformvm/service.go @@ -84,7 +84,7 @@ var ( type Service struct { vm *VM addrManager avax.AddressManager - stakerAttributesCache *cache.LRU[ids.ID, *state.StakerColdAttributes] + stakerAttributesCache *cache.LRU[ids.ID, *state.StakerRewardAttributes] } // GetHeight returns the height of the last accepted block @@ -715,7 +715,7 @@ type GetCurrentValidatorsReply struct { Validators []interface{} `json:"validators"` } -func (s *Service) loadStakerTxAttributes(txID ids.ID) (*state.StakerColdAttributes, error) { +func (s *Service) loadStakerTxAttributes(txID ids.ID) (*state.StakerRewardAttributes, error) { // Lookup tx from the cache first. attr, found := s.stakerAttributesCache.Get(txID) if found { @@ -723,7 +723,7 @@ func (s *Service) loadStakerTxAttributes(txID ids.ID) (*state.StakerColdAttribut } // Tx not available in cache; pull it from disk and populate the cache. - attr, err := s.vm.state.GetStakerColdAttributes(txID) + attr, err := s.vm.state.GetStakerRewardAttributes(txID) if err != nil { return nil, err } diff --git a/vms/platformvm/service_test.go b/vms/platformvm/service_test.go index 90c2b4a32a0f..dc0820c73da1 100644 --- a/vms/platformvm/service_test.go +++ b/vms/platformvm/service_test.go @@ -83,7 +83,7 @@ func defaultService(t *testing.T) (*Service, *mutableSharedMemory) { return &Service{ vm: vm, addrManager: avax.NewAddressManager(vm.ctx), - stakerAttributesCache: &cache.LRU[ids.ID, *state.StakerColdAttributes]{ + stakerAttributesCache: &cache.LRU[ids.ID, *state.StakerRewardAttributes]{ Size: stakerAttributesCacheSize, }, }, mutableSharedMemory diff --git a/vms/platformvm/state/diff.go b/vms/platformvm/state/diff.go index 3e395cdf4ed7..d429fc74317d 100644 --- a/vms/platformvm/state/diff.go +++ b/vms/platformvm/state/diff.go @@ -209,8 +209,8 @@ func (d *diff) GetCurrentStakerIterator() (StakerIterator, error) { return d.currentStakerDiffs.GetStakerIterator(parentIterator), nil } -func (d *diff) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) { - return getStakerColdAttributes(d, stakerID) +func (d *diff) GetStakerRewardAttributes(stakerID ids.ID) (*StakerRewardAttributes, error) { + return getStakerRewardAttributes(d, stakerID) } func (d *diff) GetPendingValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error) { diff --git a/vms/platformvm/state/mock_state.go b/vms/platformvm/state/mock_state.go index dceff53e3f5d..d1c312a6106d 100644 --- a/vms/platformvm/state/mock_state.go +++ b/vms/platformvm/state/mock_state.go @@ -315,19 +315,19 @@ func (mr *MockChainMockRecorder) GetPendingValidator(arg0, arg1 interface{}) *go return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingValidator", reflect.TypeOf((*MockChain)(nil).GetPendingValidator), arg0, arg1) } -// GetStakerColdAttributes mocks base method. -func (m *MockChain) GetStakerColdAttributes(arg0 ids.ID) (*StakerColdAttributes, error) { +// GetStakerRewardAttributes mocks base method. +func (m *MockChain) GetStakerRewardAttributes(arg0 ids.ID) (*StakerRewardAttributes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStakerColdAttributes", arg0) - ret0, _ := ret[0].(*StakerColdAttributes) + ret := m.ctrl.Call(m, "GetStakerRewardAttributes", arg0) + ret0, _ := ret[0].(*StakerRewardAttributes) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetStakerColdAttributes indicates an expected call of GetStakerColdAttributes. -func (mr *MockChainMockRecorder) GetStakerColdAttributes(arg0 interface{}) *gomock.Call { +// GetStakerRewardAttributes indicates an expected call of GetStakerRewardAttributes. +func (mr *MockChainMockRecorder) GetStakerRewardAttributes(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerColdAttributes", reflect.TypeOf((*MockChain)(nil).GetStakerColdAttributes), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerRewardAttributes", reflect.TypeOf((*MockChain)(nil).GetStakerRewardAttributes), arg0) } // GetSubnetOwner mocks base method. @@ -807,19 +807,19 @@ func (mr *MockDiffMockRecorder) GetPendingValidator(arg0, arg1 interface{}) *gom return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingValidator", reflect.TypeOf((*MockDiff)(nil).GetPendingValidator), arg0, arg1) } -// GetStakerColdAttributes mocks base method. -func (m *MockDiff) GetStakerColdAttributes(arg0 ids.ID) (*StakerColdAttributes, error) { +// GetStakerRewardAttributes mocks base method. +func (m *MockDiff) GetStakerRewardAttributes(arg0 ids.ID) (*StakerRewardAttributes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStakerColdAttributes", arg0) - ret0, _ := ret[0].(*StakerColdAttributes) + ret := m.ctrl.Call(m, "GetStakerRewardAttributes", arg0) + ret0, _ := ret[0].(*StakerRewardAttributes) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetStakerColdAttributes indicates an expected call of GetStakerColdAttributes. -func (mr *MockDiffMockRecorder) GetStakerColdAttributes(arg0 interface{}) *gomock.Call { +// GetStakerRewardAttributes indicates an expected call of GetStakerRewardAttributes. +func (mr *MockDiffMockRecorder) GetStakerRewardAttributes(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerColdAttributes", reflect.TypeOf((*MockDiff)(nil).GetStakerColdAttributes), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerRewardAttributes", reflect.TypeOf((*MockDiff)(nil).GetStakerRewardAttributes), arg0) } // GetSubnetOwner mocks base method. @@ -1453,19 +1453,19 @@ func (mr *MockStateMockRecorder) GetRewardUTXOs(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRewardUTXOs", reflect.TypeOf((*MockState)(nil).GetRewardUTXOs), arg0) } -// GetStakerColdAttributes mocks base method. -func (m *MockState) GetStakerColdAttributes(arg0 ids.ID) (*StakerColdAttributes, error) { +// GetStakerRewardAttributes mocks base method. +func (m *MockState) GetStakerRewardAttributes(arg0 ids.ID) (*StakerRewardAttributes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetStakerColdAttributes", arg0) - ret0, _ := ret[0].(*StakerColdAttributes) + ret := m.ctrl.Call(m, "GetStakerRewardAttributes", arg0) + ret0, _ := ret[0].(*StakerRewardAttributes) ret1, _ := ret[1].(error) return ret0, ret1 } -// GetStakerColdAttributes indicates an expected call of GetStakerColdAttributes. -func (mr *MockStateMockRecorder) GetStakerColdAttributes(arg0 interface{}) *gomock.Call { +// GetStakerRewardAttributes indicates an expected call of GetStakerRewardAttributes. +func (mr *MockStateMockRecorder) GetStakerRewardAttributes(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerColdAttributes", reflect.TypeOf((*MockState)(nil).GetStakerColdAttributes), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerRewardAttributes", reflect.TypeOf((*MockState)(nil).GetStakerRewardAttributes), arg0) } // GetStartTime mocks base method. diff --git a/vms/platformvm/state/staker.go b/vms/platformvm/state/staker.go index df8cb69f22c4..ef3848c3513f 100644 --- a/vms/platformvm/state/staker.go +++ b/vms/platformvm/state/staker.go @@ -131,12 +131,11 @@ func NewPendingStaker(txID ids.ID, staker txs.ScheduledStaker) (*Staker, error) } // While Staker object contains a staker's hot attributes, likely to be used pretty often -// StakerColdAttributes contains a staker's cold attributes, rarely used, mostly when rewarding it. +// StakerRewardAttributes contains a staker's cold attributes, rarely used, mostly when rewarding it. // Note that both Staker and StakerAttribute content comes from the stakerTx creating the staker. // In state.State we do have StakerMetadata information as well, which contains data about the stakers // that are generated during staker's activity (mostly uptimes) -// TODO: consider moving delegatees reward here, out of StakersMetadata. -type StakerColdAttributes struct { +type StakerRewardAttributes struct { // common attributes Stake []*avax.TransferableOutput Outputs []*avax.TransferableOutput diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 03ed8eb561b1..42545f0ddcd5 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -119,7 +119,7 @@ type Chain interface { AddChain(createChainTx *txs.Tx) GetChainSubnet(chainID ids.ID) (ids.ID, error) - GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) + GetStakerRewardAttributes(stakerID ids.ID) (*StakerRewardAttributes, error) GetTx(txID ids.ID) (*txs.Tx, status.Status, error) AddTx(tx *txs.Tx, status status.Status) @@ -738,8 +738,8 @@ func (s *state) GetCurrentStakerIterator() (StakerIterator, error) { return s.currentStakers.GetStakerIterator(), nil } -func (s *state) GetStakerColdAttributes(stakerID ids.ID) (*StakerColdAttributes, error) { - return getStakerColdAttributes(s, stakerID) +func (s *state) GetStakerRewardAttributes(stakerID ids.ID) (*StakerRewardAttributes, error) { + return getStakerRewardAttributes(s, stakerID) } func (s *state) GetPendingValidator(subnetID ids.ID, nodeID ids.NodeID) (*Staker, error) { diff --git a/vms/platformvm/state/state_helpers.go b/vms/platformvm/state/state_helpers.go index 839ebfe4b3ba..6ba86e56a13b 100644 --- a/vms/platformvm/state/state_helpers.go +++ b/vms/platformvm/state/state_helpers.go @@ -17,7 +17,7 @@ var ( errNotABlockchain = errors.New("tx does not created a blockchain") ) -func getStakerColdAttributes(chain Chain, stakerID ids.ID) (*StakerColdAttributes, error) { +func getStakerRewardAttributes(chain Chain, stakerID ids.ID) (*StakerRewardAttributes, error) { stakerTx, _, err := chain.GetTx(stakerID) if err != nil { return nil, fmt.Errorf("failed to get next staker %s: %w", stakerID, err) @@ -31,7 +31,7 @@ func getStakerColdAttributes(chain Chain, stakerID ids.ID) (*StakerColdAttribute } } - return &StakerColdAttributes{ + return &StakerRewardAttributes{ Stake: uStakerTx.Stake(), Outputs: uStakerTx.Outputs(), Shares: uStakerTx.Shares(), @@ -40,7 +40,7 @@ func getStakerColdAttributes(chain Chain, stakerID ids.ID) (*StakerColdAttribute ProofOfPossession: pop, }, nil case txs.DelegatorTx: - return &StakerColdAttributes{ + return &StakerRewardAttributes{ Stake: uStakerTx.Stake(), Outputs: uStakerTx.Outputs(), RewardsOwner: uStakerTx.RewardsOwner(), diff --git a/vms/platformvm/state/state_helpers_test.go b/vms/platformvm/state/state_helpers_test.go index d025f7ca58eb..f90d6b7b2031 100644 --- a/vms/platformvm/state/state_helpers_test.go +++ b/vms/platformvm/state/state_helpers_test.go @@ -21,11 +21,11 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) -func TestGetStakerColdAttributes(t *testing.T) { +func TestGetStakerRewardAttributes(t *testing.T) { type test struct { name string chainF func(*gomock.Controller) Chain - expectedAttributes *StakerColdAttributes + expectedAttributes *StakerRewardAttributes expectedErr error } @@ -125,7 +125,7 @@ func TestGetStakerColdAttributes(t *testing.T) { chain.EXPECT().GetTx(stakerID).Return(validatorTx, status.Committed, nil) return chain }, - expectedAttributes: &StakerColdAttributes{ + expectedAttributes: &StakerRewardAttributes{ Stake: stakeOutputs, Outputs: outputs, Shares: shares, @@ -154,7 +154,7 @@ func TestGetStakerColdAttributes(t *testing.T) { chain.EXPECT().GetTx(stakerID).Return(validatorTx, status.Committed, nil) return chain }, - expectedAttributes: &StakerColdAttributes{ + expectedAttributes: &StakerRewardAttributes{ Stake: stakeOutputs, Outputs: outputs, Shares: shares, @@ -182,7 +182,7 @@ func TestGetStakerColdAttributes(t *testing.T) { chain.EXPECT().GetTx(stakerID).Return(delegatorTx, status.Committed, nil) return chain }, - expectedAttributes: &StakerColdAttributes{ + expectedAttributes: &StakerRewardAttributes{ Stake: stakeOutputs, Outputs: outputs, RewardsOwner: anOwner, @@ -220,7 +220,7 @@ func TestGetStakerColdAttributes(t *testing.T) { ctrl := gomock.NewController(t) chain := tt.chainF(ctrl) - attributes, err := getStakerColdAttributes(chain, stakerID) + attributes, err := getStakerRewardAttributes(chain, stakerID) require.ErrorIs(err, tt.expectedErr) if tt.expectedErr != nil { return diff --git a/vms/platformvm/txs/executor/proposal_tx_executor.go b/vms/platformvm/txs/executor/proposal_tx_executor.go index 8c96abbf4661..31834c2c9e71 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor.go @@ -363,7 +363,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error return err } - stakerAttributes, err := e.OnCommitState.GetStakerColdAttributes(stakerToReward.TxID) + stakerAttributes, err := e.OnCommitState.GetStakerRewardAttributes(stakerToReward.TxID) if err != nil { return fmt.Errorf("failed to get attributes for staker %d: %w", stakerToReward.TxID, err) } @@ -411,7 +411,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error return err } -func (e *ProposalTxExecutor) rewardValidatorTx(validator *state.Staker, valAttributes *state.StakerColdAttributes) error { +func (e *ProposalTxExecutor) rewardValidatorTx(validator *state.Staker, valAttributes *state.StakerRewardAttributes) error { var ( txID = validator.TxID stake = valAttributes.Stake @@ -513,7 +513,7 @@ func (e *ProposalTxExecutor) rewardValidatorTx(validator *state.Staker, valAttri return nil } -func (e *ProposalTxExecutor) rewardDelegatorTx(delegator *state.Staker, delAttributes *state.StakerColdAttributes) error { +func (e *ProposalTxExecutor) rewardDelegatorTx(delegator *state.Staker, delAttributes *state.StakerRewardAttributes) error { var ( txID = delegator.TxID stake = delAttributes.Stake @@ -544,7 +544,7 @@ func (e *ProposalTxExecutor) rewardDelegatorTx(delegator *state.Staker, delAttri return fmt.Errorf("failed to get whether %s is a validator: %w", delegator.NodeID, err) } - valAttributes, err := e.OnCommitState.GetStakerColdAttributes(validator.TxID) + valAttributes, err := e.OnCommitState.GetStakerRewardAttributes(validator.TxID) if err != nil { return fmt.Errorf("failed to get whether %s is a validator: %w", delegator.NodeID, err) } diff --git a/vms/platformvm/vm.go b/vms/platformvm/vm.go index 449ba86404b1..19c19437602d 100644 --- a/vms/platformvm/vm.go +++ b/vms/platformvm/vm.go @@ -420,7 +420,7 @@ func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error) { service := &Service{ vm: vm, addrManager: avax.NewAddressManager(vm.ctx), - stakerAttributesCache: &cache.LRU[ids.ID, *state.StakerColdAttributes]{ + stakerAttributesCache: &cache.LRU[ids.ID, *state.StakerRewardAttributes]{ Size: stakerAttributesCacheSize, }, } From a6d02faa563ac41b3d633df289bd8debc843d47e Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 20 Dec 2023 14:44:08 +0100 Subject: [PATCH 09/14] some more use of staker reward attributes --- vms/platformvm/service.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/vms/platformvm/service.go b/vms/platformvm/service.go index 7a7b1d893aa8..48c2ff34851a 100644 --- a/vms/platformvm/service.go +++ b/vms/platformvm/service.go @@ -2298,12 +2298,12 @@ func (s *Service) GetStake(_ *http.Request, args *GetStakeArgs, response *GetSta continue } - tx, _, err := s.vm.state.GetTx(staker.TxID) + stakerRewardAttributes, err := s.vm.state.GetStakerRewardAttributes(staker.TxID) if err != nil { return err } - stakedOuts = append(stakedOuts, getStakeHelper(tx, addrs, totalAmountStaked)...) + stakedOuts = append(stakedOuts, getStakeHelper(stakerRewardAttributes.Stake, addrs, totalAmountStaked)...) } pendingStakerIterator, err := s.vm.state.GetPendingStakerIterator() @@ -2319,12 +2319,12 @@ func (s *Service) GetStake(_ *http.Request, args *GetStakeArgs, response *GetSta continue } - tx, _, err := s.vm.state.GetTx(staker.TxID) + stakerRewardAttributes, err := s.vm.state.GetStakerRewardAttributes(staker.TxID) if err != nil { return err } - stakedOuts = append(stakedOuts, getStakeHelper(tx, addrs, totalAmountStaked)...) + stakedOuts = append(stakedOuts, getStakeHelper(stakerRewardAttributes.Stake, addrs, totalAmountStaked)...) } response.Stakeds = newJSONBalanceMap(totalAmountStaked) @@ -2751,13 +2751,7 @@ func (s *Service) getAPIOwner(owner *secp256k1fx.OutputOwners) (*platformapi.Own // Returns: // 1) The total amount staked by addresses in [addrs] // 2) The staked outputs -func getStakeHelper(tx *txs.Tx, addrs set.Set[ids.ShortID], totalAmountStaked map[ids.ID]uint64) []avax.TransferableOutput { - staker, ok := tx.Unsigned.(txs.PermissionlessStaker) - if !ok { - return nil - } - - stake := staker.Stake() +func getStakeHelper(stake []*avax.TransferableOutput, addrs set.Set[ids.ShortID], totalAmountStaked map[ids.ID]uint64) []avax.TransferableOutput { stakedOuts := make([]avax.TransferableOutput, 0, len(stake)) // Go through all of the staked outputs for _, output := range stake { From 1255c4f2257aafb2fcf3717de23de02d4652fc79 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 20 Dec 2023 22:08:54 +0100 Subject: [PATCH 10/14] nits --- vms/platformvm/service.go | 6 +++--- vms/platformvm/state/staker.go | 8 ++++---- vms/platformvm/state/state_helpers.go | 4 ++-- vms/platformvm/state/state_helpers_test.go | 2 +- vms/platformvm/txs/executor/proposal_tx_executor.go | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/vms/platformvm/service.go b/vms/platformvm/service.go index 48c2ff34851a..3f70fb393d03 100644 --- a/vms/platformvm/service.go +++ b/vms/platformvm/service.go @@ -716,13 +716,13 @@ type GetCurrentValidatorsReply struct { } func (s *Service) loadStakerTxAttributes(txID ids.ID) (*state.StakerRewardAttributes, error) { - // Lookup tx from the cache first. + // Lookup attributes from the cache first. attr, found := s.stakerAttributesCache.Get(txID) if found { return attr, nil } - // Tx not available in cache; pull it from disk and populate the cache. + // attributes not available in cache; pull them from disk and populate the cache. attr, err := s.vm.state.GetStakerRewardAttributes(txID) if err != nil { return nil, err @@ -2747,7 +2747,7 @@ func (s *Service) getAPIOwner(owner *secp256k1fx.OutputOwners) (*platformapi.Own return apiOwner, nil } -// Takes in a staker and a set of addresses +// Takes in a slice of reward attributes and a set of addresses // Returns: // 1) The total amount staked by addresses in [addrs] // 2) The staked outputs diff --git a/vms/platformvm/state/staker.go b/vms/platformvm/state/staker.go index ef3848c3513f..2cd764e22f3b 100644 --- a/vms/platformvm/state/staker.go +++ b/vms/platformvm/state/staker.go @@ -130,11 +130,11 @@ func NewPendingStaker(txID ids.ID, staker txs.ScheduledStaker) (*Staker, error) }, nil } -// While Staker object contains a staker's hot attributes, likely to be used pretty often -// StakerRewardAttributes contains a staker's cold attributes, rarely used, mostly when rewarding it. +// Staker object contains a staker's hot attributes, likely to be used often. +// StakerRewardAttributes contains a staker's cold attributes which are used less often. // Note that both Staker and StakerAttribute content comes from the stakerTx creating the staker. -// In state.State we do have StakerMetadata information as well, which contains data about the stakers -// that are generated during staker's activity (mostly uptimes) +// In state.State we also have StakerMetadata, which contains data about the stakers +// generated during staker's activity (mostly uptimes). type StakerRewardAttributes struct { // common attributes Stake []*avax.TransferableOutput diff --git a/vms/platformvm/state/state_helpers.go b/vms/platformvm/state/state_helpers.go index 6ba86e56a13b..e286c7cde56d 100644 --- a/vms/platformvm/state/state_helpers.go +++ b/vms/platformvm/state/state_helpers.go @@ -13,7 +13,7 @@ import ( ) var ( - errUnexpectedStakerTx = errors.New("unexpected stakerTx type ") + ErrUnexpectedStakerTx = errors.New("unexpected stakerTx type ") errNotABlockchain = errors.New("tx does not created a blockchain") ) @@ -46,7 +46,7 @@ func getStakerRewardAttributes(chain Chain, stakerID ids.ID) (*StakerRewardAttri RewardsOwner: uStakerTx.RewardsOwner(), }, nil default: - return nil, fmt.Errorf("%w, txType %T", errUnexpectedStakerTx, uStakerTx) + return nil, fmt.Errorf("%w, txType %T", ErrUnexpectedStakerTx, uStakerTx) } } diff --git a/vms/platformvm/state/state_helpers_test.go b/vms/platformvm/state/state_helpers_test.go index f90d6b7b2031..0dc2637661bd 100644 --- a/vms/platformvm/state/state_helpers_test.go +++ b/vms/platformvm/state/state_helpers_test.go @@ -210,7 +210,7 @@ func TestGetStakerRewardAttributes(t *testing.T) { return chain }, expectedAttributes: nil, - expectedErr: errUnexpectedStakerTx, + expectedErr: ErrUnexpectedStakerTx, }, } diff --git a/vms/platformvm/txs/executor/proposal_tx_executor.go b/vms/platformvm/txs/executor/proposal_tx_executor.go index 31834c2c9e71..8e3df3ee6eeb 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor.go @@ -365,7 +365,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error stakerAttributes, err := e.OnCommitState.GetStakerRewardAttributes(stakerToReward.TxID) if err != nil { - return fmt.Errorf("failed to get attributes for staker %d: %w", stakerToReward.TxID, err) + return fmt.Errorf("failed to get attributes for staker %s: %w", stakerToReward.TxID, err) } switch { @@ -392,7 +392,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error e.OnCommitState.DeleteCurrentDelegator(stakerToReward) e.OnAbortState.DeleteCurrentDelegator(stakerToReward) default: - return errors.New("unexpected staker type") + return state.ErrUnexpectedStakerTx } // If the reward is aborted, then the current supply should be decreased. From de5c35c3d797e8a47bee6ba956556a36560b130c Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Wed, 20 Dec 2023 22:23:48 +0100 Subject: [PATCH 11/14] nit --- vms/platformvm/state/state_helpers.go | 6 +++--- vms/platformvm/state/state_helpers_test.go | 2 +- vms/platformvm/txs/executor/proposal_tx_executor.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vms/platformvm/state/state_helpers.go b/vms/platformvm/state/state_helpers.go index e286c7cde56d..f48d25209400 100644 --- a/vms/platformvm/state/state_helpers.go +++ b/vms/platformvm/state/state_helpers.go @@ -13,8 +13,8 @@ import ( ) var ( - ErrUnexpectedStakerTx = errors.New("unexpected stakerTx type ") - errNotABlockchain = errors.New("tx does not created a blockchain") + ErrUnexpectedStakerType = errors.New("unexpected staker type ") + errNotABlockchain = errors.New("tx does not created a blockchain") ) func getStakerRewardAttributes(chain Chain, stakerID ids.ID) (*StakerRewardAttributes, error) { @@ -46,7 +46,7 @@ func getStakerRewardAttributes(chain Chain, stakerID ids.ID) (*StakerRewardAttri RewardsOwner: uStakerTx.RewardsOwner(), }, nil default: - return nil, fmt.Errorf("%w, txType %T", ErrUnexpectedStakerTx, uStakerTx) + return nil, fmt.Errorf("%w, txType %T", ErrUnexpectedStakerType, uStakerTx) } } diff --git a/vms/platformvm/state/state_helpers_test.go b/vms/platformvm/state/state_helpers_test.go index 0dc2637661bd..fe2dcc9371cb 100644 --- a/vms/platformvm/state/state_helpers_test.go +++ b/vms/platformvm/state/state_helpers_test.go @@ -210,7 +210,7 @@ func TestGetStakerRewardAttributes(t *testing.T) { return chain }, expectedAttributes: nil, - expectedErr: ErrUnexpectedStakerTx, + expectedErr: ErrUnexpectedStakerType, }, } diff --git a/vms/platformvm/txs/executor/proposal_tx_executor.go b/vms/platformvm/txs/executor/proposal_tx_executor.go index 8e3df3ee6eeb..d012ecea7d3b 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor.go @@ -392,7 +392,7 @@ func (e *ProposalTxExecutor) RewardValidatorTx(tx *txs.RewardValidatorTx) error e.OnCommitState.DeleteCurrentDelegator(stakerToReward) e.OnAbortState.DeleteCurrentDelegator(stakerToReward) default: - return state.ErrUnexpectedStakerTx + return state.ErrUnexpectedStakerType } // If the reward is aborted, then the current supply should be decreased. From b0f525bcd79d2d6a8729eb9ef546d5751f2f6e23 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Thu, 11 Jan 2024 10:03:53 +0100 Subject: [PATCH 12/14] added UTs --- vms/platformvm/state/state_helpers_test.go | 68 ++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/vms/platformvm/state/state_helpers_test.go b/vms/platformvm/state/state_helpers_test.go index fe2dcc9371cb..9925109d9091 100644 --- a/vms/platformvm/state/state_helpers_test.go +++ b/vms/platformvm/state/state_helpers_test.go @@ -5,6 +5,7 @@ package state import ( "testing" + "time" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -212,6 +213,47 @@ func TestGetStakerRewardAttributes(t *testing.T) { expectedAttributes: nil, expectedErr: ErrUnexpectedStakerType, }, + { + name: "getStakerRewardAttributes works across layers", + chainF: func(c *gomock.Controller) Chain { + // pile a diff on top of base state and let the target tx + // be included in base state. + state := NewMockState(c) + validatorTx := &txs.Tx{ + Unsigned: &txs.AddPermissionlessValidatorTx{ + BaseTx: txs.BaseTx{ + BaseTx: avax.BaseTx{ + Outs: outputs, + }, + }, + StakeOuts: stakeOutputs, + ValidatorRewardsOwner: anOwner, + DelegatorRewardsOwner: anotherOwner, + DelegationShares: shares, + Signer: pop, + }, + } + state.EXPECT().GetTx(stakerID).Return(validatorTx, status.Committed, nil) + state.EXPECT().GetTimestamp().Return(time.Now()) // needed to build diff + stateID := ids.GenerateTestID() + + versions := NewMockVersions(c) + versions.EXPECT().GetState(stateID).Return(state, true).Times(2) + + diff, err := NewDiff(stateID, versions) + require.NoError(t, err) + return diff + }, + expectedAttributes: &StakerRewardAttributes{ + Stake: stakeOutputs, + Outputs: outputs, + Shares: shares, + ValidationRewardsOwner: anOwner, + DelegationRewardsOwner: anotherOwner, + ProofOfPossession: pop, + }, + expectedErr: nil, + }, } for _, tt := range tests { @@ -283,6 +325,32 @@ func TestGetChainSubnet(t *testing.T) { expectedSubnetID: ids.Empty, expectedErr: errNotABlockchain, }, + { + name: "getChainSubnet works across layers", + chainF: func(c *gomock.Controller) Chain { + // pile a diff on top of base state and let the target tx + // be included in base state. + state := NewMockState(c) + createChainTx := &txs.Tx{ + Unsigned: &txs.CreateChainTx{ + SubnetID: subnetID, + }, + TxID: chainID, + } + state.EXPECT().GetTx(chainID).Return(createChainTx, status.Committed, nil) + state.EXPECT().GetTimestamp().Return(time.Now()) // needed to build diff + stateID := ids.GenerateTestID() + + versions := NewMockVersions(c) + versions.EXPECT().GetState(stateID).Return(state, true).Times(2) + + diff, err := NewDiff(stateID, versions) + require.NoError(t, err) + return diff + }, + expectedSubnetID: subnetID, + expectedErr: nil, + }, } for _, tt := range tests { From 297a490ce2c8a2d40fa69c453c1fb14b1b2366d1 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Thu, 18 Jan 2024 09:26:27 +0100 Subject: [PATCH 13/14] appease linter --- vms/platformvm/state/state_helpers.go | 2 +- vms/platformvm/state/state_helpers_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/state/state_helpers.go b/vms/platformvm/state/state_helpers.go index f48d25209400..6726c0162966 100644 --- a/vms/platformvm/state/state_helpers.go +++ b/vms/platformvm/state/state_helpers.go @@ -1,4 +1,4 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package state diff --git a/vms/platformvm/state/state_helpers_test.go b/vms/platformvm/state/state_helpers_test.go index 9925109d9091..6ad5eaff903e 100644 --- a/vms/platformvm/state/state_helpers_test.go +++ b/vms/platformvm/state/state_helpers_test.go @@ -1,4 +1,4 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. package state From 61cfc547027fbe51fcffc958e4c47c38aff58893 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo <alberto.benegiamo@gmail.com> Date: Fri, 19 Jan 2024 15:02:51 +0100 Subject: [PATCH 14/14] fixed mock regeneration --- vms/platformvm/state/mock_state.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vms/platformvm/state/mock_state.go b/vms/platformvm/state/mock_state.go index 07c99ccc0e46..ca405cb421a8 100644 --- a/vms/platformvm/state/mock_state.go +++ b/vms/platformvm/state/mock_state.go @@ -192,7 +192,7 @@ func (m *MockChain) GetChainSubnet(arg0 ids.ID) (ids.ID, error) { } // GetChainSubnet indicates an expected call of GetChainSubnet. -func (mr *MockChainMockRecorder) GetChainSubnet(arg0 interface{}) *gomock.Call { +func (mr *MockChainMockRecorder) GetChainSubnet(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChainSubnet", reflect.TypeOf((*MockChain)(nil).GetChainSubnet), arg0) } @@ -327,7 +327,7 @@ func (m *MockChain) GetStakerRewardAttributes(arg0 ids.ID) (*StakerRewardAttribu } // GetStakerRewardAttributes indicates an expected call of GetStakerRewardAttributes. -func (mr *MockChainMockRecorder) GetStakerRewardAttributes(arg0 interface{}) *gomock.Call { +func (mr *MockChainMockRecorder) GetStakerRewardAttributes(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerRewardAttributes", reflect.TypeOf((*MockChain)(nil).GetStakerRewardAttributes), arg0) } @@ -684,7 +684,7 @@ func (m *MockDiff) GetChainSubnet(arg0 ids.ID) (ids.ID, error) { } // GetChainSubnet indicates an expected call of GetChainSubnet. -func (mr *MockDiffMockRecorder) GetChainSubnet(arg0 interface{}) *gomock.Call { +func (mr *MockDiffMockRecorder) GetChainSubnet(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChainSubnet", reflect.TypeOf((*MockDiff)(nil).GetChainSubnet), arg0) } @@ -819,7 +819,7 @@ func (m *MockDiff) GetStakerRewardAttributes(arg0 ids.ID) (*StakerRewardAttribut } // GetStakerRewardAttributes indicates an expected call of GetStakerRewardAttributes. -func (mr *MockDiffMockRecorder) GetStakerRewardAttributes(arg0 interface{}) *gomock.Call { +func (mr *MockDiffMockRecorder) GetStakerRewardAttributes(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerRewardAttributes", reflect.TypeOf((*MockDiff)(nil).GetStakerRewardAttributes), arg0) } @@ -1286,7 +1286,7 @@ func (m *MockState) GetChainSubnet(arg0 ids.ID) (ids.ID, error) { } // GetChainSubnet indicates an expected call of GetChainSubnet. -func (mr *MockStateMockRecorder) GetChainSubnet(arg0 interface{}) *gomock.Call { +func (mr *MockStateMockRecorder) GetChainSubnet(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChainSubnet", reflect.TypeOf((*MockState)(nil).GetChainSubnet), arg0) } @@ -1465,7 +1465,7 @@ func (m *MockState) GetStakerRewardAttributes(arg0 ids.ID) (*StakerRewardAttribu } // GetStakerRewardAttributes indicates an expected call of GetStakerRewardAttributes. -func (mr *MockStateMockRecorder) GetStakerRewardAttributes(arg0 interface{}) *gomock.Call { +func (mr *MockStateMockRecorder) GetStakerRewardAttributes(arg0 any) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStakerRewardAttributes", reflect.TypeOf((*MockState)(nil).GetStakerRewardAttributes), arg0) }