From 17723e25a55cc12b83f990991a1da1f28415ab31 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 14 Nov 2023 14:27:25 +0100 Subject: [PATCH 01/25] wip: introduced post durango staker tx --- .../block/executor/proposal_block_test.go | 34 ++++++++--- .../block/executor/standard_block_test.go | 4 +- vms/platformvm/service_test.go | 8 ++- vms/platformvm/state/staker.go | 13 ++++- vms/platformvm/state/staker_test.go | 10 ++-- vms/platformvm/state/state.go | 48 ++++++++++------ vms/platformvm/txs/add_delegator_tx.go | 3 +- .../txs/add_permissionless_delegator_tx.go | 5 +- .../txs/add_permissionless_validator_tx.go | 3 +- vms/platformvm/txs/add_subnet_validator_tx.go | 3 +- vms/platformvm/txs/add_validator_tx.go | 3 +- .../txs/executor/advance_time_test.go | 4 +- .../txs/executor/proposal_tx_executor_test.go | 20 +++++-- .../txs/executor/reward_validator_test.go | 32 ++++++++--- .../txs/executor/standard_tx_executor.go | 57 +++++++++++++------ .../txs/executor/standard_tx_executor_test.go | 24 ++++++-- vms/platformvm/txs/staker_tx.go | 20 +++++-- 17 files changed, 207 insertions(+), 84 deletions(-) diff --git a/vms/platformvm/block/executor/proposal_block_test.go b/vms/platformvm/block/executor/proposal_block_test.go index 4300ad9606d9..9436687510c3 100644 --- a/vms/platformvm/block/executor/proposal_block_test.go +++ b/vms/platformvm/block/executor/proposal_block_test.go @@ -596,7 +596,7 @@ func TestBanffProposalBlockUpdateStakers(t *testing.T) { for _, subStaker := range test.subnetStakers { tx, err := env.txBuilder.NewAddSubnetValidatorTx( - 10, // Weight + env.config.MaxValidatorStake, // Weight uint64(subStaker.startTime.Unix()), uint64(subStaker.endTime.Unix()), subStaker.nodeID, // validator ID @@ -636,9 +636,11 @@ func TestBanffProposalBlockUpdateStakers(t *testing.T) { require.NoError(err) // store Staker0 to state + addValTx := addStaker0.Unsigned.(*txs.AddValidatorTx) staker0, err := state.NewCurrentStaker( addStaker0.ID(), - addStaker0.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) @@ -736,9 +738,11 @@ func TestBanffProposalBlockRemoveSubnetValidator(t *testing.T) { ) require.NoError(err) + addSubnetValTx := tx.Unsigned.(*txs.AddSubnetValidatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddSubnetValidatorTx), + addSubnetValTx, + addSubnetValTx.StartTime(), 0, ) require.NoError(err) @@ -794,9 +798,11 @@ func TestBanffProposalBlockRemoveSubnetValidator(t *testing.T) { require.NoError(err) // store Staker0 to state + addValTx := addStaker0.Unsigned.(*txs.AddValidatorTx) staker, err = state.NewCurrentStaker( addStaker0.ID(), - addStaker0.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) @@ -907,9 +913,11 @@ func TestBanffProposalBlockTrackedSubnet(t *testing.T) { require.NoError(err) // store Staker0 to state + addValTx := addStaker0.Unsigned.(*txs.AddValidatorTx) staker, err = state.NewCurrentStaker( addStaker0.ID(), - addStaker0.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) @@ -993,9 +1001,11 @@ func TestBanffProposalBlockDelegatorStakerWeight(t *testing.T) { require.NoError(err) // store Staker0 to state + addValTx := addStaker0.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( addStaker0.ID(), - addStaker0.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) @@ -1084,9 +1094,11 @@ func TestBanffProposalBlockDelegatorStakerWeight(t *testing.T) { require.NoError(err) // store Staker0 to state + addValTx = addStaker0.Unsigned.(*txs.AddValidatorTx) staker, err = state.NewCurrentStaker( addStaker0.ID(), - addStaker0.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) @@ -1174,9 +1186,11 @@ func TestBanffProposalBlockDelegatorStakers(t *testing.T) { require.NoError(err) // store Staker0 to state + addValTx := addStaker0.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( addStaker0.ID(), - addStaker0.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) @@ -1264,9 +1278,11 @@ func TestBanffProposalBlockDelegatorStakers(t *testing.T) { require.NoError(err) // store Staker0 to state + addValTx = addStaker0.Unsigned.(*txs.AddValidatorTx) staker, err = state.NewCurrentStaker( addStaker0.ID(), - addStaker0.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) diff --git a/vms/platformvm/block/executor/standard_block_test.go b/vms/platformvm/block/executor/standard_block_test.go index 110def5c5987..f5d27fd46784 100644 --- a/vms/platformvm/block/executor/standard_block_test.go +++ b/vms/platformvm/block/executor/standard_block_test.go @@ -617,9 +617,11 @@ func TestBanffStandardBlockRemoveSubnetValidator(t *testing.T) { ) require.NoError(err) + addSubnetValTx := tx.Unsigned.(*txs.AddSubnetValidatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddSubnetValidatorTx), + addSubnetValTx, + addSubnetValTx.StartTime(), 0, ) require.NoError(err) diff --git a/vms/platformvm/service_test.go b/vms/platformvm/service_test.go index b3eebf31659d..2204bcb81552 100644 --- a/vms/platformvm/service_test.go +++ b/vms/platformvm/service_test.go @@ -507,9 +507,11 @@ func TestGetStake(t *testing.T) { ) require.NoError(err) + addDelTx := tx.Unsigned.(*txs.AddDelegatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddDelegatorTx), + addDelTx, + addDelTx.StartTime(), 0, ) require.NoError(err) @@ -643,9 +645,11 @@ func TestGetCurrentValidators(t *testing.T) { ) require.NoError(err) + addDelTx := delTx.Unsigned.(*txs.AddDelegatorTx) staker, err := state.NewCurrentStaker( delTx.ID(), - delTx.Unsigned.(*txs.AddDelegatorTx), + addDelTx, + addDelTx.StartTime(), 0, ) require.NoError(err) diff --git a/vms/platformvm/state/staker.go b/vms/platformvm/state/staker.go index 37bc512e36cb..5cbabb42920d 100644 --- a/vms/platformvm/state/staker.go +++ b/vms/platformvm/state/staker.go @@ -83,19 +83,26 @@ func (s *Staker) Less(than *Staker) bool { return bytes.Compare(s.TxID[:], than.TxID[:]) == -1 } -func NewCurrentStaker(txID ids.ID, staker txs.Staker, potentialReward uint64) (*Staker, error) { +func NewCurrentStaker( + txID ids.ID, + staker txs.PostDurangoStaker, + startTime time.Time, + potentialReward uint64, +) (*Staker, error) { publicKey, _, err := staker.PublicKey() if err != nil { return nil, err } - endTime := staker.EndTime() + + stakingDuration := staker.Duration() + endTime := startTime.Add(stakingDuration) return &Staker{ TxID: txID, NodeID: staker.NodeID(), PublicKey: publicKey, SubnetID: staker.SubnetID(), Weight: staker.Weight(), - StartTime: staker.StartTime(), + StartTime: startTime, EndTime: endTime, PotentialReward: potentialReward, NextTime: endTime, diff --git a/vms/platformvm/state/staker_test.go b/vms/platformvm/state/staker_test.go index 747f442e5eda..288cea053b18 100644 --- a/vms/platformvm/state/staker_test.go +++ b/vms/platformvm/state/staker_test.go @@ -144,20 +144,20 @@ func TestNewCurrentStaker(t *testing.T) { subnetID := ids.GenerateTestID() weight := uint64(12345) startTime := time.Now() - endTime := time.Now() + duration := time.Hour + endTime := startTime.Add(duration) potentialReward := uint64(54321) currentPriority := txs.SubnetPermissionedValidatorCurrentPriority stakerTx := txs.NewMockStaker(ctrl) + stakerTx.EXPECT().Duration().Return(duration) stakerTx.EXPECT().NodeID().Return(nodeID) stakerTx.EXPECT().PublicKey().Return(publicKey, true, nil) stakerTx.EXPECT().SubnetID().Return(subnetID) stakerTx.EXPECT().Weight().Return(weight) - stakerTx.EXPECT().StartTime().Return(startTime) - stakerTx.EXPECT().EndTime().Return(endTime) stakerTx.EXPECT().CurrentPriority().Return(currentPriority) - staker, err := NewCurrentStaker(txID, stakerTx, potentialReward) + staker, err := NewCurrentStaker(txID, stakerTx, startTime, potentialReward) require.NotNil(staker) require.NoError(err) require.Equal(txID, staker.TxID) @@ -173,7 +173,7 @@ func TestNewCurrentStaker(t *testing.T) { stakerTx.EXPECT().PublicKey().Return(nil, false, errCustom) - _, err = NewCurrentStaker(txID, stakerTx, potentialReward) + _, err = NewCurrentStaker(txID, stakerTx, startTime, potentialReward) require.ErrorIs(err, errCustom) } diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index fd842f684eae..0384deacefaa 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1324,7 +1324,7 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er return fmt.Errorf("expected tx type *txs.AddValidatorTx but got %T", vdrTx.Unsigned) } - stakeAmount := tx.Validator.Wght + stakeAmount := tx.Weight() stakeDuration := tx.Validator.Duration() currentSupply, err := s.GetCurrentSupply(constants.PrimaryNetworkID) if err != nil { @@ -1341,7 +1341,7 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er return err } - staker, err := NewCurrentStaker(vdrTx.ID(), tx, potentialReward) + staker, err := NewCurrentStaker(vdrTx.ID(), tx, tx.StartTime(), potentialReward) if err != nil { return err } @@ -1447,7 +1447,11 @@ func (s *state) loadCurrentValidators() error { } tx, _, err := s.GetTx(txID) if err != nil { - return err + return fmt.Errorf("failed loading validator transaction txID %v, %w", txID, err) + } + stakerTx, ok := tx.Unsigned.(txs.Staker) + if !ok { + return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } metadataBytes := validatorIt.Value() @@ -1456,16 +1460,16 @@ func (s *state) loadCurrentValidators() error { // Note: we don't provide [LastUpdated] here because we expect it to // always be present on disk. } - if err := parseValidatorMetadata(metadataBytes, metadata); err != nil { + err = parseValidatorMetadata(metadataBytes, metadata) + if err != nil { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) - if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) - } - - staker, err := NewCurrentStaker(txID, stakerTx, metadata.PotentialReward) + staker, err := NewCurrentStaker( + txID, + stakerTx.(txs.PostDurangoStaker), + stakerTx.StartTime(), + metadata.PotentialReward) if err != nil { return err } @@ -1507,7 +1511,12 @@ func (s *state) loadCurrentValidators() error { return err } - staker, err := NewCurrentStaker(txID, stakerTx, metadata.PotentialReward) + staker, err := NewCurrentStaker( + txID, + stakerTx.(txs.PostDurangoStaker), + stakerTx.StartTime(), + metadata.PotentialReward, + ) if err != nil { return err } @@ -1537,6 +1546,11 @@ func (s *state) loadCurrentValidators() error { return err } + stakerTx, ok := tx.Unsigned.(txs.Staker) + if !ok { + return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) + } + metadata := &delegatorMetadata{ txID: txID, } @@ -1545,12 +1559,12 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) - if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) - } - - staker, err := NewCurrentStaker(txID, stakerTx, metadata.PotentialReward) + staker, err := NewCurrentStaker( + txID, + stakerTx.(txs.PostDurangoStaker), + stakerTx.StartTime(), + metadata.PotentialReward, + ) if err != nil { return err } diff --git a/vms/platformvm/txs/add_delegator_tx.go b/vms/platformvm/txs/add_delegator_tx.go index 4f6fbe395b02..4d234b0108aa 100644 --- a/vms/platformvm/txs/add_delegator_tx.go +++ b/vms/platformvm/txs/add_delegator_tx.go @@ -19,7 +19,8 @@ import ( ) var ( - _ DelegatorTx = (*AddDelegatorTx)(nil) + _ DelegatorTx = (*AddDelegatorTx)(nil) + _ PostDurangoStaker = (*AddDelegatorTx)(nil) errDelegatorWeightMismatch = errors.New("delegator weight is not equal to total stake weight") errStakeMustBeAVAX = errors.New("stake must be AVAX") diff --git a/vms/platformvm/txs/add_permissionless_delegator_tx.go b/vms/platformvm/txs/add_permissionless_delegator_tx.go index 43db685d7629..945265d6c91b 100644 --- a/vms/platformvm/txs/add_permissionless_delegator_tx.go +++ b/vms/platformvm/txs/add_permissionless_delegator_tx.go @@ -17,7 +17,10 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) -var _ DelegatorTx = (*AddPermissionlessDelegatorTx)(nil) +var ( + _ DelegatorTx = (*AddPermissionlessDelegatorTx)(nil) + _ PostDurangoStaker = (*AddPermissionlessDelegatorTx)(nil) +) // AddPermissionlessDelegatorTx is an unsigned addPermissionlessDelegatorTx type AddPermissionlessDelegatorTx struct { diff --git a/vms/platformvm/txs/add_permissionless_validator_tx.go b/vms/platformvm/txs/add_permissionless_validator_tx.go index 8f313ae000b9..1ade3f4404e5 100644 --- a/vms/platformvm/txs/add_permissionless_validator_tx.go +++ b/vms/platformvm/txs/add_permissionless_validator_tx.go @@ -21,7 +21,8 @@ import ( ) var ( - _ ValidatorTx = (*AddPermissionlessValidatorTx)(nil) + _ ValidatorTx = (*AddPermissionlessValidatorTx)(nil) + _ PostDurangoStaker = (*AddPermissionlessDelegatorTx)(nil) errEmptyNodeID = errors.New("validator nodeID cannot be empty") errNoStake = errors.New("no stake") diff --git a/vms/platformvm/txs/add_subnet_validator_tx.go b/vms/platformvm/txs/add_subnet_validator_tx.go index 0ac3474e1bd6..3eb8a775c85b 100644 --- a/vms/platformvm/txs/add_subnet_validator_tx.go +++ b/vms/platformvm/txs/add_subnet_validator_tx.go @@ -14,7 +14,8 @@ import ( ) var ( - _ StakerTx = (*AddSubnetValidatorTx)(nil) + _ StakerTx = (*AddSubnetValidatorTx)(nil) + _ PostDurangoStaker = (*AddSubnetValidatorTx)(nil) errAddPrimaryNetworkValidator = errors.New("can't add primary network validator with AddSubnetValidatorTx") ) diff --git a/vms/platformvm/txs/add_validator_tx.go b/vms/platformvm/txs/add_validator_tx.go index be6a93c2e42b..07317b890cab 100644 --- a/vms/platformvm/txs/add_validator_tx.go +++ b/vms/platformvm/txs/add_validator_tx.go @@ -19,7 +19,8 @@ import ( ) var ( - _ ValidatorTx = (*AddValidatorTx)(nil) + _ ValidatorTx = (*AddValidatorTx)(nil) + _ PostDurangoStaker = (*AddValidatorTx)(nil) errTooManyShares = fmt.Errorf("a staker can only require at most %d shares from delegators", reward.PercentDenominator) ) diff --git a/vms/platformvm/txs/executor/advance_time_test.go b/vms/platformvm/txs/executor/advance_time_test.go index 5f9eabe0553c..8cf02aba9123 100644 --- a/vms/platformvm/txs/executor/advance_time_test.go +++ b/vms/platformvm/txs/executor/advance_time_test.go @@ -477,9 +477,11 @@ func TestAdvanceTimeTxRemoveSubnetValidator(t *testing.T) { ) require.NoError(err) + addSubnetValTx := tx.Unsigned.(*txs.AddSubnetValidatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddSubnetValidatorTx), + addSubnetValTx, + addSubnetValTx.StartTime(), 0, ) require.NoError(err) diff --git a/vms/platformvm/txs/executor/proposal_tx_executor_test.go b/vms/platformvm/txs/executor/proposal_tx_executor_test.go index 0044d27a32ea..96f9e5c66b20 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor_test.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor_test.go @@ -46,9 +46,11 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { ) require.NoError(t, err) + addValTx := tx.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(t, err) @@ -74,9 +76,11 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { ) require.NoError(t, err) + addValTx := tx.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(t, err) @@ -402,9 +406,11 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { require.ErrorIs(err, ErrNotValidator) } + addValTx := addDSTx.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( addDSTx.ID(), - addDSTx.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) @@ -555,9 +561,11 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { ) require.NoError(err) + addSubnetValTx := subnetTx.Unsigned.(*txs.AddSubnetValidatorTx) staker, err = state.NewCurrentStaker( subnetTx.ID(), - subnetTx.Unsigned.(*txs.AddSubnetValidatorTx), + addSubnetValTx, + addSubnetValTx.StartTime(), 0, ) require.NoError(err) @@ -684,9 +692,11 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { ) require.NoError(err) + addSubnetValTx := subnetTx.Unsigned.(*txs.AddSubnetValidatorTx) staker, err = state.NewCurrentStaker( subnetTx.ID(), - subnetTx.Unsigned.(*txs.AddSubnetValidatorTx), + addSubnetValTx, + addSubnetValTx.StartTime(), 0, ) require.NoError(err) diff --git a/vms/platformvm/txs/executor/reward_validator_test.go b/vms/platformvm/txs/executor/reward_validator_test.go index 5871b9eef531..4060bbbb9497 100644 --- a/vms/platformvm/txs/executor/reward_validator_test.go +++ b/vms/platformvm/txs/executor/reward_validator_test.go @@ -264,16 +264,20 @@ func TestRewardDelegatorTxExecuteOnCommitPreDelegateeDeferral(t *testing.T) { ) require.NoError(err) + addValTx := vdrTx.Unsigned.(*txs.AddValidatorTx) vdrStaker, err := state.NewCurrentStaker( vdrTx.ID(), - vdrTx.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) + addDelTx := delTx.Unsigned.(*txs.AddDelegatorTx) delStaker, err := state.NewCurrentStaker( delTx.ID(), - delTx.Unsigned.(*txs.AddDelegatorTx), + addDelTx, + addDelTx.StartTime(), 1000000, ) require.NoError(err) @@ -384,18 +388,22 @@ func TestRewardDelegatorTxExecuteOnCommitPostDelegateeDeferral(t *testing.T) { ) require.NoError(err) + addValTx := vdrTx.Unsigned.(*txs.AddValidatorTx) vdrRewardAmt := uint64(2000000) vdrStaker, err := state.NewCurrentStaker( vdrTx.ID(), - vdrTx.Unsigned.(*txs.AddValidatorTx), + addValTx, + time.Unix(int64(vdrStartTime), 0), vdrRewardAmt, ) require.NoError(err) + addDelTx := delTx.Unsigned.(*txs.AddDelegatorTx) delRewardAmt := uint64(1000000) delStaker, err := state.NewCurrentStaker( delTx.ID(), - delTx.Unsigned.(*txs.AddDelegatorTx), + addDelTx, + time.Unix(int64(delStartTime), 0), delRewardAmt, ) require.NoError(err) @@ -599,18 +607,22 @@ func TestRewardDelegatorTxAndValidatorTxExecuteOnCommitPostDelegateeDeferral(t * ) require.NoError(err) + addValTx := vdrTx.Unsigned.(*txs.AddValidatorTx) vdrRewardAmt := uint64(2000000) vdrStaker, err := state.NewCurrentStaker( vdrTx.ID(), - vdrTx.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), vdrRewardAmt, ) require.NoError(err) + addDelTx := delTx.Unsigned.(*txs.AddDelegatorTx) delRewardAmt := uint64(1000000) delStaker, err := state.NewCurrentStaker( delTx.ID(), - delTx.Unsigned.(*txs.AddDelegatorTx), + addDelTx, + time.Unix(int64(delStartTime), 0), delRewardAmt, ) require.NoError(err) @@ -759,16 +771,20 @@ func TestRewardDelegatorTxExecuteOnAbort(t *testing.T) { ) require.NoError(err) + addValTx := vdrTx.Unsigned.(*txs.AddValidatorTx) vdrStaker, err := state.NewCurrentStaker( vdrTx.ID(), - vdrTx.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(err) + addDelTx := delTx.Unsigned.(*txs.AddDelegatorTx) delStaker, err := state.NewCurrentStaker( delTx.ID(), - delTx.Unsigned.(*txs.AddDelegatorTx), + addDelTx, + addDelTx.StartTime(), 1000000, ) require.NoError(err) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 22bab59afd3b..4a643e0abda0 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -291,12 +291,10 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { } txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { return err } - e.State.PutPendingValidator(newStaker) avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) @@ -322,15 +320,12 @@ func (e *StandardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) } txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { return err } - e.State.PutPendingValidator(newStaker) avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) - return nil } @@ -345,15 +340,12 @@ func (e *StandardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { } txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { return err } - e.State.PutPendingDelegator(newStaker) avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) - return nil } @@ -445,12 +437,10 @@ func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionl } txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { return err } - e.State.PutPendingValidator(newStaker) avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) @@ -479,15 +469,12 @@ func (e *StandardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionl } txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { return err } - e.State.PutPendingDelegator(newStaker) avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) - return nil } @@ -545,3 +532,37 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } + +// addStakerFromStakerTx creates the staker and adds it to state. +func (e *StandardTxExecutor) addStakerFromStakerTx( + stakerTx txs.Staker, + chainTime time.Time, +) error { + // Pre Durango fork, stakers were added as pending first, then promoted + // to current when chainTime reaches their start time. + // Post Durango fork, stakers will be immediately marked as current. + // Their start time is current chain time. + + var ( + txID = e.Tx.ID() + staker *state.Staker + err error + ) + + staker, err = state.NewPendingStaker(txID, stakerTx) + if err != nil { + return err + } + + switch priority := staker.Priority; { + case priority.IsCurrentValidator(): + e.State.PutCurrentValidator(staker) + case priority.IsCurrentDelegator(): + e.State.PutCurrentDelegator(staker) + case priority.IsPendingValidator(): + e.State.PutPendingValidator(staker) + case priority.IsPendingDelegator(): + e.State.PutPendingDelegator(staker) + } + return nil +} diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index 5cfc420b1705..f0730897d626 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -120,9 +120,11 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { ) require.NoError(t, err) + addValTx := tx.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(t, err) @@ -148,9 +150,11 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { ) require.NoError(t, err) + addValTx := tx.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddValidatorTx), + addValTx, + addValTx.StartTime(), 0, ) require.NoError(t, err) @@ -485,9 +489,11 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { require.ErrorIs(err, ErrNotValidator) } + addValTx := addDSTx.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( addDSTx.ID(), - addDSTx.Unsigned.(*txs.AddValidatorTx), + addValTx, + dsStartTime, 0, ) require.NoError(err) @@ -621,9 +627,11 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { ) require.NoError(err) + addSubnetValTx := subnetTx.Unsigned.(*txs.AddSubnetValidatorTx) staker, err = state.NewCurrentStaker( subnetTx.ID(), - subnetTx.Unsigned.(*txs.AddSubnetValidatorTx), + addSubnetValTx, + defaultValidateStartTime, 0, ) require.NoError(err) @@ -775,9 +783,11 @@ func TestStandardTxExecutorAddSubnetValidator(t *testing.T) { ) require.NoError(err) + addSubnetValTx := subnetTx.Unsigned.(*txs.AddSubnetValidatorTx) staker, err = state.NewCurrentStaker( subnetTx.ID(), - subnetTx.Unsigned.(*txs.AddSubnetValidatorTx), + addSubnetValTx, + defaultValidateStartTime, 0, ) require.NoError(err) @@ -879,9 +889,11 @@ func TestStandardTxExecutorAddValidator(t *testing.T) { ) require.NoError(err) + addValTx := tx.Unsigned.(*txs.AddValidatorTx) staker, err := state.NewCurrentStaker( tx.ID(), - tx.Unsigned.(*txs.AddValidatorTx), + addValTx, + startTime, 0, ) require.NoError(err) diff --git a/vms/platformvm/txs/staker_tx.go b/vms/platformvm/txs/staker_tx.go index 049d3519375f..ac3e85d7d03e 100644 --- a/vms/platformvm/txs/staker_tx.go +++ b/vms/platformvm/txs/staker_tx.go @@ -42,15 +42,27 @@ type PermissionlessStaker interface { Stake() []*avax.TransferableOutput } -type Staker interface { +type commonStaker interface { SubnetID() ids.ID NodeID() ids.NodeID // PublicKey returns the BLS public key registered by this transaction. If // there was no key registered by this transaction, it will return false. PublicKey() (*bls.PublicKey, bool, error) - StartTime() time.Time - EndTime() time.Time Weight() uint64 - PendingPriority() Priority CurrentPriority() Priority } + +// TODO: Rename this to Staker and Starker below to PreDurangoStaker +// Current naming is only functional to slicing up the whole change +// into smaller parts which are easier to review +type PostDurangoStaker interface { + commonStaker + Duration() time.Duration +} + +type Staker interface { + commonStaker + PendingPriority() Priority + StartTime() time.Time + EndTime() time.Time +} From 88130e48dd536fc060e1276dbcf84f6c8a4fdc91 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 14 Nov 2023 15:45:22 +0100 Subject: [PATCH 02/25] TO BE SQUASHED --- vms/platformvm/state/staker_test.go | 2 +- vms/platformvm/txs/add_delegator_tx.go | 2 +- .../txs/add_permissionless_delegator_tx.go | 2 +- .../txs/add_permissionless_validator_tx.go | 2 +- vms/platformvm/txs/add_subnet_validator_tx.go | 2 +- vms/platformvm/txs/add_validator_tx.go | 2 +- .../txs/executor/standard_tx_executor.go | 15 +-- .../txs/mock_post_durango_staker.go | 126 ++++++++++++++++++ 8 files changed, 138 insertions(+), 15 deletions(-) create mode 100644 vms/platformvm/txs/mock_post_durango_staker.go diff --git a/vms/platformvm/state/staker_test.go b/vms/platformvm/state/staker_test.go index 288cea053b18..479952329fcf 100644 --- a/vms/platformvm/state/staker_test.go +++ b/vms/platformvm/state/staker_test.go @@ -149,7 +149,7 @@ func TestNewCurrentStaker(t *testing.T) { potentialReward := uint64(54321) currentPriority := txs.SubnetPermissionedValidatorCurrentPriority - stakerTx := txs.NewMockStaker(ctrl) + stakerTx := txs.NewMockPostDurangoStaker(ctrl) stakerTx.EXPECT().Duration().Return(duration) stakerTx.EXPECT().NodeID().Return(nodeID) stakerTx.EXPECT().PublicKey().Return(publicKey, true, nil) diff --git a/vms/platformvm/txs/add_delegator_tx.go b/vms/platformvm/txs/add_delegator_tx.go index 4d234b0108aa..aaa86922d0ee 100644 --- a/vms/platformvm/txs/add_delegator_tx.go +++ b/vms/platformvm/txs/add_delegator_tx.go @@ -19,7 +19,7 @@ import ( ) var ( - _ DelegatorTx = (*AddDelegatorTx)(nil) + _ DelegatorTx = (*AddDelegatorTx)(nil) _ PostDurangoStaker = (*AddDelegatorTx)(nil) errDelegatorWeightMismatch = errors.New("delegator weight is not equal to total stake weight") diff --git a/vms/platformvm/txs/add_permissionless_delegator_tx.go b/vms/platformvm/txs/add_permissionless_delegator_tx.go index 945265d6c91b..8cbc5a2d97c5 100644 --- a/vms/platformvm/txs/add_permissionless_delegator_tx.go +++ b/vms/platformvm/txs/add_permissionless_delegator_tx.go @@ -18,7 +18,7 @@ import ( ) var ( - _ DelegatorTx = (*AddPermissionlessDelegatorTx)(nil) + _ DelegatorTx = (*AddPermissionlessDelegatorTx)(nil) _ PostDurangoStaker = (*AddPermissionlessDelegatorTx)(nil) ) diff --git a/vms/platformvm/txs/add_permissionless_validator_tx.go b/vms/platformvm/txs/add_permissionless_validator_tx.go index 1ade3f4404e5..1961f30dc303 100644 --- a/vms/platformvm/txs/add_permissionless_validator_tx.go +++ b/vms/platformvm/txs/add_permissionless_validator_tx.go @@ -21,7 +21,7 @@ import ( ) var ( - _ ValidatorTx = (*AddPermissionlessValidatorTx)(nil) + _ ValidatorTx = (*AddPermissionlessValidatorTx)(nil) _ PostDurangoStaker = (*AddPermissionlessDelegatorTx)(nil) errEmptyNodeID = errors.New("validator nodeID cannot be empty") diff --git a/vms/platformvm/txs/add_subnet_validator_tx.go b/vms/platformvm/txs/add_subnet_validator_tx.go index 3eb8a775c85b..1230f62f627b 100644 --- a/vms/platformvm/txs/add_subnet_validator_tx.go +++ b/vms/platformvm/txs/add_subnet_validator_tx.go @@ -14,7 +14,7 @@ import ( ) var ( - _ StakerTx = (*AddSubnetValidatorTx)(nil) + _ StakerTx = (*AddSubnetValidatorTx)(nil) _ PostDurangoStaker = (*AddSubnetValidatorTx)(nil) errAddPrimaryNetworkValidator = errors.New("can't add primary network validator with AddSubnetValidatorTx") diff --git a/vms/platformvm/txs/add_validator_tx.go b/vms/platformvm/txs/add_validator_tx.go index 07317b890cab..359efc3a70c8 100644 --- a/vms/platformvm/txs/add_validator_tx.go +++ b/vms/platformvm/txs/add_validator_tx.go @@ -19,7 +19,7 @@ import ( ) var ( - _ ValidatorTx = (*AddValidatorTx)(nil) + _ ValidatorTx = (*AddValidatorTx)(nil) _ PostDurangoStaker = (*AddValidatorTx)(nil) errTooManyShares = fmt.Errorf("a staker can only require at most %d shares from delegators", reward.PercentDenominator) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 4a643e0abda0..d4976dc9ca06 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -291,7 +291,7 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { } txID := e.Tx.ID() - if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } @@ -320,7 +320,7 @@ func (e *StandardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) } txID := e.Tx.ID() - if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } @@ -340,7 +340,7 @@ func (e *StandardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { } txID := e.Tx.ID() - if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } @@ -437,7 +437,7 @@ func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionl } txID := e.Tx.ID() - if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } @@ -469,7 +469,7 @@ func (e *StandardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionl } txID := e.Tx.ID() - if err := e.addStakerFromStakerTx(tx, e.State.GetTimestamp()); err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } @@ -534,10 +534,7 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { } // addStakerFromStakerTx creates the staker and adds it to state. -func (e *StandardTxExecutor) addStakerFromStakerTx( - stakerTx txs.Staker, - chainTime time.Time, -) error { +func (e *StandardTxExecutor) addStakerFromStakerTx(stakerTx txs.Staker) error { // Pre Durango fork, stakers were added as pending first, then promoted // to current when chainTime reaches their start time. // Post Durango fork, stakers will be immediately marked as current. diff --git a/vms/platformvm/txs/mock_post_durango_staker.go b/vms/platformvm/txs/mock_post_durango_staker.go new file mode 100644 index 000000000000..be13403099a5 --- /dev/null +++ b/vms/platformvm/txs/mock_post_durango_staker.go @@ -0,0 +1,126 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ava-labs/avalanchego/vms/platformvm/txs (interfaces: Staker) + +// Package txs is a generated GoMock package. +package txs + +import ( + reflect "reflect" + time "time" + + ids "github.com/ava-labs/avalanchego/ids" + bls "github.com/ava-labs/avalanchego/utils/crypto/bls" + gomock "go.uber.org/mock/gomock" +) + +// MockPostDurangoStaker is a mock of Staker interface. +type MockPostDurangoStaker struct { + ctrl *gomock.Controller + recorder *MockPostDurangoStakerMockRecorder +} + +// MockPostDurangoStakerMockRecorder is the mock recorder for MockStaker. +type MockPostDurangoStakerMockRecorder struct { + mock *MockPostDurangoStaker +} + +// NewMockPostDurangoStaker creates a new mock instance. +func NewMockPostDurangoStaker(ctrl *gomock.Controller) *MockPostDurangoStaker { + mock := &MockPostDurangoStaker{ctrl: ctrl} + mock.recorder = &MockPostDurangoStakerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPostDurangoStaker) EXPECT() *MockPostDurangoStakerMockRecorder { + return m.recorder +} + +// CurrentPriority mocks base method. +func (m *MockPostDurangoStaker) CurrentPriority() Priority { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CurrentPriority") + ret0, _ := ret[0].(Priority) + return ret0 +} + +// CurrentPriority indicates an expected call of CurrentPriority. +func (mr *MockPostDurangoStakerMockRecorder) CurrentPriority() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentPriority", reflect.TypeOf((*MockPostDurangoStaker)(nil).CurrentPriority)) +} + +// Duration mocks base method. +func (m *MockPostDurangoStaker) Duration() time.Duration { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Duration") + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +// EndTime indicates an expected call of EndTime. +func (mr *MockPostDurangoStakerMockRecorder) Duration() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Duration", reflect.TypeOf((*MockPostDurangoStaker)(nil).Duration)) +} + +// NodeID mocks base method. +func (m *MockPostDurangoStaker) NodeID() ids.NodeID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NodeID") + ret0, _ := ret[0].(ids.NodeID) + return ret0 +} + +// NodeID indicates an expected call of NodeID. +func (mr *MockPostDurangoStakerMockRecorder) NodeID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeID", reflect.TypeOf((*MockPostDurangoStaker)(nil).NodeID)) +} + +// PublicKey mocks base method. +func (m *MockPostDurangoStaker) PublicKey() (*bls.PublicKey, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PublicKey") + ret0, _ := ret[0].(*bls.PublicKey) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// PublicKey indicates an expected call of PublicKey. +func (mr *MockPostDurangoStakerMockRecorder) PublicKey() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublicKey", reflect.TypeOf((*MockPostDurangoStaker)(nil).PublicKey)) +} + +// SubnetID mocks base method. +func (m *MockPostDurangoStaker) SubnetID() ids.ID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubnetID") + ret0, _ := ret[0].(ids.ID) + return ret0 +} + +// SubnetID indicates an expected call of SubnetID. +func (mr *MockPostDurangoStakerMockRecorder) SubnetID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubnetID", reflect.TypeOf((*MockPostDurangoStaker)(nil).SubnetID)) +} + +// Weight mocks base method. +func (m *MockPostDurangoStaker) Weight() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Weight") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// Weight indicates an expected call of Weight. +func (mr *MockPostDurangoStakerMockRecorder) Weight() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Weight", reflect.TypeOf((*MockPostDurangoStaker)(nil).Weight)) +} From acc1517dfa09fe3db5ec32141e4214f03e86fb89 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 14 Nov 2023 17:03:12 +0100 Subject: [PATCH 03/25] nit --- vms/platformvm/block/executor/proposal_block_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vms/platformvm/block/executor/proposal_block_test.go b/vms/platformvm/block/executor/proposal_block_test.go index 9436687510c3..2f0cc49651e3 100644 --- a/vms/platformvm/block/executor/proposal_block_test.go +++ b/vms/platformvm/block/executor/proposal_block_test.go @@ -596,7 +596,7 @@ func TestBanffProposalBlockUpdateStakers(t *testing.T) { for _, subStaker := range test.subnetStakers { tx, err := env.txBuilder.NewAddSubnetValidatorTx( - env.config.MaxValidatorStake, // Weight + 10, // Weight uint64(subStaker.startTime.Unix()), uint64(subStaker.endTime.Unix()), subStaker.nodeID, // validator ID From 19a8318fba86be266446e4ae21742bf4991a2213 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 15 Nov 2023 14:33:52 +0100 Subject: [PATCH 04/25] nit --- .../txs/executor/standard_tx_executor.go | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index d4976dc9ca06..780dd4996efa 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -290,11 +290,11 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { return err } - txID := e.Tx.ID() if err := e.addStakerFromStakerTx(tx); err != nil { return err } + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) @@ -319,13 +319,12 @@ func (e *StandardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) return err } - txID := e.Tx.ID() if err := e.addStakerFromStakerTx(tx); err != nil { return err } avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -339,13 +338,12 @@ func (e *StandardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { return err } - txID := e.Tx.ID() if err := e.addStakerFromStakerTx(tx); err != nil { return err } avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -436,11 +434,11 @@ func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionl return err } - txID := e.Tx.ID() if err := e.addStakerFromStakerTx(tx); err != nil { return err } + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) @@ -468,13 +466,12 @@ func (e *StandardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionl return err } - txID := e.Tx.ID() if err := e.addStakerFromStakerTx(tx); err != nil { return err } avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -498,7 +495,6 @@ func (e *StandardTxExecutor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwn txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) - return nil } @@ -535,9 +531,9 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { // addStakerFromStakerTx creates the staker and adds it to state. func (e *StandardTxExecutor) addStakerFromStakerTx(stakerTx txs.Staker) error { - // Pre Durango fork, stakers were added as pending first, then promoted + // Pre Durango fork, stakers are added as pending first, then promoted // to current when chainTime reaches their start time. - // Post Durango fork, stakers will be immediately marked as current. + // Post Durango fork, stakers are immediately marked as current. // Their start time is current chain time. var ( From b213740e7b6a968c088ee6370e9268f3b3c728e2 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 15 Nov 2023 15:56:33 +0100 Subject: [PATCH 05/25] updated PR to acp proposal --- vms/platformvm/state/staker.go | 7 +- vms/platformvm/state/staker_test.go | 9 +- vms/platformvm/state/state.go | 22 +-- vms/platformvm/txs/add_delegator_tx.go | 4 +- .../txs/add_permissionless_delegator_tx.go | 4 +- .../txs/add_permissionless_validator_tx.go | 4 +- vms/platformvm/txs/add_subnet_validator_tx.go | 4 +- vms/platformvm/txs/add_validator_tx.go | 4 +- .../txs/executor/standard_tx_executor.go | 2 +- vms/platformvm/txs/mempool/mempool.go | 2 +- .../txs/mock_post_durango_staker.go | 126 -------------- vms/platformvm/txs/mock_pre_durango_staker.go | 154 ++++++++++++++++++ vms/platformvm/txs/mock_staker.go | 28 ---- vms/platformvm/txs/staker_tx.go | 18 +- vms/platformvm/txs/txheap/by_end_time.go | 6 +- vms/platformvm/txs/txheap/by_start_time.go | 6 +- vms/platformvm/validator_set_property_test.go | 2 +- 17 files changed, 196 insertions(+), 206 deletions(-) delete mode 100644 vms/platformvm/txs/mock_post_durango_staker.go create mode 100644 vms/platformvm/txs/mock_pre_durango_staker.go diff --git a/vms/platformvm/state/staker.go b/vms/platformvm/state/staker.go index 5cbabb42920d..61971163de97 100644 --- a/vms/platformvm/state/staker.go +++ b/vms/platformvm/state/staker.go @@ -85,7 +85,7 @@ func (s *Staker) Less(than *Staker) bool { func NewCurrentStaker( txID ids.ID, - staker txs.PostDurangoStaker, + staker txs.Staker, startTime time.Time, potentialReward uint64, ) (*Staker, error) { @@ -94,8 +94,7 @@ func NewCurrentStaker( return nil, err } - stakingDuration := staker.Duration() - endTime := startTime.Add(stakingDuration) + endTime := staker.EndTime() return &Staker{ TxID: txID, NodeID: staker.NodeID(), @@ -110,7 +109,7 @@ func NewCurrentStaker( }, nil } -func NewPendingStaker(txID ids.ID, staker txs.Staker) (*Staker, error) { +func NewPendingStaker(txID ids.ID, staker txs.PreDurangoStaker) (*Staker, error) { publicKey, _, err := staker.PublicKey() if err != nil { return nil, err diff --git a/vms/platformvm/state/staker_test.go b/vms/platformvm/state/staker_test.go index 479952329fcf..85deccb52776 100644 --- a/vms/platformvm/state/staker_test.go +++ b/vms/platformvm/state/staker_test.go @@ -144,13 +144,12 @@ func TestNewCurrentStaker(t *testing.T) { subnetID := ids.GenerateTestID() weight := uint64(12345) startTime := time.Now() - duration := time.Hour - endTime := startTime.Add(duration) + endTime := startTime.Add(time.Hour) potentialReward := uint64(54321) currentPriority := txs.SubnetPermissionedValidatorCurrentPriority - stakerTx := txs.NewMockPostDurangoStaker(ctrl) - stakerTx.EXPECT().Duration().Return(duration) + stakerTx := txs.NewMockStaker(ctrl) + stakerTx.EXPECT().EndTime().Return(endTime) stakerTx.EXPECT().NodeID().Return(nodeID) stakerTx.EXPECT().PublicKey().Return(publicKey, true, nil) stakerTx.EXPECT().SubnetID().Return(subnetID) @@ -192,7 +191,7 @@ func TestNewPendingStaker(t *testing.T) { endTime := time.Now() pendingPriority := txs.SubnetPermissionedValidatorPendingPriority - stakerTx := txs.NewMockStaker(ctrl) + stakerTx := txs.NewMockPreDurangoStaker(ctrl) stakerTx.EXPECT().NodeID().Return(nodeID) stakerTx.EXPECT().PublicKey().Return(publicKey, true, nil) stakerTx.EXPECT().SubnetID().Return(subnetID) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 0384deacefaa..7c05b941199c 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1460,15 +1460,14 @@ func (s *state) loadCurrentValidators() error { // Note: we don't provide [LastUpdated] here because we expect it to // always be present on disk. } - err = parseValidatorMetadata(metadataBytes, metadata) - if err != nil { + if err := parseValidatorMetadata(metadataBytes, metadata); err != nil { return err } staker, err := NewCurrentStaker( txID, - stakerTx.(txs.PostDurangoStaker), - stakerTx.StartTime(), + stakerTx, + stakerTx.(txs.PreDurangoStaker).StartTime(), metadata.PotentialReward) if err != nil { return err @@ -1501,11 +1500,12 @@ func (s *state) loadCurrentValidators() error { } metadataBytes := subnetValidatorIt.Value() + startTime := stakerTx.(txs.PreDurangoStaker).StartTime() metadata := &validatorMetadata{ txID: txID, // use the start time as the fallback value // in case it's not stored in the database - LastUpdated: uint64(stakerTx.StartTime().Unix()), + LastUpdated: uint64(startTime.Unix()), } if err := parseValidatorMetadata(metadataBytes, metadata); err != nil { return err @@ -1513,8 +1513,8 @@ func (s *state) loadCurrentValidators() error { staker, err := NewCurrentStaker( txID, - stakerTx.(txs.PostDurangoStaker), - stakerTx.StartTime(), + stakerTx, + startTime, metadata.PotentialReward, ) if err != nil { @@ -1561,8 +1561,8 @@ func (s *state) loadCurrentValidators() error { staker, err := NewCurrentStaker( txID, - stakerTx.(txs.PostDurangoStaker), - stakerTx.StartTime(), + stakerTx, + stakerTx.(txs.PreDurangoStaker).StartTime(), metadata.PotentialReward, ) if err != nil { @@ -1608,7 +1608,7 @@ func (s *state) loadPendingValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) + stakerTx, ok := tx.Unsigned.(txs.PreDurangoStaker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } @@ -1643,7 +1643,7 @@ func (s *state) loadPendingValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) + stakerTx, ok := tx.Unsigned.(txs.PreDurangoStaker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } diff --git a/vms/platformvm/txs/add_delegator_tx.go b/vms/platformvm/txs/add_delegator_tx.go index aaa86922d0ee..d05b8753eab8 100644 --- a/vms/platformvm/txs/add_delegator_tx.go +++ b/vms/platformvm/txs/add_delegator_tx.go @@ -19,8 +19,8 @@ import ( ) var ( - _ DelegatorTx = (*AddDelegatorTx)(nil) - _ PostDurangoStaker = (*AddDelegatorTx)(nil) + _ DelegatorTx = (*AddDelegatorTx)(nil) + _ PreDurangoStaker = (*AddDelegatorTx)(nil) errDelegatorWeightMismatch = errors.New("delegator weight is not equal to total stake weight") errStakeMustBeAVAX = errors.New("stake must be AVAX") diff --git a/vms/platformvm/txs/add_permissionless_delegator_tx.go b/vms/platformvm/txs/add_permissionless_delegator_tx.go index 8cbc5a2d97c5..7d2fe407f7e8 100644 --- a/vms/platformvm/txs/add_permissionless_delegator_tx.go +++ b/vms/platformvm/txs/add_permissionless_delegator_tx.go @@ -18,8 +18,8 @@ import ( ) var ( - _ DelegatorTx = (*AddPermissionlessDelegatorTx)(nil) - _ PostDurangoStaker = (*AddPermissionlessDelegatorTx)(nil) + _ DelegatorTx = (*AddPermissionlessDelegatorTx)(nil) + _ PreDurangoStaker = (*AddPermissionlessDelegatorTx)(nil) ) // AddPermissionlessDelegatorTx is an unsigned addPermissionlessDelegatorTx diff --git a/vms/platformvm/txs/add_permissionless_validator_tx.go b/vms/platformvm/txs/add_permissionless_validator_tx.go index 1961f30dc303..9094919550d0 100644 --- a/vms/platformvm/txs/add_permissionless_validator_tx.go +++ b/vms/platformvm/txs/add_permissionless_validator_tx.go @@ -21,8 +21,8 @@ import ( ) var ( - _ ValidatorTx = (*AddPermissionlessValidatorTx)(nil) - _ PostDurangoStaker = (*AddPermissionlessDelegatorTx)(nil) + _ ValidatorTx = (*AddPermissionlessValidatorTx)(nil) + _ PreDurangoStaker = (*AddPermissionlessDelegatorTx)(nil) errEmptyNodeID = errors.New("validator nodeID cannot be empty") errNoStake = errors.New("no stake") diff --git a/vms/platformvm/txs/add_subnet_validator_tx.go b/vms/platformvm/txs/add_subnet_validator_tx.go index 1230f62f627b..457070f87041 100644 --- a/vms/platformvm/txs/add_subnet_validator_tx.go +++ b/vms/platformvm/txs/add_subnet_validator_tx.go @@ -14,8 +14,8 @@ import ( ) var ( - _ StakerTx = (*AddSubnetValidatorTx)(nil) - _ PostDurangoStaker = (*AddSubnetValidatorTx)(nil) + _ StakerTx = (*AddSubnetValidatorTx)(nil) + _ PreDurangoStaker = (*AddSubnetValidatorTx)(nil) errAddPrimaryNetworkValidator = errors.New("can't add primary network validator with AddSubnetValidatorTx") ) diff --git a/vms/platformvm/txs/add_validator_tx.go b/vms/platformvm/txs/add_validator_tx.go index 359efc3a70c8..906e9a63b55d 100644 --- a/vms/platformvm/txs/add_validator_tx.go +++ b/vms/platformvm/txs/add_validator_tx.go @@ -19,8 +19,8 @@ import ( ) var ( - _ ValidatorTx = (*AddValidatorTx)(nil) - _ PostDurangoStaker = (*AddValidatorTx)(nil) + _ ValidatorTx = (*AddValidatorTx)(nil) + _ PreDurangoStaker = (*AddValidatorTx)(nil) errTooManyShares = fmt.Errorf("a staker can only require at most %d shares from delegators", reward.PercentDenominator) ) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 780dd4996efa..5c6745c2dc7e 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -530,7 +530,7 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { } // addStakerFromStakerTx creates the staker and adds it to state. -func (e *StandardTxExecutor) addStakerFromStakerTx(stakerTx txs.Staker) error { +func (e *StandardTxExecutor) addStakerFromStakerTx(stakerTx txs.PreDurangoStaker) error { // Pre Durango fork, stakers are added as pending first, then promoted // to current when chainTime reaches their start time. // Post Durango fork, stakers are immediately marked as current. diff --git a/vms/platformvm/txs/mempool/mempool.go b/vms/platformvm/txs/mempool/mempool.go index 91b547cf5414..d836604d2c02 100644 --- a/vms/platformvm/txs/mempool/mempool.go +++ b/vms/platformvm/txs/mempool/mempool.go @@ -316,7 +316,7 @@ func DropExpiredStakerTxs(mempool Mempool, minStartTime time.Time) []ids.ID { for mempool.HasStakerTx() { tx := mempool.PeekStakerTx() - startTime := tx.Unsigned.(txs.Staker).StartTime() + startTime := tx.Unsigned.(txs.PreDurangoStaker).StartTime() if !startTime.Before(minStartTime) { // The next proposal tx in the mempool starts sufficiently far in // the future. diff --git a/vms/platformvm/txs/mock_post_durango_staker.go b/vms/platformvm/txs/mock_post_durango_staker.go deleted file mode 100644 index be13403099a5..000000000000 --- a/vms/platformvm/txs/mock_post_durango_staker.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ava-labs/avalanchego/vms/platformvm/txs (interfaces: Staker) - -// Package txs is a generated GoMock package. -package txs - -import ( - reflect "reflect" - time "time" - - ids "github.com/ava-labs/avalanchego/ids" - bls "github.com/ava-labs/avalanchego/utils/crypto/bls" - gomock "go.uber.org/mock/gomock" -) - -// MockPostDurangoStaker is a mock of Staker interface. -type MockPostDurangoStaker struct { - ctrl *gomock.Controller - recorder *MockPostDurangoStakerMockRecorder -} - -// MockPostDurangoStakerMockRecorder is the mock recorder for MockStaker. -type MockPostDurangoStakerMockRecorder struct { - mock *MockPostDurangoStaker -} - -// NewMockPostDurangoStaker creates a new mock instance. -func NewMockPostDurangoStaker(ctrl *gomock.Controller) *MockPostDurangoStaker { - mock := &MockPostDurangoStaker{ctrl: ctrl} - mock.recorder = &MockPostDurangoStakerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockPostDurangoStaker) EXPECT() *MockPostDurangoStakerMockRecorder { - return m.recorder -} - -// CurrentPriority mocks base method. -func (m *MockPostDurangoStaker) CurrentPriority() Priority { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CurrentPriority") - ret0, _ := ret[0].(Priority) - return ret0 -} - -// CurrentPriority indicates an expected call of CurrentPriority. -func (mr *MockPostDurangoStakerMockRecorder) CurrentPriority() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentPriority", reflect.TypeOf((*MockPostDurangoStaker)(nil).CurrentPriority)) -} - -// Duration mocks base method. -func (m *MockPostDurangoStaker) Duration() time.Duration { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Duration") - ret0, _ := ret[0].(time.Duration) - return ret0 -} - -// EndTime indicates an expected call of EndTime. -func (mr *MockPostDurangoStakerMockRecorder) Duration() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Duration", reflect.TypeOf((*MockPostDurangoStaker)(nil).Duration)) -} - -// NodeID mocks base method. -func (m *MockPostDurangoStaker) NodeID() ids.NodeID { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NodeID") - ret0, _ := ret[0].(ids.NodeID) - return ret0 -} - -// NodeID indicates an expected call of NodeID. -func (mr *MockPostDurangoStakerMockRecorder) NodeID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeID", reflect.TypeOf((*MockPostDurangoStaker)(nil).NodeID)) -} - -// PublicKey mocks base method. -func (m *MockPostDurangoStaker) PublicKey() (*bls.PublicKey, bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PublicKey") - ret0, _ := ret[0].(*bls.PublicKey) - ret1, _ := ret[1].(bool) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// PublicKey indicates an expected call of PublicKey. -func (mr *MockPostDurangoStakerMockRecorder) PublicKey() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublicKey", reflect.TypeOf((*MockPostDurangoStaker)(nil).PublicKey)) -} - -// SubnetID mocks base method. -func (m *MockPostDurangoStaker) SubnetID() ids.ID { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SubnetID") - ret0, _ := ret[0].(ids.ID) - return ret0 -} - -// SubnetID indicates an expected call of SubnetID. -func (mr *MockPostDurangoStakerMockRecorder) SubnetID() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubnetID", reflect.TypeOf((*MockPostDurangoStaker)(nil).SubnetID)) -} - -// Weight mocks base method. -func (m *MockPostDurangoStaker) Weight() uint64 { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Weight") - ret0, _ := ret[0].(uint64) - return ret0 -} - -// Weight indicates an expected call of Weight. -func (mr *MockPostDurangoStakerMockRecorder) Weight() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Weight", reflect.TypeOf((*MockPostDurangoStaker)(nil).Weight)) -} diff --git a/vms/platformvm/txs/mock_pre_durango_staker.go b/vms/platformvm/txs/mock_pre_durango_staker.go new file mode 100644 index 000000000000..75c01e66fb39 --- /dev/null +++ b/vms/platformvm/txs/mock_pre_durango_staker.go @@ -0,0 +1,154 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ava-labs/avalanchego/vms/platformvm/txs (interfaces: Staker) + +// Package txs is a generated GoMock package. +package txs + +import ( + reflect "reflect" + time "time" + + ids "github.com/ava-labs/avalanchego/ids" + bls "github.com/ava-labs/avalanchego/utils/crypto/bls" + gomock "go.uber.org/mock/gomock" +) + +// MockPreDurangoStaker is a mock of Staker interface. +type MockPreDurangoStaker struct { + ctrl *gomock.Controller + recorder *MockPreDurangoStakerMockRecorder +} + +// MockPreDurangoStakerMockRecorder is the mock recorder for MockStaker. +type MockPreDurangoStakerMockRecorder struct { + mock *MockPreDurangoStaker +} + +// NewMockPreDurangoStaker creates a new mock instance. +func NewMockPreDurangoStaker(ctrl *gomock.Controller) *MockPreDurangoStaker { + mock := &MockPreDurangoStaker{ctrl: ctrl} + mock.recorder = &MockPreDurangoStakerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPreDurangoStaker) EXPECT() *MockPreDurangoStakerMockRecorder { + return m.recorder +} + +// CurrentPriority mocks base method. +func (m *MockPreDurangoStaker) CurrentPriority() Priority { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CurrentPriority") + ret0, _ := ret[0].(Priority) + return ret0 +} + +// CurrentPriority indicates an expected call of CurrentPriority. +func (mr *MockPreDurangoStakerMockRecorder) CurrentPriority() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentPriority", reflect.TypeOf((*MockPreDurangoStaker)(nil).CurrentPriority)) +} + +// EndTime mocks base method. +func (m *MockPreDurangoStaker) EndTime() time.Time { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EndTime") + ret0, _ := ret[0].(time.Time) + return ret0 +} + +// EndTime indicates an expected call of EndTime. +func (mr *MockPreDurangoStakerMockRecorder) EndTime() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EndTime", reflect.TypeOf((*MockPreDurangoStaker)(nil).EndTime)) +} + +// NodeID mocks base method. +func (m *MockPreDurangoStaker) NodeID() ids.NodeID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NodeID") + ret0, _ := ret[0].(ids.NodeID) + return ret0 +} + +// NodeID indicates an expected call of NodeID. +func (mr *MockPreDurangoStakerMockRecorder) NodeID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeID", reflect.TypeOf((*MockPreDurangoStaker)(nil).NodeID)) +} + +// PendingPriority mocks base method. +func (m *MockPreDurangoStaker) PendingPriority() Priority { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PendingPriority") + ret0, _ := ret[0].(Priority) + return ret0 +} + +// PendingPriority indicates an expected call of PendingPriority. +func (mr *MockPreDurangoStakerMockRecorder) PendingPriority() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PendingPriority", reflect.TypeOf((*MockPreDurangoStaker)(nil).PendingPriority)) +} + +// PublicKey mocks base method. +func (m *MockPreDurangoStaker) PublicKey() (*bls.PublicKey, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PublicKey") + ret0, _ := ret[0].(*bls.PublicKey) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// PublicKey indicates an expected call of PublicKey. +func (mr *MockPreDurangoStakerMockRecorder) PublicKey() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublicKey", reflect.TypeOf((*MockPreDurangoStaker)(nil).PublicKey)) +} + +// StartTime mocks base method. +func (m *MockPreDurangoStaker) StartTime() time.Time { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StartTime") + ret0, _ := ret[0].(time.Time) + return ret0 +} + +// StartTime indicates an expected call of StartTime. +func (mr *MockPreDurangoStakerMockRecorder) StartTime() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartTime", reflect.TypeOf((*MockPreDurangoStaker)(nil).StartTime)) +} + +// SubnetID mocks base method. +func (m *MockPreDurangoStaker) SubnetID() ids.ID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubnetID") + ret0, _ := ret[0].(ids.ID) + return ret0 +} + +// SubnetID indicates an expected call of SubnetID. +func (mr *MockPreDurangoStakerMockRecorder) SubnetID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubnetID", reflect.TypeOf((*MockPreDurangoStaker)(nil).SubnetID)) +} + +// Weight mocks base method. +func (m *MockPreDurangoStaker) Weight() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Weight") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// Weight indicates an expected call of Weight. +func (mr *MockPreDurangoStakerMockRecorder) Weight() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Weight", reflect.TypeOf((*MockPreDurangoStaker)(nil).Weight)) +} diff --git a/vms/platformvm/txs/mock_staker.go b/vms/platformvm/txs/mock_staker.go index e01ca66cf9e3..f74c2534ca39 100644 --- a/vms/platformvm/txs/mock_staker.go +++ b/vms/platformvm/txs/mock_staker.go @@ -81,20 +81,6 @@ func (mr *MockStakerMockRecorder) NodeID() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeID", reflect.TypeOf((*MockStaker)(nil).NodeID)) } -// PendingPriority mocks base method. -func (m *MockStaker) PendingPriority() Priority { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PendingPriority") - ret0, _ := ret[0].(Priority) - return ret0 -} - -// PendingPriority indicates an expected call of PendingPriority. -func (mr *MockStakerMockRecorder) PendingPriority() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PendingPriority", reflect.TypeOf((*MockStaker)(nil).PendingPriority)) -} - // PublicKey mocks base method. func (m *MockStaker) PublicKey() (*bls.PublicKey, bool, error) { m.ctrl.T.Helper() @@ -111,20 +97,6 @@ func (mr *MockStakerMockRecorder) PublicKey() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublicKey", reflect.TypeOf((*MockStaker)(nil).PublicKey)) } -// StartTime mocks base method. -func (m *MockStaker) StartTime() time.Time { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StartTime") - ret0, _ := ret[0].(time.Time) - return ret0 -} - -// StartTime indicates an expected call of StartTime. -func (mr *MockStakerMockRecorder) StartTime() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartTime", reflect.TypeOf((*MockStaker)(nil).StartTime)) -} - // SubnetID mocks base method. func (m *MockStaker) SubnetID() ids.ID { m.ctrl.T.Helper() diff --git a/vms/platformvm/txs/staker_tx.go b/vms/platformvm/txs/staker_tx.go index ac3e85d7d03e..a8b0842540a7 100644 --- a/vms/platformvm/txs/staker_tx.go +++ b/vms/platformvm/txs/staker_tx.go @@ -42,27 +42,19 @@ type PermissionlessStaker interface { Stake() []*avax.TransferableOutput } -type commonStaker interface { +type Staker interface { SubnetID() ids.ID NodeID() ids.NodeID // PublicKey returns the BLS public key registered by this transaction. If // there was no key registered by this transaction, it will return false. PublicKey() (*bls.PublicKey, bool, error) + EndTime() time.Time Weight() uint64 CurrentPriority() Priority } -// TODO: Rename this to Staker and Starker below to PreDurangoStaker -// Current naming is only functional to slicing up the whole change -// into smaller parts which are easier to review -type PostDurangoStaker interface { - commonStaker - Duration() time.Duration -} - -type Staker interface { - commonStaker - PendingPriority() Priority +type PreDurangoStaker interface { + Staker StartTime() time.Time - EndTime() time.Time + PendingPriority() Priority } diff --git a/vms/platformvm/txs/txheap/by_end_time.go b/vms/platformvm/txs/txheap/by_end_time.go index ba144448919d..122f24f10c5a 100644 --- a/vms/platformvm/txs/txheap/by_end_time.go +++ b/vms/platformvm/txs/txheap/by_end_time.go @@ -21,8 +21,8 @@ func NewByEndTime() TimedHeap { return &byEndTime{ txHeap: txHeap{ heap: heap.NewMap[ids.ID, heapTx](func(a, b heapTx) bool { - aTime := a.tx.Unsigned.(txs.Staker).EndTime() - bTime := b.tx.Unsigned.(txs.Staker).EndTime() + aTime := a.tx.Unsigned.(txs.PreDurangoStaker).EndTime() + bTime := b.tx.Unsigned.(txs.PreDurangoStaker).EndTime() return aTime.Before(bTime) }), }, @@ -30,5 +30,5 @@ func NewByEndTime() TimedHeap { } func (h *byEndTime) Timestamp() time.Time { - return h.Peek().Unsigned.(txs.Staker).EndTime() + return h.Peek().Unsigned.(txs.PreDurangoStaker).EndTime() } diff --git a/vms/platformvm/txs/txheap/by_start_time.go b/vms/platformvm/txs/txheap/by_start_time.go index f19c28d76436..d755f600c548 100644 --- a/vms/platformvm/txs/txheap/by_start_time.go +++ b/vms/platformvm/txs/txheap/by_start_time.go @@ -27,8 +27,8 @@ func NewByStartTime() TimedHeap { return &byStartTime{ txHeap: txHeap{ heap: heap.NewMap[ids.ID, heapTx](func(a, b heapTx) bool { - aTime := a.tx.Unsigned.(txs.Staker).StartTime() - bTime := b.tx.Unsigned.(txs.Staker).StartTime() + aTime := a.tx.Unsigned.(txs.PreDurangoStaker).StartTime() + bTime := b.tx.Unsigned.(txs.PreDurangoStaker).StartTime() return aTime.Before(bTime) }), }, @@ -36,5 +36,5 @@ func NewByStartTime() TimedHeap { } func (h *byStartTime) Timestamp() time.Time { - return h.Peek().Unsigned.(txs.Staker).StartTime() + return h.Peek().Unsigned.(txs.PreDurangoStaker).StartTime() } diff --git a/vms/platformvm/validator_set_property_test.go b/vms/platformvm/validator_set_property_test.go index be3962f36701..0198c1c03bec 100644 --- a/vms/platformvm/validator_set_property_test.go +++ b/vms/platformvm/validator_set_property_test.go @@ -373,7 +373,7 @@ func addPrimaryValidatorWithoutBLSKey(vm *VM, data *validatorInputData) (*state. } func internalAddValidator(vm *VM, signedTx *txs.Tx) (*state.Staker, error) { - stakerTx := signedTx.Unsigned.(txs.StakerTx) + stakerTx := signedTx.Unsigned.(txs.PreDurangoStaker) if err := vm.Builder.AddUnverifiedTx(signedTx); err != nil { return nil, fmt.Errorf("could not add tx to mempool: %w", err) } From 6079eb0485d4cbde60e9c8b060d5c3340060b2bc Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 16 Nov 2023 13:54:36 +0100 Subject: [PATCH 06/25] introduced pre durango staker tx --- vms/platformvm/state/staker.go | 4 +- vms/platformvm/state/staker_test.go | 6 +- vms/platformvm/state/state.go | 32 ++-- vms/platformvm/txs/add_delegator_tx.go | 3 +- .../txs/add_permissionless_delegator_tx.go | 5 +- .../txs/add_permissionless_validator_tx.go | 3 +- vms/platformvm/txs/add_subnet_validator_tx.go | 3 +- vms/platformvm/txs/add_validator_tx.go | 3 +- .../txs/executor/standard_tx_executor.go | 63 ++++--- vms/platformvm/txs/mempool/mempool.go | 2 +- vms/platformvm/txs/mock_scheduled_staker.go | 154 ++++++++++++++++++ vms/platformvm/txs/mock_staker.go | 28 ---- vms/platformvm/txs/staker_tx.go | 8 +- vms/platformvm/txs/txheap/by_end_time.go | 6 +- vms/platformvm/txs/txheap/by_start_time.go | 6 +- vms/platformvm/validator_set_property_test.go | 2 +- 16 files changed, 237 insertions(+), 91 deletions(-) create mode 100644 vms/platformvm/txs/mock_scheduled_staker.go diff --git a/vms/platformvm/state/staker.go b/vms/platformvm/state/staker.go index 37bc512e36cb..2488e4aff79e 100644 --- a/vms/platformvm/state/staker.go +++ b/vms/platformvm/state/staker.go @@ -83,7 +83,7 @@ func (s *Staker) Less(than *Staker) bool { return bytes.Compare(s.TxID[:], than.TxID[:]) == -1 } -func NewCurrentStaker(txID ids.ID, staker txs.Staker, potentialReward uint64) (*Staker, error) { +func NewCurrentStaker(txID ids.ID, staker txs.ScheduledStaker, potentialReward uint64) (*Staker, error) { publicKey, _, err := staker.PublicKey() if err != nil { return nil, err @@ -103,7 +103,7 @@ func NewCurrentStaker(txID ids.ID, staker txs.Staker, potentialReward uint64) (* }, nil } -func NewPendingStaker(txID ids.ID, staker txs.Staker) (*Staker, error) { +func NewPendingStaker(txID ids.ID, staker txs.ScheduledStaker) (*Staker, error) { publicKey, _, err := staker.PublicKey() if err != nil { return nil, err diff --git a/vms/platformvm/state/staker_test.go b/vms/platformvm/state/staker_test.go index 747f442e5eda..9482e33b793a 100644 --- a/vms/platformvm/state/staker_test.go +++ b/vms/platformvm/state/staker_test.go @@ -144,11 +144,11 @@ func TestNewCurrentStaker(t *testing.T) { subnetID := ids.GenerateTestID() weight := uint64(12345) startTime := time.Now() - endTime := time.Now() + endTime := startTime.Add(time.Hour) potentialReward := uint64(54321) currentPriority := txs.SubnetPermissionedValidatorCurrentPriority - stakerTx := txs.NewMockStaker(ctrl) + stakerTx := txs.NewMockScheduledStaker(ctrl) stakerTx.EXPECT().NodeID().Return(nodeID) stakerTx.EXPECT().PublicKey().Return(publicKey, true, nil) stakerTx.EXPECT().SubnetID().Return(subnetID) @@ -192,7 +192,7 @@ func TestNewPendingStaker(t *testing.T) { endTime := time.Now() pendingPriority := txs.SubnetPermissionedValidatorPendingPriority - stakerTx := txs.NewMockStaker(ctrl) + stakerTx := txs.NewMockScheduledStaker(ctrl) stakerTx.EXPECT().NodeID().Return(nodeID) stakerTx.EXPECT().PublicKey().Return(publicKey, true, nil) stakerTx.EXPECT().SubnetID().Return(subnetID) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index fd842f684eae..e9dbad13d943 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1324,7 +1324,7 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er return fmt.Errorf("expected tx type *txs.AddValidatorTx but got %T", vdrTx.Unsigned) } - stakeAmount := tx.Validator.Wght + stakeAmount := tx.Weight() stakeDuration := tx.Validator.Duration() currentSupply, err := s.GetCurrentSupply(constants.PrimaryNetworkID) if err != nil { @@ -1447,7 +1447,11 @@ func (s *state) loadCurrentValidators() error { } tx, _, err := s.GetTx(txID) if err != nil { - return err + return fmt.Errorf("failed loading validator transaction txID %v, %w", txID, err) + } + stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + if !ok { + return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } metadataBytes := validatorIt.Value() @@ -1460,11 +1464,6 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) - if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) - } - staker, err := NewCurrentStaker(txID, stakerTx, metadata.PotentialReward) if err != nil { return err @@ -1491,17 +1490,18 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) + stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } metadataBytes := subnetValidatorIt.Value() + startTime := stakerTx.StartTime() metadata := &validatorMetadata{ txID: txID, // use the start time as the fallback value // in case it's not stored in the database - LastUpdated: uint64(stakerTx.StartTime().Unix()), + LastUpdated: uint64(startTime.Unix()), } if err := parseValidatorMetadata(metadataBytes, metadata); err != nil { return err @@ -1537,6 +1537,11 @@ func (s *state) loadCurrentValidators() error { return err } + stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + if !ok { + return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) + } + metadata := &delegatorMetadata{ txID: txID, } @@ -1545,11 +1550,6 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) - if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) - } - staker, err := NewCurrentStaker(txID, stakerTx, metadata.PotentialReward) if err != nil { return err @@ -1594,7 +1594,7 @@ func (s *state) loadPendingValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) + stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } @@ -1629,7 +1629,7 @@ func (s *state) loadPendingValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) + stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } diff --git a/vms/platformvm/txs/add_delegator_tx.go b/vms/platformvm/txs/add_delegator_tx.go index 4f6fbe395b02..af328cc693bf 100644 --- a/vms/platformvm/txs/add_delegator_tx.go +++ b/vms/platformvm/txs/add_delegator_tx.go @@ -19,7 +19,8 @@ import ( ) var ( - _ DelegatorTx = (*AddDelegatorTx)(nil) + _ DelegatorTx = (*AddDelegatorTx)(nil) + _ ScheduledStaker = (*AddDelegatorTx)(nil) errDelegatorWeightMismatch = errors.New("delegator weight is not equal to total stake weight") errStakeMustBeAVAX = errors.New("stake must be AVAX") diff --git a/vms/platformvm/txs/add_permissionless_delegator_tx.go b/vms/platformvm/txs/add_permissionless_delegator_tx.go index 43db685d7629..346a80dd61f7 100644 --- a/vms/platformvm/txs/add_permissionless_delegator_tx.go +++ b/vms/platformvm/txs/add_permissionless_delegator_tx.go @@ -17,7 +17,10 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) -var _ DelegatorTx = (*AddPermissionlessDelegatorTx)(nil) +var ( + _ DelegatorTx = (*AddPermissionlessDelegatorTx)(nil) + _ ScheduledStaker = (*AddPermissionlessDelegatorTx)(nil) +) // AddPermissionlessDelegatorTx is an unsigned addPermissionlessDelegatorTx type AddPermissionlessDelegatorTx struct { diff --git a/vms/platformvm/txs/add_permissionless_validator_tx.go b/vms/platformvm/txs/add_permissionless_validator_tx.go index 8f313ae000b9..34b13129ade8 100644 --- a/vms/platformvm/txs/add_permissionless_validator_tx.go +++ b/vms/platformvm/txs/add_permissionless_validator_tx.go @@ -21,7 +21,8 @@ import ( ) var ( - _ ValidatorTx = (*AddPermissionlessValidatorTx)(nil) + _ ValidatorTx = (*AddPermissionlessValidatorTx)(nil) + _ ScheduledStaker = (*AddPermissionlessDelegatorTx)(nil) errEmptyNodeID = errors.New("validator nodeID cannot be empty") errNoStake = errors.New("no stake") diff --git a/vms/platformvm/txs/add_subnet_validator_tx.go b/vms/platformvm/txs/add_subnet_validator_tx.go index 0ac3474e1bd6..53fd43562c02 100644 --- a/vms/platformvm/txs/add_subnet_validator_tx.go +++ b/vms/platformvm/txs/add_subnet_validator_tx.go @@ -14,7 +14,8 @@ import ( ) var ( - _ StakerTx = (*AddSubnetValidatorTx)(nil) + _ StakerTx = (*AddSubnetValidatorTx)(nil) + _ ScheduledStaker = (*AddSubnetValidatorTx)(nil) errAddPrimaryNetworkValidator = errors.New("can't add primary network validator with AddSubnetValidatorTx") ) diff --git a/vms/platformvm/txs/add_validator_tx.go b/vms/platformvm/txs/add_validator_tx.go index be6a93c2e42b..a0e82dba7c77 100644 --- a/vms/platformvm/txs/add_validator_tx.go +++ b/vms/platformvm/txs/add_validator_tx.go @@ -19,7 +19,8 @@ import ( ) var ( - _ ValidatorTx = (*AddValidatorTx)(nil) + _ ValidatorTx = (*AddValidatorTx)(nil) + _ ScheduledStaker = (*AddValidatorTx)(nil) errTooManyShares = fmt.Errorf("a staker can only require at most %d shares from delegators", reward.PercentDenominator) ) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 22bab59afd3b..ab98dc4959fa 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -290,13 +290,11 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingValidator(newStaker) + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) @@ -321,16 +319,12 @@ func (e *StandardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingValidator(newStaker) avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) - + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -344,16 +338,12 @@ func (e *StandardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingDelegator(newStaker) avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) - + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -444,13 +434,11 @@ func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionl return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingValidator(newStaker) + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) @@ -478,16 +466,12 @@ func (e *StandardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionl return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingDelegator(newStaker) avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) - + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -511,7 +495,6 @@ func (e *StandardTxExecutor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwn txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) - return nil } @@ -545,3 +528,29 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } + +// addStakerFromStakerTx creates the staker and adds it to state. +func (e *StandardTxExecutor) addStakerFromStakerTx(stakerTx txs.ScheduledStaker) error { + var ( + txID = e.Tx.ID() + staker *state.Staker + err error + ) + + staker, err = state.NewPendingStaker(txID, stakerTx) + if err != nil { + return err + } + + switch priority := staker.Priority; { + case priority.IsCurrentValidator(): + e.State.PutCurrentValidator(staker) + case priority.IsCurrentDelegator(): + e.State.PutCurrentDelegator(staker) + case priority.IsPendingValidator(): + e.State.PutPendingValidator(staker) + case priority.IsPendingDelegator(): + e.State.PutPendingDelegator(staker) + } + return nil +} diff --git a/vms/platformvm/txs/mempool/mempool.go b/vms/platformvm/txs/mempool/mempool.go index 91b547cf5414..b1acabdd41fa 100644 --- a/vms/platformvm/txs/mempool/mempool.go +++ b/vms/platformvm/txs/mempool/mempool.go @@ -316,7 +316,7 @@ func DropExpiredStakerTxs(mempool Mempool, minStartTime time.Time) []ids.ID { for mempool.HasStakerTx() { tx := mempool.PeekStakerTx() - startTime := tx.Unsigned.(txs.Staker).StartTime() + startTime := tx.Unsigned.(txs.ScheduledStaker).StartTime() if !startTime.Before(minStartTime) { // The next proposal tx in the mempool starts sufficiently far in // the future. diff --git a/vms/platformvm/txs/mock_scheduled_staker.go b/vms/platformvm/txs/mock_scheduled_staker.go new file mode 100644 index 000000000000..984577a4c4e3 --- /dev/null +++ b/vms/platformvm/txs/mock_scheduled_staker.go @@ -0,0 +1,154 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ava-labs/avalanchego/vms/platformvm/txs (interfaces: Staker) + +// Package txs is a generated GoMock package. +package txs + +import ( + reflect "reflect" + time "time" + + ids "github.com/ava-labs/avalanchego/ids" + bls "github.com/ava-labs/avalanchego/utils/crypto/bls" + gomock "go.uber.org/mock/gomock" +) + +// MockScheduledStaker is a mock of Staker interface. +type MockScheduledStaker struct { + ctrl *gomock.Controller + recorder *MockScheduledStakerMockRecorder +} + +// MockScheduledStakerMockRecorder is the mock recorder for MockStaker. +type MockScheduledStakerMockRecorder struct { + mock *MockScheduledStaker +} + +// NewMockScheduledStaker creates a new mock instance. +func NewMockScheduledStaker(ctrl *gomock.Controller) *MockScheduledStaker { + mock := &MockScheduledStaker{ctrl: ctrl} + mock.recorder = &MockScheduledStakerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockScheduledStaker) EXPECT() *MockScheduledStakerMockRecorder { + return m.recorder +} + +// CurrentPriority mocks base method. +func (m *MockScheduledStaker) CurrentPriority() Priority { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CurrentPriority") + ret0, _ := ret[0].(Priority) + return ret0 +} + +// CurrentPriority indicates an expected call of CurrentPriority. +func (mr *MockScheduledStakerMockRecorder) CurrentPriority() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentPriority", reflect.TypeOf((*MockScheduledStaker)(nil).CurrentPriority)) +} + +// EndTime mocks base method. +func (m *MockScheduledStaker) EndTime() time.Time { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EndTime") + ret0, _ := ret[0].(time.Time) + return ret0 +} + +// EndTime indicates an expected call of EndTime. +func (mr *MockScheduledStakerMockRecorder) EndTime() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EndTime", reflect.TypeOf((*MockScheduledStaker)(nil).EndTime)) +} + +// NodeID mocks base method. +func (m *MockScheduledStaker) NodeID() ids.NodeID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NodeID") + ret0, _ := ret[0].(ids.NodeID) + return ret0 +} + +// NodeID indicates an expected call of NodeID. +func (mr *MockScheduledStakerMockRecorder) NodeID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeID", reflect.TypeOf((*MockScheduledStaker)(nil).NodeID)) +} + +// PendingPriority mocks base method. +func (m *MockScheduledStaker) PendingPriority() Priority { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PendingPriority") + ret0, _ := ret[0].(Priority) + return ret0 +} + +// PendingPriority indicates an expected call of PendingPriority. +func (mr *MockScheduledStakerMockRecorder) PendingPriority() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PendingPriority", reflect.TypeOf((*MockScheduledStaker)(nil).PendingPriority)) +} + +// PublicKey mocks base method. +func (m *MockScheduledStaker) PublicKey() (*bls.PublicKey, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PublicKey") + ret0, _ := ret[0].(*bls.PublicKey) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// PublicKey indicates an expected call of PublicKey. +func (mr *MockScheduledStakerMockRecorder) PublicKey() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublicKey", reflect.TypeOf((*MockScheduledStaker)(nil).PublicKey)) +} + +// StartTime mocks base method. +func (m *MockScheduledStaker) StartTime() time.Time { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StartTime") + ret0, _ := ret[0].(time.Time) + return ret0 +} + +// StartTime indicates an expected call of StartTime. +func (mr *MockScheduledStakerMockRecorder) StartTime() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartTime", reflect.TypeOf((*MockScheduledStaker)(nil).StartTime)) +} + +// SubnetID mocks base method. +func (m *MockScheduledStaker) SubnetID() ids.ID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SubnetID") + ret0, _ := ret[0].(ids.ID) + return ret0 +} + +// SubnetID indicates an expected call of SubnetID. +func (mr *MockScheduledStakerMockRecorder) SubnetID() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubnetID", reflect.TypeOf((*MockScheduledStaker)(nil).SubnetID)) +} + +// Weight mocks base method. +func (m *MockScheduledStaker) Weight() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Weight") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// Weight indicates an expected call of Weight. +func (mr *MockScheduledStakerMockRecorder) Weight() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Weight", reflect.TypeOf((*MockScheduledStaker)(nil).Weight)) +} \ No newline at end of file diff --git a/vms/platformvm/txs/mock_staker.go b/vms/platformvm/txs/mock_staker.go index e01ca66cf9e3..f74c2534ca39 100644 --- a/vms/platformvm/txs/mock_staker.go +++ b/vms/platformvm/txs/mock_staker.go @@ -81,20 +81,6 @@ func (mr *MockStakerMockRecorder) NodeID() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NodeID", reflect.TypeOf((*MockStaker)(nil).NodeID)) } -// PendingPriority mocks base method. -func (m *MockStaker) PendingPriority() Priority { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PendingPriority") - ret0, _ := ret[0].(Priority) - return ret0 -} - -// PendingPriority indicates an expected call of PendingPriority. -func (mr *MockStakerMockRecorder) PendingPriority() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PendingPriority", reflect.TypeOf((*MockStaker)(nil).PendingPriority)) -} - // PublicKey mocks base method. func (m *MockStaker) PublicKey() (*bls.PublicKey, bool, error) { m.ctrl.T.Helper() @@ -111,20 +97,6 @@ func (mr *MockStakerMockRecorder) PublicKey() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublicKey", reflect.TypeOf((*MockStaker)(nil).PublicKey)) } -// StartTime mocks base method. -func (m *MockStaker) StartTime() time.Time { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StartTime") - ret0, _ := ret[0].(time.Time) - return ret0 -} - -// StartTime indicates an expected call of StartTime. -func (mr *MockStakerMockRecorder) StartTime() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartTime", reflect.TypeOf((*MockStaker)(nil).StartTime)) -} - // SubnetID mocks base method. func (m *MockStaker) SubnetID() ids.ID { m.ctrl.T.Helper() diff --git a/vms/platformvm/txs/staker_tx.go b/vms/platformvm/txs/staker_tx.go index 049d3519375f..1cdcdcc337a8 100644 --- a/vms/platformvm/txs/staker_tx.go +++ b/vms/platformvm/txs/staker_tx.go @@ -48,9 +48,13 @@ type Staker interface { // PublicKey returns the BLS public key registered by this transaction. If // there was no key registered by this transaction, it will return false. PublicKey() (*bls.PublicKey, bool, error) - StartTime() time.Time EndTime() time.Time Weight() uint64 - PendingPriority() Priority CurrentPriority() Priority } + +type ScheduledStaker interface { + Staker + StartTime() time.Time + PendingPriority() Priority +} diff --git a/vms/platformvm/txs/txheap/by_end_time.go b/vms/platformvm/txs/txheap/by_end_time.go index ba144448919d..db706e38e8a3 100644 --- a/vms/platformvm/txs/txheap/by_end_time.go +++ b/vms/platformvm/txs/txheap/by_end_time.go @@ -21,8 +21,8 @@ func NewByEndTime() TimedHeap { return &byEndTime{ txHeap: txHeap{ heap: heap.NewMap[ids.ID, heapTx](func(a, b heapTx) bool { - aTime := a.tx.Unsigned.(txs.Staker).EndTime() - bTime := b.tx.Unsigned.(txs.Staker).EndTime() + aTime := a.tx.Unsigned.(txs.ScheduledStaker).EndTime() + bTime := b.tx.Unsigned.(txs.ScheduledStaker).EndTime() return aTime.Before(bTime) }), }, @@ -30,5 +30,5 @@ func NewByEndTime() TimedHeap { } func (h *byEndTime) Timestamp() time.Time { - return h.Peek().Unsigned.(txs.Staker).EndTime() + return h.Peek().Unsigned.(txs.ScheduledStaker).EndTime() } diff --git a/vms/platformvm/txs/txheap/by_start_time.go b/vms/platformvm/txs/txheap/by_start_time.go index f19c28d76436..4fe32ac8cf6c 100644 --- a/vms/platformvm/txs/txheap/by_start_time.go +++ b/vms/platformvm/txs/txheap/by_start_time.go @@ -27,8 +27,8 @@ func NewByStartTime() TimedHeap { return &byStartTime{ txHeap: txHeap{ heap: heap.NewMap[ids.ID, heapTx](func(a, b heapTx) bool { - aTime := a.tx.Unsigned.(txs.Staker).StartTime() - bTime := b.tx.Unsigned.(txs.Staker).StartTime() + aTime := a.tx.Unsigned.(txs.ScheduledStaker).StartTime() + bTime := b.tx.Unsigned.(txs.ScheduledStaker).StartTime() return aTime.Before(bTime) }), }, @@ -36,5 +36,5 @@ func NewByStartTime() TimedHeap { } func (h *byStartTime) Timestamp() time.Time { - return h.Peek().Unsigned.(txs.Staker).StartTime() + return h.Peek().Unsigned.(txs.ScheduledStaker).StartTime() } diff --git a/vms/platformvm/validator_set_property_test.go b/vms/platformvm/validator_set_property_test.go index 35135bb49f3d..fdc9969dfe38 100644 --- a/vms/platformvm/validator_set_property_test.go +++ b/vms/platformvm/validator_set_property_test.go @@ -373,7 +373,7 @@ func addPrimaryValidatorWithoutBLSKey(vm *VM, data *validatorInputData) (*state. } func internalAddValidator(vm *VM, signedTx *txs.Tx) (*state.Staker, error) { - stakerTx := signedTx.Unsigned.(txs.StakerTx) + stakerTx := signedTx.Unsigned.(txs.ScheduledStaker) if err := vm.Builder.IssueTx(context.Background(), signedTx); err != nil { return nil, fmt.Errorf("could not add tx to mempool: %w", err) } From c6736b65ae84a26154425ae06e6f60db85ded2ad Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 16 Nov 2023 14:34:59 +0100 Subject: [PATCH 07/25] nit --- vms/platformvm/txs/mock_scheduled_staker.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/vms/platformvm/txs/mock_scheduled_staker.go b/vms/platformvm/txs/mock_scheduled_staker.go index 984577a4c4e3..ce1a22b4eda0 100644 --- a/vms/platformvm/txs/mock_scheduled_staker.go +++ b/vms/platformvm/txs/mock_scheduled_staker.go @@ -1,8 +1,5 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ava-labs/avalanchego/vms/platformvm/txs (interfaces: Staker) +// Source: github.com/ava-labs/avalanchego/vms/platformvm/txs (interfaces: ScheduledStaker) // Package txs is a generated GoMock package. package txs @@ -16,13 +13,13 @@ import ( gomock "go.uber.org/mock/gomock" ) -// MockScheduledStaker is a mock of Staker interface. +// MockScheduledStaker is a mock of ScheduledStaker interface. type MockScheduledStaker struct { ctrl *gomock.Controller recorder *MockScheduledStakerMockRecorder } -// MockScheduledStakerMockRecorder is the mock recorder for MockStaker. +// MockScheduledStakerMockRecorder is the mock recorder for MockScheduledStaker. type MockScheduledStakerMockRecorder struct { mock *MockScheduledStaker } @@ -151,4 +148,4 @@ func (m *MockScheduledStaker) Weight() uint64 { func (mr *MockScheduledStakerMockRecorder) Weight() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Weight", reflect.TypeOf((*MockScheduledStaker)(nil).Weight)) -} \ No newline at end of file +} From a0fb5386cab1bd140edc639bd01138446728e2ff Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 16 Nov 2023 14:59:14 +0100 Subject: [PATCH 08/25] nit --- vms/platformvm/state/state.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index aed5ee022bc4..88a58f1ceb93 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1494,13 +1494,13 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + stakerTx, ok := tx.Unsigned.(txs.Staker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } metadataBytes := subnetValidatorIt.Value() - startTime := stakerTx.StartTime() + startTime := stakerTx.(txs.ScheduledStaker).StartTime() metadata := &validatorMetadata{ txID: txID, // use the start time as the fallback value From 9a9897cf1c3b82542012bd8252ec0251beb91fee Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Sat, 18 Nov 2023 21:18:34 +0100 Subject: [PATCH 09/25] nit --- .../txs/executor/staker_tx_verification.go | 57 ++++++------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index 9ec4880e4a44..54016eab72b6 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "math" + "time" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" @@ -165,14 +166,7 @@ func verifyAddValidatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if startTime.After(maxStartTime) { - return nil, ErrFutureStakeTime - } - - return outs, nil + return outs, StakerTimeTooMuchIntheFuture(currentTimestamp, startTime) } // verifyAddSubnetValidatorTx carries out the validation for an @@ -255,14 +249,7 @@ func verifyAddSubnetValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if validatorStartTime.After(maxStartTime) { - return ErrFutureStakeTime - } - - return nil + return StakerTimeTooMuchIntheFuture(currentTimestamp, validatorStartTime) } // Returns the representation of [tx.NodeID] validating [tx.Subnet]. @@ -438,14 +425,7 @@ func verifyAddDelegatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if validatorStartTime.After(maxStartTime) { - return nil, ErrFutureStakeTime - } - - return outs, nil + return outs, StakerTimeTooMuchIntheFuture(currentTimestamp, validatorStartTime) } // verifyAddPermissionlessValidatorTx carries out the validation for an @@ -562,14 +542,7 @@ func verifyAddPermissionlessValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if startTime.After(maxStartTime) { - return ErrFutureStakeTime - } - - return nil + return StakerTimeTooMuchIntheFuture(currentTimestamp, startTime) } // verifyAddPermissionlessDelegatorTx carries out the validation for an @@ -706,14 +679,7 @@ func verifyAddPermissionlessDelegatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if startTime.After(maxStartTime) { - return ErrFutureStakeTime - } - - return nil + return StakerTimeTooMuchIntheFuture(currentTimestamp, startTime) } // Returns an error if the given tx is invalid. @@ -762,3 +728,14 @@ func verifyTransferSubnetOwnershipTx( return nil } + +func StakerTimeTooMuchIntheFuture(chainTime, stakerStartTime time.Time) error { + // Make sure the tx doesn't start too far in the future. This is done last + // to allow the verifier visitor to explicitly check for this error. + maxStartTime := chainTime.Add(MaxFutureStartTime) + if stakerStartTime.After(maxStartTime) { + return ErrFutureStakeTime + } + + return nil +} From d17f2a263d4b2e44bd93052695a96923e8b66070 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Sat, 18 Nov 2023 22:11:49 +0100 Subject: [PATCH 10/25] nits --- .../txs/executor/staker_tx_verification.go | 110 +++++++++--------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index 54016eab72b6..5f39f97f5412 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -124,16 +124,14 @@ func verifyAddValidatorTx( return outs, nil } - currentTimestamp := chainState.GetTimestamp() + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + ) + // Ensure the proposed validator starts after the current time - startTime := tx.StartTime() - if !currentTimestamp.Before(startTime) { - return nil, fmt.Errorf( - "%w: %s >= %s", - ErrTimestampNotBeforeStartTime, - currentTimestamp, - startTime, - ) + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return nil, err } _, err := GetValidator(chainState, constants.PrimaryNetworkID, tx.Validator.NodeID) @@ -166,7 +164,7 @@ func verifyAddValidatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return outs, StakerTimeTooMuchIntheFuture(currentTimestamp, startTime) + return outs, stakerTooMuchIntheFuture(currentTimestamp, startTime) } // verifyAddSubnetValidatorTx carries out the validation for an @@ -197,16 +195,14 @@ func verifyAddSubnetValidatorTx( return nil } - currentTimestamp := chainState.GetTimestamp() - // Ensure the proposed validator starts after the current timestamp - validatorStartTime := tx.StartTime() - if !currentTimestamp.Before(validatorStartTime) { - return fmt.Errorf( - "%w: %s >= %s", - ErrTimestampNotBeforeStartTime, - currentTimestamp, - validatorStartTime, - ) + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + ) + + // Ensure the proposed validator starts after the current time + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return err } _, err := GetValidator(chainState, tx.SubnetValidator.Subnet, tx.Validator.NodeID) @@ -249,7 +245,7 @@ func verifyAddSubnetValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return StakerTimeTooMuchIntheFuture(currentTimestamp, validatorStartTime) + return stakerTooMuchIntheFuture(currentTimestamp, startTime) } // Returns the representation of [tx.NodeID] validating [tx.Subnet]. @@ -359,16 +355,14 @@ func verifyAddDelegatorTx( return outs, nil } - currentTimestamp := chainState.GetTimestamp() - // Ensure the proposed validator starts after the current timestamp - validatorStartTime := tx.StartTime() - if !currentTimestamp.Before(validatorStartTime) { - return nil, fmt.Errorf( - "%w: %s >= %s", - ErrTimestampNotBeforeStartTime, - currentTimestamp, - validatorStartTime, - ) + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + ) + + // Ensure the proposed validator starts after the current time + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return nil, err } primaryNetworkValidator, err := GetValidator(chainState, constants.PrimaryNetworkID, tx.Validator.NodeID) @@ -425,7 +419,7 @@ func verifyAddDelegatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return outs, StakerTimeTooMuchIntheFuture(currentTimestamp, validatorStartTime) + return outs, stakerTooMuchIntheFuture(currentTimestamp, startTime) } // verifyAddPermissionlessValidatorTx carries out the validation for an @@ -445,16 +439,14 @@ func verifyAddPermissionlessValidatorTx( return nil } - currentTimestamp := chainState.GetTimestamp() + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + ) + // Ensure the proposed validator starts after the current time - startTime := tx.StartTime() - if !currentTimestamp.Before(startTime) { - return fmt.Errorf( - "%w: %s >= %s", - ErrTimestampNotBeforeStartTime, - currentTimestamp, - startTime, - ) + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return err } validatorRules, err := getValidatorRules(backend, chainState, tx.Subnet) @@ -542,7 +534,7 @@ func verifyAddPermissionlessValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return StakerTimeTooMuchIntheFuture(currentTimestamp, startTime) + return stakerTooMuchIntheFuture(currentTimestamp, startTime) } // verifyAddPermissionlessDelegatorTx carries out the validation for an @@ -562,15 +554,14 @@ func verifyAddPermissionlessDelegatorTx( return nil } - currentTimestamp := chainState.GetTimestamp() - // Ensure the proposed validator starts after the current timestamp - startTime := tx.StartTime() - if !currentTimestamp.Before(startTime) { - return fmt.Errorf( - "chain timestamp (%s) not before validator's start time (%s)", - currentTimestamp, - startTime, - ) + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + ) + + // Ensure the proposed validator starts after the current time + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return err } delegatorRules, err := getDelegatorRules(backend, chainState, tx.Subnet) @@ -679,7 +670,7 @@ func verifyAddPermissionlessDelegatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return StakerTimeTooMuchIntheFuture(currentTimestamp, startTime) + return stakerTooMuchIntheFuture(currentTimestamp, startTime) } // Returns an error if the given tx is invalid. @@ -729,7 +720,20 @@ func verifyTransferSubnetOwnershipTx( return nil } -func StakerTimeTooMuchIntheFuture(chainTime, stakerStartTime time.Time) error { +// Ensure the proposed validator starts after the current time +func checkStakerStartTime(chainTime, stakerTime time.Time) error { + if !chainTime.Before(stakerTime) { + return fmt.Errorf( + "%w: %s >= %s", + ErrTimestampNotBeforeStartTime, + chainTime, + stakerTime, + ) + } + return nil +} + +func stakerTooMuchIntheFuture(chainTime, stakerStartTime time.Time) error { // Make sure the tx doesn't start too far in the future. This is done last // to allow the verifier visitor to explicitly check for this error. maxStartTime := chainTime.Add(MaxFutureStartTime) From 4c4c01151d2a06785d0ea94bb71a807f0ee7e20f Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Sun, 19 Nov 2023 12:51:40 +0100 Subject: [PATCH 11/25] nits to reduce future diffs --- vms/platformvm/state/staker_test.go | 2 +- vms/platformvm/state/state.go | 26 +-- .../txs/executor/staker_tx_verification.go | 163 ++++++++---------- .../txs/executor/standard_tx_executor.go | 63 ++++--- 4 files changed, 120 insertions(+), 134 deletions(-) diff --git a/vms/platformvm/state/staker_test.go b/vms/platformvm/state/staker_test.go index 747f442e5eda..a6faa4ab704f 100644 --- a/vms/platformvm/state/staker_test.go +++ b/vms/platformvm/state/staker_test.go @@ -144,7 +144,7 @@ func TestNewCurrentStaker(t *testing.T) { subnetID := ids.GenerateTestID() weight := uint64(12345) startTime := time.Now() - endTime := time.Now() + endTime := startTime.Add(time.Hour) potentialReward := uint64(54321) currentPriority := txs.SubnetPermissionedValidatorCurrentPriority diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 199b245008f7..2ae814b1e710 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1324,7 +1324,7 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er return fmt.Errorf("expected tx type *txs.AddValidatorTx but got %T", vdrTx.Unsigned) } - stakeAmount := tx.Validator.Wght + stakeAmount := tx.Weight() stakeDuration := tx.Validator.Duration() currentSupply, err := s.GetCurrentSupply(constants.PrimaryNetworkID) if err != nil { @@ -1447,7 +1447,11 @@ func (s *state) loadCurrentValidators() error { } tx, _, err := s.GetTx(txID) if err != nil { - return err + return fmt.Errorf("failed loading validator transaction txID %v, %w", txID, err) + } + stakerTx, ok := tx.Unsigned.(txs.Staker) + if !ok { + return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } metadataBytes := validatorIt.Value() @@ -1460,11 +1464,6 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) - if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) - } - staker, err := NewCurrentStaker(txID, stakerTx, metadata.PotentialReward) if err != nil { return err @@ -1497,11 +1496,12 @@ func (s *state) loadCurrentValidators() error { } metadataBytes := subnetValidatorIt.Value() + startTime := stakerTx.StartTime() metadata := &validatorMetadata{ txID: txID, // use the start time as the fallback value // in case it's not stored in the database - LastUpdated: uint64(stakerTx.StartTime().Unix()), + LastUpdated: uint64(startTime.Unix()), } if err := parseValidatorMetadata(metadataBytes, metadata); err != nil { return err @@ -1537,6 +1537,11 @@ func (s *state) loadCurrentValidators() error { return err } + stakerTx, ok := tx.Unsigned.(txs.Staker) + if !ok { + return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) + } + metadata := &delegatorMetadata{ txID: txID, } @@ -1545,11 +1550,6 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) - if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) - } - staker, err := NewCurrentStaker(txID, stakerTx, metadata.PotentialReward) if err != nil { return err diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index 9ec4880e4a44..e3ea4d42a04f 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "math" + "time" "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" @@ -91,7 +92,11 @@ func verifyAddValidatorTx( return nil, err } - duration := tx.Validator.Duration() + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + duration = tx.Validator.Duration() + ) switch { case tx.Validator.Wght < backend.Config.MinValidatorStake: @@ -123,16 +128,8 @@ func verifyAddValidatorTx( return outs, nil } - currentTimestamp := chainState.GetTimestamp() - // Ensure the proposed validator starts after the current time - startTime := tx.StartTime() - if !currentTimestamp.Before(startTime) { - return nil, fmt.Errorf( - "%w: %s >= %s", - ErrTimestampNotBeforeStartTime, - currentTimestamp, - startTime, - ) + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return nil, err } _, err := GetValidator(chainState, constants.PrimaryNetworkID, tx.Validator.NodeID) @@ -165,14 +162,7 @@ func verifyAddValidatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if startTime.After(maxStartTime) { - return nil, ErrFutureStakeTime - } - - return outs, nil + return outs, stakerTooMuchIntheFuture(currentTimestamp, startTime) } // verifyAddSubnetValidatorTx carries out the validation for an @@ -188,7 +178,12 @@ func verifyAddSubnetValidatorTx( return err } - duration := tx.Validator.Duration() + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + duration = tx.Validator.Duration() + ) + switch { case duration < backend.Config.MinStakeDuration: // Ensure staking length is not too short @@ -203,16 +198,8 @@ func verifyAddSubnetValidatorTx( return nil } - currentTimestamp := chainState.GetTimestamp() - // Ensure the proposed validator starts after the current timestamp - validatorStartTime := tx.StartTime() - if !currentTimestamp.Before(validatorStartTime) { - return fmt.Errorf( - "%w: %s >= %s", - ErrTimestampNotBeforeStartTime, - currentTimestamp, - validatorStartTime, - ) + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return err } _, err := GetValidator(chainState, tx.SubnetValidator.Subnet, tx.Validator.NodeID) @@ -255,14 +242,7 @@ func verifyAddSubnetValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if validatorStartTime.After(maxStartTime) { - return ErrFutureStakeTime - } - - return nil + return stakerTooMuchIntheFuture(currentTimestamp, startTime) } // Returns the representation of [tx.NodeID] validating [tx.Subnet]. @@ -349,7 +329,12 @@ func verifyAddDelegatorTx( return nil, err } - duration := tx.Validator.Duration() + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + duration = tx.Validator.Duration() + ) + switch { case duration < backend.Config.MinStakeDuration: // Ensure staking length is not too short @@ -372,16 +357,8 @@ func verifyAddDelegatorTx( return outs, nil } - currentTimestamp := chainState.GetTimestamp() - // Ensure the proposed validator starts after the current timestamp - validatorStartTime := tx.StartTime() - if !currentTimestamp.Before(validatorStartTime) { - return nil, fmt.Errorf( - "%w: %s >= %s", - ErrTimestampNotBeforeStartTime, - currentTimestamp, - validatorStartTime, - ) + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return nil, err } primaryNetworkValidator, err := GetValidator(chainState, constants.PrimaryNetworkID, tx.Validator.NodeID) @@ -438,14 +415,7 @@ func verifyAddDelegatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if validatorStartTime.After(maxStartTime) { - return nil, ErrFutureStakeTime - } - - return outs, nil + return outs, stakerTooMuchIntheFuture(currentTimestamp, startTime) } // verifyAddPermissionlessValidatorTx carries out the validation for an @@ -465,16 +435,15 @@ func verifyAddPermissionlessValidatorTx( return nil } - currentTimestamp := chainState.GetTimestamp() + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + duration = tx.Validator.Duration() + ) + // Ensure the proposed validator starts after the current time - startTime := tx.StartTime() - if !currentTimestamp.Before(startTime) { - return fmt.Errorf( - "%w: %s >= %s", - ErrTimestampNotBeforeStartTime, - currentTimestamp, - startTime, - ) + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return err } validatorRules, err := getValidatorRules(backend, chainState, tx.Subnet) @@ -482,7 +451,6 @@ func verifyAddPermissionlessValidatorTx( return err } - duration := tx.Validator.Duration() stakedAssetID := tx.StakeOuts[0].AssetID() switch { case tx.Validator.Wght < validatorRules.minValidatorStake: @@ -562,14 +530,7 @@ func verifyAddPermissionlessValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if startTime.After(maxStartTime) { - return ErrFutureStakeTime - } - - return nil + return stakerTooMuchIntheFuture(currentTimestamp, startTime) } // verifyAddPermissionlessDelegatorTx carries out the validation for an @@ -589,15 +550,15 @@ func verifyAddPermissionlessDelegatorTx( return nil } - currentTimestamp := chainState.GetTimestamp() - // Ensure the proposed validator starts after the current timestamp - startTime := tx.StartTime() - if !currentTimestamp.Before(startTime) { - return fmt.Errorf( - "chain timestamp (%s) not before validator's start time (%s)", - currentTimestamp, - startTime, - ) + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + duration = tx.Validator.Duration() + ) + + // Ensure the proposed validator starts after the current time + if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + return err } delegatorRules, err := getDelegatorRules(backend, chainState, tx.Subnet) @@ -605,7 +566,6 @@ func verifyAddPermissionlessDelegatorTx( return err } - duration := tx.Validator.Duration() stakedAssetID := tx.StakeOuts[0].AssetID() switch { case tx.Validator.Wght < delegatorRules.minDelegatorStake: @@ -706,14 +666,7 @@ func verifyAddPermissionlessDelegatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. - maxStartTime := currentTimestamp.Add(MaxFutureStartTime) - if startTime.After(maxStartTime) { - return ErrFutureStakeTime - } - - return nil + return stakerTooMuchIntheFuture(currentTimestamp, startTime) } // Returns an error if the given tx is invalid. @@ -762,3 +715,27 @@ func verifyTransferSubnetOwnershipTx( return nil } + +// Ensure the proposed validator starts after the current time +func checkStakerStartTime(chainTime, stakerTime time.Time) error { + if !chainTime.Before(stakerTime) { + return fmt.Errorf( + "%w: %s >= %s", + ErrTimestampNotBeforeStartTime, + chainTime, + stakerTime, + ) + } + return nil +} + +func stakerTooMuchIntheFuture(chainTime, stakerStartTime time.Time) error { + // Make sure the tx doesn't start too far in the future. This is done last + // to allow the verifier visitor to explicitly check for this error. + maxStartTime := chainTime.Add(MaxFutureStartTime) + if stakerStartTime.After(maxStartTime) { + return ErrFutureStakeTime + } + + return nil +} diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 22bab59afd3b..d3895530f76d 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -290,13 +290,11 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingValidator(newStaker) + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) @@ -321,16 +319,12 @@ func (e *StandardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingValidator(newStaker) avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) - + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -344,16 +338,12 @@ func (e *StandardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingDelegator(newStaker) avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) - + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -444,13 +434,11 @@ func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionl return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingValidator(newStaker) + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) @@ -478,16 +466,12 @@ func (e *StandardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionl return err } - txID := e.Tx.ID() - newStaker, err := state.NewPendingStaker(txID, tx) - if err != nil { + if err := e.addStakerFromStakerTx(tx); err != nil { return err } - e.State.PutPendingDelegator(newStaker) avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, txID, tx.Outs) - + avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } @@ -511,7 +495,6 @@ func (e *StandardTxExecutor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwn txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) avax.Produce(e.State, txID, tx.Outs) - return nil } @@ -545,3 +528,29 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { avax.Produce(e.State, e.Tx.ID(), tx.Outs) return nil } + +// addStakerFromStakerTx creates the staker and adds it to state. +func (e *StandardTxExecutor) addStakerFromStakerTx(stakerTx txs.Staker) error { + var ( + txID = e.Tx.ID() + staker *state.Staker + err error + ) + + staker, err = state.NewPendingStaker(txID, stakerTx) + if err != nil { + return err + } + + switch priority := staker.Priority; { + case priority.IsCurrentValidator(): + e.State.PutCurrentValidator(staker) + case priority.IsCurrentDelegator(): + e.State.PutCurrentDelegator(staker) + case priority.IsPendingValidator(): + e.State.PutPendingValidator(staker) + case priority.IsPendingDelegator(): + e.State.PutPendingDelegator(staker) + } + return nil +} From 905e55ec4d9d42851d55c45379f0f6f97a5a895a Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Sun, 19 Nov 2023 13:05:08 +0100 Subject: [PATCH 12/25] nit --- vms/platformvm/block/builder/builder.go | 22 ++----------- .../txs/executor/tx_mempool_verifier.go | 32 ++++++++++++------- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/vms/platformvm/block/builder/builder.go b/vms/platformvm/block/builder/builder.go index 13a1c7902b6d..a4ad4abcc31c 100644 --- a/vms/platformvm/block/builder/builder.go +++ b/vms/platformvm/block/builder/builder.go @@ -123,38 +123,22 @@ func (b *builder) buildBlock() (block.Block, error) { return nil, err } nextHeight := preferred.Height() + 1 + preferredState, ok := b.blkManager.GetState(preferredID) if !ok { return nil, fmt.Errorf("%w: %s", state.ErrMissingParentState, preferredID) } - timestamp := b.txExecutorBackend.Clk.Time() - if parentTime := preferred.Timestamp(); parentTime.After(timestamp) { - timestamp = parentTime - } - // [timestamp] = max(now, parentTime) - - nextStakerChangeTime, err := txexecutor.GetNextStakerChangeTime(preferredState) + nextTimeStamp, timeWasCapped, err := txexecutor.NextBlockTime(preferredState, b.txExecutorBackend.Clk) if err != nil { return nil, fmt.Errorf("could not calculate next staker change time: %w", err) } - // timeWasCapped means that [timestamp] was reduced to - // [nextStakerChangeTime]. It is used as a flag for [buildApricotBlock] to - // be willing to issue an advanceTimeTx. It is also used as a flag for - // [buildBanffBlock] to force the issuance of an empty block to advance - // the time forward; if there are no available transactions. - timeWasCapped := !timestamp.Before(nextStakerChangeTime) - if timeWasCapped { - timestamp = nextStakerChangeTime - } - // [timestamp] = min(max(now, parentTime), nextStakerChangeTime) - return buildBlock( b, preferredID, nextHeight, - timestamp, + nextTimeStamp, timeWasCapped, preferredState, ) diff --git a/vms/platformvm/txs/executor/tx_mempool_verifier.go b/vms/platformvm/txs/executor/tx_mempool_verifier.go index 6704ccbd0489..2ec0e6c343b6 100644 --- a/vms/platformvm/txs/executor/tx_mempool_verifier.go +++ b/vms/platformvm/txs/executor/tx_mempool_verifier.go @@ -9,6 +9,7 @@ import ( "time" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) @@ -111,7 +112,7 @@ func (v *MempoolTxVerifier) standardBaseState() (state.Diff, error) { return nil, err } - nextBlkTime, err := v.nextBlockTime(state) + nextBlkTime, _, err := NextBlockTime(state, v.Clk) if err != nil { return nil, err } @@ -134,20 +135,27 @@ func (v *MempoolTxVerifier) standardBaseState() (state.Diff, error) { return state, nil } -func (v *MempoolTxVerifier) nextBlockTime(state state.Diff) (time.Time, error) { - var ( - parentTime = state.GetTimestamp() - nextBlkTime = v.Clk.Time() - ) - if parentTime.After(nextBlkTime) { - nextBlkTime = parentTime +func NextBlockTime(state state.Chain, clk *mockable.Clock) (time.Time, bool, error) { + timestamp := clk.Time() + if parentTime := state.GetTimestamp(); parentTime.After(timestamp) { + timestamp = parentTime } + // [timestamp] = max(now, parentTime) + nextStakerChangeTime, err := GetNextStakerChangeTime(state) if err != nil { - return time.Time{}, fmt.Errorf("could not calculate next staker change time: %w", err) + return time.Time{}, false, fmt.Errorf("could not calculate next staker change time: %w", err) } - if !nextBlkTime.Before(nextStakerChangeTime) { - nextBlkTime = nextStakerChangeTime + + // timeWasCapped means that [timestamp] was reduced to + // [nextStakerChangeTime]. It is used as a flag for [buildApricotBlock] to + // be willing to issue an advanceTimeTx. It is also used as a flag for + // [buildBanffBlock] to force the issuance of an empty block to advance + // the time forward; if there are no available transactions. + timeWasCapped := !timestamp.Before(nextStakerChangeTime) + if timeWasCapped { + timestamp = nextStakerChangeTime } - return nextBlkTime, nil + // [timestamp] = min(max(now, parentTime), nextStakerChangeTime) + return timestamp, timeWasCapped, nil } From 89094cddccd352307b733564ef0871297514d9b0 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Sun, 19 Nov 2023 13:17:35 +0100 Subject: [PATCH 13/25] improved e2e test --- tests/e2e/p/staking_rewards.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/e2e/p/staking_rewards.go b/tests/e2e/p/staking_rewards.go index 41a77985729b..f0d8b22df1b1 100644 --- a/tests/e2e/p/staking_rewards.go +++ b/tests/e2e/p/staking_rewards.go @@ -103,12 +103,18 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { betaNodeID, betaPOP, err := betaInfoClient.GetNodeID(e2e.DefaultContext()) require.NoError(err) + pvmClient := platformvm.NewClient(alphaNode.GetProcessContext().URI) + const ( delegationPercent = 0.10 // 10% delegationShare = reward.PercentDenominator * delegationPercent weight = 2_000 * units.Avax ) + ginkgo.By("retrieving supply before inserting validators") + supplyAtValidatorsStart, _, err := pvmClient.GetCurrentSupply(e2e.DefaultContext(), constants.PrimaryNetworkID) + require.NoError(err) + alphaValidatorStartTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) alphaValidatorEndTime := alphaValidatorStartTime.Add(validationPeriod) tests.Outf("alpha node validation period starting at: %v\n", alphaValidatorStartTime) @@ -171,6 +177,10 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { require.NoError(err) }) + ginkgo.By("retrieving supply before inserting delegators") + supplyAtDelegatorsStart, _, err := pvmClient.GetCurrentSupply(e2e.DefaultContext(), constants.PrimaryNetworkID) + require.NoError(err) + gammaDelegatorStartTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) tests.Outf("gamma delegation period starting at: %v\n", gammaDelegatorStartTime) @@ -227,8 +237,6 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { // delegation periods are shorter than the validation periods. time.Sleep(time.Until(betaValidatorEndTime)) - pvmClient := platformvm.NewClient(alphaNode.GetProcessContext().URI) - ginkgo.By("waiting until the alpha and beta nodes are no longer validators") e2e.Eventually(func() bool { validators, err := pvmClient.GetCurrentValidators(e2e.DefaultContext(), constants.PrimaryNetworkID, nil) @@ -270,11 +278,9 @@ var _ = ginkgo.Describe("[Staking Rewards]", func() { require.Len(rewardBalances, len(rewardKeys)) ginkgo.By("determining expected validation and delegation rewards") - currentSupply, _, err := pvmClient.GetCurrentSupply(e2e.DefaultContext(), constants.PrimaryNetworkID) - require.NoError(err) calculator := reward.NewCalculator(rewardConfig) - expectedValidationReward := calculator.Calculate(validationPeriod, weight, currentSupply) - potentialDelegationReward := calculator.Calculate(delegationPeriod, weight, currentSupply) + expectedValidationReward := calculator.Calculate(validationPeriod, weight, supplyAtValidatorsStart) + potentialDelegationReward := calculator.Calculate(delegationPeriod, weight, supplyAtDelegatorsStart) expectedDelegationFee, expectedDelegatorReward := reward.Split(potentialDelegationReward, delegationShare) ginkgo.By("checking expected rewards against actual rewards") From c3e367085623b613407a85bff916ae55d28fecc8 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 21 Nov 2023 20:24:03 +0100 Subject: [PATCH 14/25] nits --- vms/platformvm/block/builder/builder.go | 1 - .../txs/executor/staker_tx_verification.go | 74 +++++++++---------- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/vms/platformvm/block/builder/builder.go b/vms/platformvm/block/builder/builder.go index a4ad4abcc31c..595d396a854f 100644 --- a/vms/platformvm/block/builder/builder.go +++ b/vms/platformvm/block/builder/builder.go @@ -123,7 +123,6 @@ func (b *builder) buildBlock() (block.Block, error) { return nil, err } nextHeight := preferred.Height() + 1 - preferredState, ok := b.blkManager.GetState(preferredID) if !ok { return nil, fmt.Errorf("%w: %s", state.ErrMissingParentState, preferredID) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index e3ea4d42a04f..858c175539e8 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -92,12 +92,7 @@ func verifyAddValidatorTx( return nil, err } - var ( - currentTimestamp = chainState.GetTimestamp() - startTime = tx.StartTime() - duration = tx.Validator.Duration() - ) - + duration := tx.Validator.Duration() switch { case tx.Validator.Wght < backend.Config.MinValidatorStake: // Ensure validator is staking at least the minimum amount @@ -128,7 +123,11 @@ func verifyAddValidatorTx( return outs, nil } - if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + ) + if err := verifyStakerStartTime(currentTimestamp, startTime); err != nil { return nil, err } @@ -162,7 +161,7 @@ func verifyAddValidatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return outs, stakerTooMuchIntheFuture(currentTimestamp, startTime) + return outs, verifyStakerStartsSoon(currentTimestamp, startTime) } // verifyAddSubnetValidatorTx carries out the validation for an @@ -178,12 +177,7 @@ func verifyAddSubnetValidatorTx( return err } - var ( - currentTimestamp = chainState.GetTimestamp() - startTime = tx.StartTime() - duration = tx.Validator.Duration() - ) - + duration := tx.Validator.Duration() switch { case duration < backend.Config.MinStakeDuration: // Ensure staking length is not too short @@ -198,7 +192,11 @@ func verifyAddSubnetValidatorTx( return nil } - if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + ) + if err := verifyStakerStartTime(currentTimestamp, startTime); err != nil { return err } @@ -242,7 +240,7 @@ func verifyAddSubnetValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return stakerTooMuchIntheFuture(currentTimestamp, startTime) + return verifyStakerStartsSoon(currentTimestamp, startTime) } // Returns the representation of [tx.NodeID] validating [tx.Subnet]. @@ -329,12 +327,7 @@ func verifyAddDelegatorTx( return nil, err } - var ( - currentTimestamp = chainState.GetTimestamp() - startTime = tx.StartTime() - duration = tx.Validator.Duration() - ) - + duration := tx.Validator.Duration() switch { case duration < backend.Config.MinStakeDuration: // Ensure staking length is not too short @@ -357,7 +350,11 @@ func verifyAddDelegatorTx( return outs, nil } - if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + var ( + currentTimestamp = chainState.GetTimestamp() + startTime = tx.StartTime() + ) + if err := verifyStakerStartTime(currentTimestamp, startTime); err != nil { return nil, err } @@ -415,7 +412,7 @@ func verifyAddDelegatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return outs, stakerTooMuchIntheFuture(currentTimestamp, startTime) + return outs, verifyStakerStartsSoon(currentTimestamp, startTime) } // verifyAddPermissionlessValidatorTx carries out the validation for an @@ -438,11 +435,8 @@ func verifyAddPermissionlessValidatorTx( var ( currentTimestamp = chainState.GetTimestamp() startTime = tx.StartTime() - duration = tx.Validator.Duration() ) - - // Ensure the proposed validator starts after the current time - if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + if err := verifyStakerStartTime(currentTimestamp, startTime); err != nil { return err } @@ -451,7 +445,10 @@ func verifyAddPermissionlessValidatorTx( return err } - stakedAssetID := tx.StakeOuts[0].AssetID() + var ( + duration = tx.Validator.Duration() + stakedAssetID = tx.StakeOuts[0].AssetID() + ) switch { case tx.Validator.Wght < validatorRules.minValidatorStake: // Ensure validator is staking at least the minimum amount @@ -530,7 +527,7 @@ func verifyAddPermissionlessValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return stakerTooMuchIntheFuture(currentTimestamp, startTime) + return verifyStakerStartsSoon(currentTimestamp, startTime) } // verifyAddPermissionlessDelegatorTx carries out the validation for an @@ -553,11 +550,8 @@ func verifyAddPermissionlessDelegatorTx( var ( currentTimestamp = chainState.GetTimestamp() startTime = tx.StartTime() - duration = tx.Validator.Duration() ) - - // Ensure the proposed validator starts after the current time - if err := checkStakerStartTime(currentTimestamp, startTime); err != nil { + if err := verifyStakerStartTime(currentTimestamp, startTime); err != nil { return err } @@ -566,7 +560,10 @@ func verifyAddPermissionlessDelegatorTx( return err } - stakedAssetID := tx.StakeOuts[0].AssetID() + var ( + duration = tx.Validator.Duration() + stakedAssetID = tx.StakeOuts[0].AssetID() + ) switch { case tx.Validator.Wght < delegatorRules.minDelegatorStake: // Ensure delegator is staking at least the minimum amount @@ -666,7 +663,7 @@ func verifyAddPermissionlessDelegatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } - return stakerTooMuchIntheFuture(currentTimestamp, startTime) + return verifyStakerStartsSoon(currentTimestamp, startTime) } // Returns an error if the given tx is invalid. @@ -717,7 +714,7 @@ func verifyTransferSubnetOwnershipTx( } // Ensure the proposed validator starts after the current time -func checkStakerStartTime(chainTime, stakerTime time.Time) error { +func verifyStakerStartTime(chainTime, stakerTime time.Time) error { if !chainTime.Before(stakerTime) { return fmt.Errorf( "%w: %s >= %s", @@ -729,13 +726,12 @@ func checkStakerStartTime(chainTime, stakerTime time.Time) error { return nil } -func stakerTooMuchIntheFuture(chainTime, stakerStartTime time.Time) error { +func verifyStakerStartsSoon(chainTime, stakerStartTime time.Time) error { // Make sure the tx doesn't start too far in the future. This is done last // to allow the verifier visitor to explicitly check for this error. maxStartTime := chainTime.Add(MaxFutureStartTime) if stakerStartTime.After(maxStartTime) { return ErrFutureStakeTime } - return nil } From ce87deadfa3470f5d3c680cccdaf963d148387fd Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 22 Nov 2023 09:49:44 +0100 Subject: [PATCH 15/25] nits --- vms/platformvm/block/builder/builder.go | 4 +-- vms/platformvm/state/state.go | 1 + .../txs/executor/staker_tx_verification.go | 13 +++++-- .../txs/executor/standard_tx_executor.go | 35 +++++++++---------- .../txs/executor/tx_mempool_verifier.go | 7 ++-- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/vms/platformvm/block/builder/builder.go b/vms/platformvm/block/builder/builder.go index 595d396a854f..aee2181d2e40 100644 --- a/vms/platformvm/block/builder/builder.go +++ b/vms/platformvm/block/builder/builder.go @@ -128,7 +128,7 @@ func (b *builder) buildBlock() (block.Block, error) { return nil, fmt.Errorf("%w: %s", state.ErrMissingParentState, preferredID) } - nextTimeStamp, timeWasCapped, err := txexecutor.NextBlockTime(preferredState, b.txExecutorBackend.Clk) + timestamp, timeWasCapped, err := txexecutor.NextBlockTime(preferredState, b.txExecutorBackend.Clk) if err != nil { return nil, fmt.Errorf("could not calculate next staker change time: %w", err) } @@ -137,7 +137,7 @@ func (b *builder) buildBlock() (block.Block, error) { b, preferredID, nextHeight, - nextTimeStamp, + timestamp, timeWasCapped, preferredState, ) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 2ae814b1e710..d36a31b08fae 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1449,6 +1449,7 @@ func (s *state) loadCurrentValidators() error { if err != nil { return fmt.Errorf("failed loading validator transaction txID %v, %w", txID, err) } + stakerTx, ok := tx.Unsigned.(txs.Staker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index 858c175539e8..fce8bef81b97 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -161,6 +161,8 @@ func verifyAddValidatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } + // verifyStakerStartsSoon is checked last to allow + // the verifier visitor to explicitly check for this error. return outs, verifyStakerStartsSoon(currentTimestamp, startTime) } @@ -240,6 +242,8 @@ func verifyAddSubnetValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } + // verifyStakerStartsSoon is checked last to allow + // the verifier visitor to explicitly check for this error. return verifyStakerStartsSoon(currentTimestamp, startTime) } @@ -412,6 +416,8 @@ func verifyAddDelegatorTx( return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } + // verifyStakerStartsSoon is checked last to allow + // the verifier visitor to explicitly check for this error. return outs, verifyStakerStartsSoon(currentTimestamp, startTime) } @@ -527,6 +533,8 @@ func verifyAddPermissionlessValidatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } + // verifyStakerStartsSoon is checked last to allow + // the verifier visitor to explicitly check for this error. return verifyStakerStartsSoon(currentTimestamp, startTime) } @@ -663,6 +671,8 @@ func verifyAddPermissionlessDelegatorTx( return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) } + // verifyStakerStartsSoon is checked last to allow + // the verifier visitor to explicitly check for this error. return verifyStakerStartsSoon(currentTimestamp, startTime) } @@ -727,8 +737,7 @@ func verifyStakerStartTime(chainTime, stakerTime time.Time) error { } func verifyStakerStartsSoon(chainTime, stakerStartTime time.Time) error { - // Make sure the tx doesn't start too far in the future. This is done last - // to allow the verifier visitor to explicitly check for this error. + // Make sure the tx doesn't start too far in the future. maxStartTime := chainTime.Add(MaxFutureStartTime) if stakerStartTime.After(maxStartTime) { return ErrFutureStakeTime diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index d3895530f76d..afc122dbf1d4 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -290,7 +290,7 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { return err } - if err := e.addStakerFromStakerTx(tx); err != nil { + if err := e.putStaker(tx); err != nil { return err } @@ -319,12 +319,13 @@ func (e *StandardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) return err } - if err := e.addStakerFromStakerTx(tx); err != nil { + if err := e.putStaker(tx); err != nil { return err } + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, e.Tx.ID(), tx.Outs) + avax.Produce(e.State, txID, tx.Outs) return nil } @@ -338,12 +339,13 @@ func (e *StandardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { return err } - if err := e.addStakerFromStakerTx(tx); err != nil { + if err := e.putStaker(tx); err != nil { return err } + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, e.Tx.ID(), tx.Outs) + avax.Produce(e.State, txID, tx.Outs) return nil } @@ -434,7 +436,7 @@ func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionl return err } - if err := e.addStakerFromStakerTx(tx); err != nil { + if err := e.putStaker(tx); err != nil { return err } @@ -466,12 +468,13 @@ func (e *StandardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionl return err } - if err := e.addStakerFromStakerTx(tx); err != nil { + if err := e.putStaker(tx); err != nil { return err } + txID := e.Tx.ID() avax.Consume(e.State, tx.Ins) - avax.Produce(e.State, e.Tx.ID(), tx.Outs) + avax.Produce(e.State, txID, tx.Outs) return nil } @@ -522,22 +525,18 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { return err } + txID := e.Tx.ID() // Consume the UTXOS avax.Consume(e.State, tx.Ins) // Produce the UTXOS - avax.Produce(e.State, e.Tx.ID(), tx.Outs) + avax.Produce(e.State, txID, tx.Outs) return nil } -// addStakerFromStakerTx creates the staker and adds it to state. -func (e *StandardTxExecutor) addStakerFromStakerTx(stakerTx txs.Staker) error { - var ( - txID = e.Tx.ID() - staker *state.Staker - err error - ) - - staker, err = state.NewPendingStaker(txID, stakerTx) +// putStaker creates the staker and adds it to state. +func (e *StandardTxExecutor) putStaker(stakerTx txs.Staker) error { + txID := e.Tx.ID() + staker, err := state.NewPendingStaker(txID, stakerTx) if err != nil { return err } diff --git a/vms/platformvm/txs/executor/tx_mempool_verifier.go b/vms/platformvm/txs/executor/tx_mempool_verifier.go index 2ec0e6c343b6..8794f32553cd 100644 --- a/vms/platformvm/txs/executor/tx_mempool_verifier.go +++ b/vms/platformvm/txs/executor/tx_mempool_verifier.go @@ -136,8 +136,11 @@ func (v *MempoolTxVerifier) standardBaseState() (state.Diff, error) { } func NextBlockTime(state state.Chain, clk *mockable.Clock) (time.Time, bool, error) { - timestamp := clk.Time() - if parentTime := state.GetTimestamp(); parentTime.After(timestamp) { + var ( + timestamp = clk.Time() + parentTime = state.GetTimestamp() + ) + if parentTime.After(timestamp) { timestamp = parentTime } // [timestamp] = max(now, parentTime) From 73d5c2f6895ba32f8a0224d6a4a6bb536c3f636d Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 27 Nov 2023 11:27:44 +0100 Subject: [PATCH 16/25] nit --- vms/platformvm/block/builder/builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vms/platformvm/block/builder/builder.go b/vms/platformvm/block/builder/builder.go index cda5fdf24590..7ef8668dfe98 100644 --- a/vms/platformvm/block/builder/builder.go +++ b/vms/platformvm/block/builder/builder.go @@ -130,7 +130,7 @@ func (b *builder) buildBlock() (block.Block, error) { timestamp, timeWasCapped, err := txexecutor.NextBlockTime(preferredState, b.txExecutorBackend.Clk) if err != nil { - return nil, fmt.Errorf("could not calculate next staker change time: %w", err) + return nil, err } return buildBlock( From c353c3349fdf531b53535310df1995e456197146 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 28 Nov 2023 08:59:35 +0100 Subject: [PATCH 17/25] nits --- vms/platformvm/block/builder/builder.go | 2 +- vms/platformvm/txs/executor/standard_tx_executor.go | 2 +- vms/platformvm/txs/executor/tx_mempool_verifier.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vms/platformvm/block/builder/builder.go b/vms/platformvm/block/builder/builder.go index 7ef8668dfe98..cda5fdf24590 100644 --- a/vms/platformvm/block/builder/builder.go +++ b/vms/platformvm/block/builder/builder.go @@ -130,7 +130,7 @@ func (b *builder) buildBlock() (block.Block, error) { timestamp, timeWasCapped, err := txexecutor.NextBlockTime(preferredState, b.txExecutorBackend.Clk) if err != nil { - return nil, err + return nil, fmt.Errorf("could not calculate next staker change time: %w", err) } return buildBlock( diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index afc122dbf1d4..323d343742eb 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -533,7 +533,7 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { return nil } -// putStaker creates the staker and adds it to state. +// Creates the staker as defined in [stakerTx] and adds it to [e.State]. func (e *StandardTxExecutor) putStaker(stakerTx txs.Staker) error { txID := e.Tx.ID() staker, err := state.NewPendingStaker(txID, stakerTx) diff --git a/vms/platformvm/txs/executor/tx_mempool_verifier.go b/vms/platformvm/txs/executor/tx_mempool_verifier.go index 9756196d7de2..77759fec9427 100644 --- a/vms/platformvm/txs/executor/tx_mempool_verifier.go +++ b/vms/platformvm/txs/executor/tx_mempool_verifier.go @@ -136,7 +136,7 @@ func NextBlockTime(state state.Chain, clk *mockable.Clock) (time.Time, bool, err nextStakerChangeTime, err := GetNextStakerChangeTime(state) if err != nil { - return time.Time{}, false, fmt.Errorf("could not calculate next staker change time: %w", err) + return time.Time{}, false, fmt.Errorf("failed getting next staker change time: %w", err) } // timeWasCapped means that [timestamp] was reduced to From 5e10688ae15572115fcaa542de56e9e8dc49f389 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Fri, 1 Dec 2023 11:29:06 +0100 Subject: [PATCH 18/25] nits --- vms/platformvm/state/state.go | 2 +- vms/platformvm/txs/executor/standard_tx_executor.go | 6 ++---- vms/platformvm/txs/executor/tx_mempool_verifier.go | 6 +----- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index f8e0e9bca900..82ff0107762a 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1448,7 +1448,7 @@ func (s *state) loadCurrentValidators() error { } tx, _, err := s.GetTx(txID) if err != nil { - return fmt.Errorf("failed loading validator transaction txID %v, %w", txID, err) + return fmt.Errorf("failed loading validator transaction txID %s, %w", txID, err) } stakerTx, ok := tx.Unsigned.(txs.Staker) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 5293bf45cf01..083e4f4c75c7 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -542,14 +542,12 @@ func (e *StandardTxExecutor) putStaker(stakerTx txs.Staker) error { } switch priority := staker.Priority; { - case priority.IsCurrentValidator(): - e.State.PutCurrentValidator(staker) - case priority.IsCurrentDelegator(): - e.State.PutCurrentDelegator(staker) case priority.IsPendingValidator(): e.State.PutPendingValidator(staker) case priority.IsPendingDelegator(): e.State.PutPendingDelegator(staker) + default: + return fmt.Errorf("staker %s, unexpected priority %d", staker.TxID, priority) } return nil } diff --git a/vms/platformvm/txs/executor/tx_mempool_verifier.go b/vms/platformvm/txs/executor/tx_mempool_verifier.go index 77759fec9427..378b742ae484 100644 --- a/vms/platformvm/txs/executor/tx_mempool_verifier.go +++ b/vms/platformvm/txs/executor/tx_mempool_verifier.go @@ -139,11 +139,7 @@ func NextBlockTime(state state.Chain, clk *mockable.Clock) (time.Time, bool, err return time.Time{}, false, fmt.Errorf("failed getting next staker change time: %w", err) } - // timeWasCapped means that [timestamp] was reduced to - // [nextStakerChangeTime]. It is used as a flag for [buildApricotBlock] to - // be willing to issue an advanceTimeTx. It is also used as a flag for - // [buildBanffBlock] to force the issuance of an empty block to advance - // the time forward; if there are no available transactions. + // timeWasCapped means that [timestamp] was reduced to [nextStakerChangeTime] timeWasCapped := !timestamp.Before(nextStakerChangeTime) if timeWasCapped { timestamp = nextStakerChangeTime From 9b97b597534af53e7bc574ce99b21c5708de0851 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 5 Dec 2023 11:28:31 +0100 Subject: [PATCH 19/25] fix --- vms/platformvm/state/state.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index f6fb3bc3de23..e12a0c308645 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1320,13 +1320,13 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er // Persist primary network validator set at genesis for _, vdrTx := range genesis.Validators { - validatorTx, ok := vdrTx.Unsigned.(*txs.AddValidatorTx) + validatorTx, ok := vdrTx.Unsigned.(txs.ScheduledStaker) if !ok { return fmt.Errorf("expected tx type txs.ValidatorTx but got %T", vdrTx.Unsigned) } stakeAmount := validatorTx.Weight() - stakeDuration := validatorTx.Duration() + stakeDuration := validatorTx.EndTime().Sub(validatorTx.StartTime()) currentSupply, err := s.GetCurrentSupply(constants.PrimaryNetworkID) if err != nil { return err From 0684a8ab525b04d92ff18ef937a4f94a2ebceba5 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Tue, 5 Dec 2023 12:40:19 -0500 Subject: [PATCH 20/25] nits --- vms/platformvm/txs/txheap/by_end_time.go | 6 +++--- vms/platformvm/validator_set_property_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vms/platformvm/txs/txheap/by_end_time.go b/vms/platformvm/txs/txheap/by_end_time.go index 5d4376623044..2499ce971bc9 100644 --- a/vms/platformvm/txs/txheap/by_end_time.go +++ b/vms/platformvm/txs/txheap/by_end_time.go @@ -27,8 +27,8 @@ func NewByEndTime() TimedHeap { return &byEndTime{ txHeap: txHeap{ heap: heap.NewMap[ids.ID, heapTx](func(a, b heapTx) bool { - aTime := a.tx.Unsigned.(txs.ScheduledStaker).EndTime() - bTime := b.tx.Unsigned.(txs.ScheduledStaker).EndTime() + aTime := a.tx.Unsigned.(txs.Staker).EndTime() + bTime := b.tx.Unsigned.(txs.Staker).EndTime() return aTime.Before(bTime) }), }, @@ -36,5 +36,5 @@ func NewByEndTime() TimedHeap { } func (h *byEndTime) Timestamp() time.Time { - return h.Peek().Unsigned.(txs.ScheduledStaker).EndTime() + return h.Peek().Unsigned.(txs.Staker).EndTime() } diff --git a/vms/platformvm/validator_set_property_test.go b/vms/platformvm/validator_set_property_test.go index 63e6febb9545..189e220679ff 100644 --- a/vms/platformvm/validator_set_property_test.go +++ b/vms/platformvm/validator_set_property_test.go @@ -373,7 +373,6 @@ func addPrimaryValidatorWithoutBLSKey(vm *VM, data *validatorInputData) (*state. } func internalAddValidator(vm *VM, signedTx *txs.Tx) (*state.Staker, error) { - stakerTx := signedTx.Unsigned.(txs.ScheduledStaker) if err := vm.Network.IssueTx(context.Background(), signedTx); err != nil { return nil, fmt.Errorf("could not add tx to mempool: %w", err) } @@ -393,6 +392,7 @@ func internalAddValidator(vm *VM, signedTx *txs.Tx) (*state.Staker, error) { } // move time ahead, promoting the validator to current + stakerTx := signedTx.Unsigned.(txs.ScheduledStaker) currentTime := stakerTx.StartTime() vm.clock.Set(currentTime) vm.state.SetTimestamp(currentTime) From 89ce3c251fba59c6f1af80714be3c186fa379e26 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 6 Dec 2023 11:12:23 +0100 Subject: [PATCH 21/25] fix error --- vms/platformvm/state/state.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index e12a0c308645..bec50e62adc4 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1320,9 +1320,12 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er // Persist primary network validator set at genesis for _, vdrTx := range genesis.Validators { + // we expect genesis validator txs to be AddValidatorTx or AddPermissionlessValidatorTx + // even if, post Durango, we don't explicitly type check for these two txs. + // TODO: enforce stricter type check validatorTx, ok := vdrTx.Unsigned.(txs.ScheduledStaker) if !ok { - return fmt.Errorf("expected tx type txs.ValidatorTx but got %T", vdrTx.Unsigned) + return fmt.Errorf("expected a scheduled staker but got %T", vdrTx.Unsigned) } stakeAmount := validatorTx.Weight() From fa9269c5102e165172e5f4db849a768ccdc45a72 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Wed, 6 Dec 2023 13:49:44 -0500 Subject: [PATCH 22/25] simplify comment --- vms/platformvm/state/state.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index bec50e62adc4..36a49428020c 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1320,9 +1320,10 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er // Persist primary network validator set at genesis for _, vdrTx := range genesis.Validators { - // we expect genesis validator txs to be AddValidatorTx or AddPermissionlessValidatorTx - // even if, post Durango, we don't explicitly type check for these two txs. - // TODO: enforce stricter type check + // We expect genesis validator txs to be either AddValidatorTx or + // AddPermissionlessValidatorTx. + // + // TODO: Enforce stricter type check validatorTx, ok := vdrTx.Unsigned.(txs.ScheduledStaker) if !ok { return fmt.Errorf("expected a scheduled staker but got %T", vdrTx.Unsigned) From db4c048db4cfe7fafd153e78488956bb716585a1 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 7 Dec 2023 14:08:47 +0100 Subject: [PATCH 23/25] fixed bad merge --- vms/platformvm/state/state.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 4f4a0303f13f..8f03ebd8808f 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1455,7 +1455,7 @@ func (s *state) loadCurrentValidators() error { return fmt.Errorf("failed loading validator transaction txID %s, %w", txID, err) } - stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + stakerTx, ok := tx.Unsigned.(txs.Staker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } @@ -1500,7 +1500,7 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + stakerTx, ok := tx.Unsigned.(txs.Staker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } @@ -1552,7 +1552,7 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + stakerTx, ok := tx.Unsigned.(txs.Staker) if !ok { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } From b100a3df202ab1426355d6e3482b0ce59f5fe1f4 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 7 Dec 2023 14:31:44 +0100 Subject: [PATCH 24/25] explicit type casts --- vms/platformvm/state/state.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 8f03ebd8808f..671e812f0fa9 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1470,10 +1470,15 @@ func (s *state) loadCurrentValidators() error { return err } + scheduledStakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + if !ok { + return fmt.Errorf("expected tx type txs.ScheduledStaker but got %T", tx.Unsigned) + } + staker, err := NewCurrentStaker( txID, stakerTx, - stakerTx.(txs.ScheduledStaker).StartTime(), + scheduledStakerTx.StartTime(), metadata.PotentialReward) if err != nil { return err @@ -1505,8 +1510,13 @@ func (s *state) loadCurrentValidators() error { return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) } + scheduledStakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + if !ok { + return fmt.Errorf("expected tx type txs.ScheduledStaker but got %T", tx.Unsigned) + } + metadataBytes := subnetValidatorIt.Value() - startTime := stakerTx.(txs.ScheduledStaker).StartTime() + startTime := scheduledStakerTx.StartTime() metadata := &validatorMetadata{ txID: txID, // use the start time as the fallback value @@ -1565,10 +1575,15 @@ func (s *state) loadCurrentValidators() error { return err } + scheduledStakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + if !ok { + return fmt.Errorf("expected tx type txs.ScheduledStaker but got %T", tx.Unsigned) + } + staker, err := NewCurrentStaker( txID, stakerTx, - stakerTx.(txs.ScheduledStaker).StartTime(), + scheduledStakerTx.StartTime(), metadata.PotentialReward, ) if err != nil { From 85c41e6329c072d63a3d159b55fb41e2fca9e7fc Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Thu, 7 Dec 2023 15:55:17 -0500 Subject: [PATCH 25/25] reduce diff --- vms/platformvm/state/state.go | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 671e812f0fa9..c130326ef26b 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1455,9 +1455,9 @@ func (s *state) loadCurrentValidators() error { return fmt.Errorf("failed loading validator transaction txID %s, %w", txID, err) } - stakerTx, ok := tx.Unsigned.(txs.Staker) + stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) + return fmt.Errorf("expected tx type txs.ScheduledStaker but got %T", tx.Unsigned) } metadataBytes := validatorIt.Value() @@ -1470,15 +1470,10 @@ func (s *state) loadCurrentValidators() error { return err } - scheduledStakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) - if !ok { - return fmt.Errorf("expected tx type txs.ScheduledStaker but got %T", tx.Unsigned) - } - staker, err := NewCurrentStaker( txID, stakerTx, - scheduledStakerTx.StartTime(), + stakerTx.StartTime(), metadata.PotentialReward) if err != nil { return err @@ -1505,18 +1500,13 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) - if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) - } - - scheduledStakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) + stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) if !ok { return fmt.Errorf("expected tx type txs.ScheduledStaker but got %T", tx.Unsigned) } metadataBytes := subnetValidatorIt.Value() - startTime := scheduledStakerTx.StartTime() + startTime := stakerTx.StartTime() metadata := &validatorMetadata{ txID: txID, // use the start time as the fallback value @@ -1562,9 +1552,9 @@ func (s *state) loadCurrentValidators() error { return err } - stakerTx, ok := tx.Unsigned.(txs.Staker) + stakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) if !ok { - return fmt.Errorf("expected tx type txs.Staker but got %T", tx.Unsigned) + return fmt.Errorf("expected tx type txs.ScheduledStaker but got %T", tx.Unsigned) } metadata := &delegatorMetadata{ @@ -1575,15 +1565,10 @@ func (s *state) loadCurrentValidators() error { return err } - scheduledStakerTx, ok := tx.Unsigned.(txs.ScheduledStaker) - if !ok { - return fmt.Errorf("expected tx type txs.ScheduledStaker but got %T", tx.Unsigned) - } - staker, err := NewCurrentStaker( txID, stakerTx, - scheduledStakerTx.StartTime(), + stakerTx.StartTime(), metadata.PotentialReward, ) if err != nil {