From 0a2715f2178e429090a10ba6c503bb7107963ce9 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 15 Jul 2024 10:49:48 -0400 Subject: [PATCH 1/8] reduce diff --- vms/platformvm/txs/executor/staker_tx_verification.go | 6 ++---- vms/platformvm/txs/executor/standard_tx_executor.go | 9 +++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index 28ba0f78d4c6..eb50d200b3da 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -761,10 +761,8 @@ func verifyTransferSubnetOwnershipTx( var ( currentTimestamp = chainState.GetTimestamp() upgrades = backend.Config.UpgradeConfig - isDurangoActive = upgrades.IsDurangoActivated(currentTimestamp) ) - - if !isDurangoActive { + if !upgrades.IsDurangoActivated(currentTimestamp) { return ErrDurangoUpgradeNotActive } @@ -788,7 +786,7 @@ func verifyTransferSubnetOwnershipTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) + feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, upgrades, currentTimestamp) fee, err := feeCalculator.CalculateFee(sTx) if err != nil { return err diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 5c5e466dc049..8de6893cba03 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -570,10 +570,8 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { var ( currentTimestamp = e.State.GetTimestamp() upgrades = e.Backend.Config.UpgradeConfig - IsDurangoActive = upgrades.IsDurangoActivated(currentTimestamp) ) - - if !IsDurangoActive { + if !upgrades.IsDurangoActivated(currentTimestamp) { return ErrDurangoUpgradeNotActive } @@ -587,7 +585,7 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) + feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, upgrades, currentTimestamp) fee, err := feeCalculator.CalculateFee(e.Tx) if err != nil { return err @@ -617,13 +615,12 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { func (e *StandardTxExecutor) putStaker(stakerTx txs.Staker) error { var ( chainTime = e.State.GetTimestamp() - upgrades = e.Backend.Config.UpgradeConfig txID = e.Tx.ID() staker *state.Staker err error ) - if !upgrades.IsDurangoActivated(chainTime) { + if !e.Config.UpgradeConfig.IsDurangoActivated(chainTime) { // Pre-Durango, stakers set a future [StartTime] and are added to the // pending staker set. They are promoted to the current staker set once // the chain time reaches [StartTime]. From 730f72e995a8f85025c527f5c861599b6af0ff05 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 15 Jul 2024 17:04:04 +0200 Subject: [PATCH 2/8] Restructured fee calculator API (#3145) Co-authored-by: Stephen Buttolph --- vms/platformvm/service_test.go | 7 +- .../txs/executor/staker_tx_verification.go | 63 +++++--- .../txs/executor/standard_tx_executor.go | 55 ++++--- vms/platformvm/txs/fee/calculator.go | 139 +----------------- vms/platformvm/txs/fee/calculator_test.go | 6 +- vms/platformvm/txs/fee/static_calculator.go | 136 +++++++++++++++++ vms/platformvm/txs/txstest/context.go | 6 +- 7 files changed, 225 insertions(+), 187 deletions(-) create mode 100644 vms/platformvm/txs/fee/static_calculator.go diff --git a/vms/platformvm/service_test.go b/vms/platformvm/service_test.go index 69e94d0dee3e..94558a75314a 100644 --- a/vms/platformvm/service_test.go +++ b/vms/platformvm/service_test.go @@ -376,10 +376,9 @@ func TestGetBalance(t *testing.T) { require := require.New(t) service, _, _ := defaultService(t) - var ( - feeCalc = fee.NewStaticCalculator(service.vm.Config.StaticFeeConfig, service.vm.Config.UpgradeConfig) - createSubnetFee = feeCalc.CalculateFee(&txs.CreateSubnetTx{}, service.vm.clock.Time()) - ) + feeCalc := fee.NewStaticCalculator(service.vm.Config.StaticFeeConfig, service.vm.Config.UpgradeConfig, service.vm.clock.Time()) + createSubnetFee, err := feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) + require.NoError(err) // Ensure GetStake is correct for each of the genesis validators genesis, _ := defaultGenesis(t, service.vm.ctx.AVAXAssetID) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index 0aac4ad50f64..eb50d200b3da 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -164,9 +164,11 @@ func verifyAddValidatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(sTx) + if err != nil { + return nil, err + } if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -255,9 +257,11 @@ func verifyAddSubnetValidatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(sTx) + if err != nil { + return err + } if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -333,9 +337,11 @@ func verifyRemoveSubnetValidatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(sTx) + if err != nil { + return nil, false, err + } if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -451,9 +457,11 @@ func verifyAddDelegatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(sTx) + if err != nil { + return nil, err + } if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -571,9 +579,11 @@ func verifyAddPermissionlessValidatorTx( copy(outs[len(tx.Outs):], tx.StakeOuts) // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(sTx) + if err != nil { + return err + } if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -716,9 +726,11 @@ func verifyAddPermissionlessDelegatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(sTx) + if err != nil { + return err + } if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -746,7 +758,11 @@ func verifyTransferSubnetOwnershipTx( sTx *txs.Tx, tx *txs.TransferSubnetOwnershipTx, ) error { - if !backend.Config.UpgradeConfig.IsDurangoActivated(chainState.GetTimestamp()) { + var ( + currentTimestamp = chainState.GetTimestamp() + upgrades = backend.Config.UpgradeConfig + ) + if !upgrades.IsDurangoActivated(currentTimestamp) { return ErrDurangoUpgradeNotActive } @@ -770,10 +786,11 @@ func verifyTransferSubnetOwnershipTx( } // Verify the flowcheck - currentTimestamp := chainState.GetTimestamp() - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, upgrades, currentTimestamp) + fee, err := feeCalculator.CalculateFee(sTx) + if err != nil { + return err + } if err := backend.FlowChecker.VerifySpend( tx, chainState, diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 2de7d3392ba8..8de6893cba03 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -69,9 +69,11 @@ func (e *StandardTxExecutor) CreateChainTx(tx *txs.CreateChainTx) error { } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(e.Tx) + if err != nil { + return err + } if err := e.FlowChecker.VerifySpend( tx, e.State, @@ -117,9 +119,11 @@ func (e *StandardTxExecutor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(e.Tx) + if err != nil { + return err + } if err := e.FlowChecker.VerifySpend( tx, e.State, @@ -200,9 +204,11 @@ func (e *StandardTxExecutor) ImportTx(tx *txs.ImportTx) error { copy(ins[len(tx.Ins):], tx.ImportedInputs) // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(e.Tx) + if err != nil { + return err + } if err := e.FlowChecker.VerifySpendUTXOs( tx, utxos, @@ -259,9 +265,11 @@ func (e *StandardTxExecutor) ExportTx(tx *txs.ExportTx) error { } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(e.Tx) + if err != nil { + return err + } if err := e.FlowChecker.VerifySpend( tx, e.State, @@ -448,9 +456,11 @@ func (e *StandardTxExecutor) TransformSubnetTx(tx *txs.TransformSubnetTx) error } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) + fee, err := feeCalculator.CalculateFee(e.Tx) + if err != nil { + return err + } totalRewardAmount := tx.MaximumSupply - tx.InitialSupply if err := e.Backend.FlowChecker.VerifySpend( tx, @@ -557,7 +567,11 @@ func (e *StandardTxExecutor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwn } func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { - if !e.Backend.Config.UpgradeConfig.IsDurangoActivated(e.State.GetTimestamp()) { + var ( + currentTimestamp = e.State.GetTimestamp() + upgrades = e.Backend.Config.UpgradeConfig + ) + if !upgrades.IsDurangoActivated(currentTimestamp) { return ErrDurangoUpgradeNotActive } @@ -571,10 +585,11 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { } // Verify the flowcheck - currentTimestamp := e.State.GetTimestamp() - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig) - fee := feeCalculator.CalculateFee(tx, currentTimestamp) - + feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, upgrades, currentTimestamp) + fee, err := feeCalculator.CalculateFee(e.Tx) + if err != nil { + return err + } if err := e.FlowChecker.VerifySpend( tx, e.State, diff --git a/vms/platformvm/txs/fee/calculator.go b/vms/platformvm/txs/fee/calculator.go index f349f282f7ca..f33db9c1520f 100644 --- a/vms/platformvm/txs/fee/calculator.go +++ b/vms/platformvm/txs/fee/calculator.go @@ -3,140 +3,9 @@ package fee -import ( - "time" +import "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/platformvm/upgrade" -) - -var _ txs.Visitor = (*calculator)(nil) - -func NewStaticCalculator(config StaticConfig, upgradeTimes upgrade.Config) *Calculator { - return &Calculator{ - config: config, - upgradeTimes: upgradeTimes, - } -} - -type Calculator struct { - config StaticConfig - upgradeTimes upgrade.Config -} - -// [CalculateFee] returns the minimal fee needed to accept [tx], at chain time [time] -func (c *Calculator) CalculateFee(tx txs.UnsignedTx, time time.Time) uint64 { - tmp := &calculator{ - upgrades: c.upgradeTimes, - staticCfg: c.config, - time: time, - } - - // this is guaranteed to never return an error - _ = tx.Visit(tmp) - return tmp.fee -} - -// calculator is intentionally unexported and used through Calculator to provide -// a more convenient API -type calculator struct { - // Pre E-fork inputs - upgrades upgrade.Config - staticCfg StaticConfig - time time.Time - - // outputs of visitor execution - fee uint64 -} - -func (c *calculator) AddValidatorTx(*txs.AddValidatorTx) error { - c.fee = c.staticCfg.AddPrimaryNetworkValidatorFee - return nil -} - -func (c *calculator) AddSubnetValidatorTx(*txs.AddSubnetValidatorTx) error { - c.fee = c.staticCfg.AddSubnetValidatorFee - return nil -} - -func (c *calculator) AddDelegatorTx(*txs.AddDelegatorTx) error { - c.fee = c.staticCfg.AddPrimaryNetworkDelegatorFee - return nil -} - -func (c *calculator) CreateChainTx(*txs.CreateChainTx) error { - if c.upgrades.IsApricotPhase3Activated(c.time) { - c.fee = c.staticCfg.CreateBlockchainTxFee - } else { - c.fee = c.staticCfg.CreateAssetTxFee - } - return nil -} - -func (c *calculator) CreateSubnetTx(*txs.CreateSubnetTx) error { - if c.upgrades.IsApricotPhase3Activated(c.time) { - c.fee = c.staticCfg.CreateSubnetTxFee - } else { - c.fee = c.staticCfg.CreateAssetTxFee - } - return nil -} - -func (c *calculator) AdvanceTimeTx(*txs.AdvanceTimeTx) error { - c.fee = 0 // no fees - return nil -} - -func (c *calculator) RewardValidatorTx(*txs.RewardValidatorTx) error { - c.fee = 0 // no fees - return nil -} - -func (c *calculator) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { - c.fee = c.staticCfg.TxFee - return nil -} - -func (c *calculator) TransformSubnetTx(*txs.TransformSubnetTx) error { - c.fee = c.staticCfg.TransformSubnetTxFee - return nil -} - -func (c *calculator) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { - c.fee = c.staticCfg.TxFee - return nil -} - -func (c *calculator) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { - if tx.Subnet != constants.PrimaryNetworkID { - c.fee = c.staticCfg.AddSubnetValidatorFee - } else { - c.fee = c.staticCfg.AddPrimaryNetworkValidatorFee - } - return nil -} - -func (c *calculator) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { - if tx.Subnet != constants.PrimaryNetworkID { - c.fee = c.staticCfg.AddSubnetDelegatorFee - } else { - c.fee = c.staticCfg.AddPrimaryNetworkDelegatorFee - } - return nil -} - -func (c *calculator) BaseTx(*txs.BaseTx) error { - c.fee = c.staticCfg.TxFee - return nil -} - -func (c *calculator) ImportTx(*txs.ImportTx) error { - c.fee = c.staticCfg.TxFee - return nil -} - -func (c *calculator) ExportTx(*txs.ExportTx) error { - c.fee = c.staticCfg.TxFee - return nil +// Calculator is the interfaces that any fee Calculator must implement +type Calculator interface { + CalculateFee(tx *txs.Tx) (uint64, error) } diff --git a/vms/platformvm/txs/fee/calculator_test.go b/vms/platformvm/txs/fee/calculator_test.go index c25fec9073e8..454072e9df8d 100644 --- a/vms/platformvm/txs/fee/calculator_test.go +++ b/vms/platformvm/txs/fee/calculator_test.go @@ -188,8 +188,10 @@ func TestTxFees(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { uTx := tt.unsignedTx() - fc := NewStaticCalculator(feeTestsDefaultCfg, upgrades) - require.Equal(t, tt.expected, fc.CalculateFee(uTx, tt.chainTime)) + fc := NewStaticCalculator(feeTestsDefaultCfg, upgrades, tt.chainTime) + fee, err := fc.CalculateFee(&txs.Tx{Unsigned: uTx}) + require.NoError(t, err) + require.Equal(t, tt.expected, fee) }) } } diff --git a/vms/platformvm/txs/fee/static_calculator.go b/vms/platformvm/txs/fee/static_calculator.go new file mode 100644 index 000000000000..7bfb5cf799a0 --- /dev/null +++ b/vms/platformvm/txs/fee/static_calculator.go @@ -0,0 +1,136 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package fee + +import ( + "time" + + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/upgrade" +) + +var ( + _ Calculator = (*staticCalculator)(nil) + _ txs.Visitor = (*staticCalculator)(nil) +) + +func NewStaticCalculator( + config StaticConfig, + upgradeTimes upgrade.Config, + chainTime time.Time, +) Calculator { + return &staticCalculator{ + upgrades: upgradeTimes, + staticCfg: config, + time: chainTime, + } +} + +type staticCalculator struct { + // inputs + staticCfg StaticConfig + upgrades upgrade.Config + time time.Time + + // outputs of visitor execution + fee uint64 +} + +func (c *staticCalculator) CalculateFee(tx *txs.Tx) (uint64, error) { + c.fee = 0 // zero fee among different calculateFee invocations (unlike gas which gets cumulated) + err := tx.Unsigned.Visit(c) + return c.fee, err +} + +func (c *staticCalculator) AddValidatorTx(*txs.AddValidatorTx) error { + c.fee = c.staticCfg.AddPrimaryNetworkValidatorFee + return nil +} + +func (c *staticCalculator) AddSubnetValidatorTx(*txs.AddSubnetValidatorTx) error { + c.fee = c.staticCfg.AddSubnetValidatorFee + return nil +} + +func (c *staticCalculator) AddDelegatorTx(*txs.AddDelegatorTx) error { + c.fee = c.staticCfg.AddPrimaryNetworkDelegatorFee + return nil +} + +func (c *staticCalculator) CreateChainTx(*txs.CreateChainTx) error { + if c.upgrades.IsApricotPhase3Activated(c.time) { + c.fee = c.staticCfg.CreateBlockchainTxFee + } else { + c.fee = c.staticCfg.CreateAssetTxFee + } + return nil +} + +func (c *staticCalculator) CreateSubnetTx(*txs.CreateSubnetTx) error { + if c.upgrades.IsApricotPhase3Activated(c.time) { + c.fee = c.staticCfg.CreateSubnetTxFee + } else { + c.fee = c.staticCfg.CreateAssetTxFee + } + return nil +} + +func (c *staticCalculator) AdvanceTimeTx(*txs.AdvanceTimeTx) error { + c.fee = 0 // no fees + return nil +} + +func (c *staticCalculator) RewardValidatorTx(*txs.RewardValidatorTx) error { + c.fee = 0 // no fees + return nil +} + +func (c *staticCalculator) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { + c.fee = c.staticCfg.TxFee + return nil +} + +func (c *staticCalculator) TransformSubnetTx(*txs.TransformSubnetTx) error { + c.fee = c.staticCfg.TransformSubnetTxFee + return nil +} + +func (c *staticCalculator) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { + c.fee = c.staticCfg.TxFee + return nil +} + +func (c *staticCalculator) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { + if tx.Subnet != constants.PrimaryNetworkID { + c.fee = c.staticCfg.AddSubnetValidatorFee + } else { + c.fee = c.staticCfg.AddPrimaryNetworkValidatorFee + } + return nil +} + +func (c *staticCalculator) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { + if tx.Subnet != constants.PrimaryNetworkID { + c.fee = c.staticCfg.AddSubnetDelegatorFee + } else { + c.fee = c.staticCfg.AddPrimaryNetworkDelegatorFee + } + return nil +} + +func (c *staticCalculator) BaseTx(*txs.BaseTx) error { + c.fee = c.staticCfg.TxFee + return nil +} + +func (c *staticCalculator) ImportTx(*txs.ImportTx) error { + c.fee = c.staticCfg.TxFee + return nil +} + +func (c *staticCalculator) ExportTx(*txs.ExportTx) error { + c.fee = c.staticCfg.TxFee + return nil +} diff --git a/vms/platformvm/txs/txstest/context.go b/vms/platformvm/txs/txstest/context.go index ec2252a632e1..d8ca8c32853d 100644 --- a/vms/platformvm/txs/txstest/context.go +++ b/vms/platformvm/txs/txstest/context.go @@ -19,9 +19,9 @@ func newContext( timestamp time.Time, ) *builder.Context { var ( - feeCalc = fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig) - createSubnetFee = feeCalc.CalculateFee(&txs.CreateSubnetTx{}, timestamp) - createChainFee = feeCalc.CalculateFee(&txs.CreateChainTx{}, timestamp) + feeCalc = fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig, timestamp) + createSubnetFee, _ = feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) + createChainFee, _ = feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateChainTx{}}) ) return &builder.Context{ From 46442c91435ed594d65adead34232dddc3250f12 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 15 Jul 2024 12:28:45 -0400 Subject: [PATCH 3/8] nits --- vms/platformvm/block/executor/verifier.go | 7 ------- vms/platformvm/service_test.go | 4 ++-- vms/platformvm/state/chain_time_helpers.go | 10 ++++++---- vms/platformvm/txs/txstest/context.go | 6 +++--- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/vms/platformvm/block/executor/verifier.go b/vms/platformvm/block/executor/verifier.go index b4f5d366bef4..2e5626a76d14 100644 --- a/vms/platformvm/block/executor/verifier.go +++ b/vms/platformvm/block/executor/verifier.go @@ -357,9 +357,6 @@ func (v *verifier) abortBlock(b block.Block) error { statelessBlock: b, onAcceptState: onAbortState, timestamp: onAbortState.GetTimestamp(), - - // blockComplexity not set. We'll assign same complexity - // as proposal blocks upon acceptance } return nil } @@ -377,9 +374,6 @@ func (v *verifier) commitBlock(b block.Block) error { statelessBlock: b, onAcceptState: onCommitState, timestamp: onCommitState.GetTimestamp(), - - // blockComplexity not set. We'll assign same complexity - // as proposal blocks upon acceptance } return nil } @@ -475,7 +469,6 @@ func (v *verifier) processStandardTxs(txs []*txs.Tx, feeCalculator fee.Calculato funcs = make([]func(), 0, len(txs)) atomicRequests = make(map[ids.ID]*atomic.Requests) ) - for _, tx := range txs { txExecutor := executor.StandardTxExecutor{ Backend: v.txExecutorBackend, diff --git a/vms/platformvm/service_test.go b/vms/platformvm/service_test.go index 377e0fce9c4a..ccda2c6c054b 100644 --- a/vms/platformvm/service_test.go +++ b/vms/platformvm/service_test.go @@ -375,9 +375,9 @@ func TestGetBalance(t *testing.T) { require := require.New(t) service, _, _ := defaultService(t) - feeCalc, err := state.PickFeeCalculator(&service.vm.Config, service.vm.state) + feeCalculator, err := state.PickFeeCalculator(&service.vm.Config, service.vm.state) require.NoError(err) - createSubnetFee, err := feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) + createSubnetFee, err := feeCalculator.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) require.NoError(err) // Ensure GetStake is correct for each of the genesis validators diff --git a/vms/platformvm/state/chain_time_helpers.go b/vms/platformvm/state/chain_time_helpers.go index 9ac7a6c7c1f2..22fa97a7ac3c 100644 --- a/vms/platformvm/state/chain_time_helpers.go +++ b/vms/platformvm/state/chain_time_helpers.go @@ -71,9 +71,11 @@ func GetNextStakerChangeTime(state Chain) (time.Time, error) { } } -// [PickFeeCalculator] creates either a static or a dynamic fee calculator, depending on the active upgrade -// [PickFeeCalculator] does not modify [state] +// PickFeeCalculator creates either a static or a dynamic fee calculator, +// depending on the active upgrade. +// +// PickFeeCalculator does not modify [state]. func PickFeeCalculator(cfg *config.Config, state Chain) (fee.Calculator, error) { - childBlkTime := state.GetTimestamp() - return fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig, childBlkTime), nil + timestamp := state.GetTimestamp() + return fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig, timestamp), nil } diff --git a/vms/platformvm/txs/txstest/context.go b/vms/platformvm/txs/txstest/context.go index d8ca8c32853d..fb8181f7e39c 100644 --- a/vms/platformvm/txs/txstest/context.go +++ b/vms/platformvm/txs/txstest/context.go @@ -19,9 +19,9 @@ func newContext( timestamp time.Time, ) *builder.Context { var ( - feeCalc = fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig, timestamp) - createSubnetFee, _ = feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) - createChainFee, _ = feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateChainTx{}}) + feeCalculator = fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig, timestamp) + createSubnetFee, _ = feeCalculator.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) + createChainFee, _ = feeCalculator.CalculateFee(&txs.Tx{Unsigned: &txs.CreateChainTx{}}) ) return &builder.Context{ From d288bb5798c427717bd1cb90a02fe875a8a623da Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 15 Jul 2024 12:30:06 -0400 Subject: [PATCH 4/8] nit --- vms/platformvm/block/executor/verifier.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vms/platformvm/block/executor/verifier.go b/vms/platformvm/block/executor/verifier.go index 2e5626a76d14..9824289329b5 100644 --- a/vms/platformvm/block/executor/verifier.go +++ b/vms/platformvm/block/executor/verifier.go @@ -168,9 +168,9 @@ func (v *verifier) ApricotProposalBlock(b *block.ApricotProposalBlock) error { } var ( - staticFeesCfg = v.txExecutorBackend.Config.StaticFeeConfig - upgrades = v.txExecutorBackend.Config.UpgradeConfig - feeCalculator = fee.NewStaticCalculator(staticFeesCfg, upgrades, onCommitState.GetTimestamp()) + staticFeeConfig = v.txExecutorBackend.Config.StaticFeeConfig + upgradeConfig = v.txExecutorBackend.Config.UpgradeConfig + feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, onCommitState.GetTimestamp()) ) return v.proposalBlock(b, nil, onCommitState, onAbortState, feeCalculator, nil, nil, nil) } @@ -187,9 +187,9 @@ func (v *verifier) ApricotStandardBlock(b *block.ApricotStandardBlock) error { } var ( - staticFeesCfg = v.txExecutorBackend.Config.StaticFeeConfig - upgrades = v.txExecutorBackend.Config.UpgradeConfig - feeCalculator = fee.NewStaticCalculator(staticFeesCfg, upgrades, onAcceptState.GetTimestamp()) + staticFeeConfig = v.txExecutorBackend.Config.StaticFeeConfig + upgradeConfig = v.txExecutorBackend.Config.UpgradeConfig + feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, onAcceptState.GetTimestamp()) ) return v.standardBlock(b, feeCalculator, onAcceptState) } From 885bea03f91661181af8a0addbb4ac8c6f7cefc5 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 15 Jul 2024 12:31:44 -0400 Subject: [PATCH 5/8] nit --- vms/platformvm/block/executor/verifier.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vms/platformvm/block/executor/verifier.go b/vms/platformvm/block/executor/verifier.go index 9824289329b5..85e71dd3d973 100644 --- a/vms/platformvm/block/executor/verifier.go +++ b/vms/platformvm/block/executor/verifier.go @@ -170,7 +170,8 @@ func (v *verifier) ApricotProposalBlock(b *block.ApricotProposalBlock) error { var ( staticFeeConfig = v.txExecutorBackend.Config.StaticFeeConfig upgradeConfig = v.txExecutorBackend.Config.UpgradeConfig - feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, onCommitState.GetTimestamp()) + timestamp = onCommitState.GetTimestamp() // Equal to parent timestamp + feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, timestamp) ) return v.proposalBlock(b, nil, onCommitState, onAbortState, feeCalculator, nil, nil, nil) } @@ -189,7 +190,8 @@ func (v *verifier) ApricotStandardBlock(b *block.ApricotStandardBlock) error { var ( staticFeeConfig = v.txExecutorBackend.Config.StaticFeeConfig upgradeConfig = v.txExecutorBackend.Config.UpgradeConfig - feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, onAcceptState.GetTimestamp()) + timestamp = onAcceptState.GetTimestamp() + feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, timestamp) ) return v.standardBlock(b, feeCalculator, onAcceptState) } From 0941ecbb3d5aa40476c0ae37cb46ef4dad492ab4 Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Mon, 15 Jul 2024 12:33:03 -0400 Subject: [PATCH 6/8] nit --- vms/platformvm/block/executor/verifier.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vms/platformvm/block/executor/verifier.go b/vms/platformvm/block/executor/verifier.go index 85e71dd3d973..fcd38a9d72be 100644 --- a/vms/platformvm/block/executor/verifier.go +++ b/vms/platformvm/block/executor/verifier.go @@ -190,7 +190,7 @@ func (v *verifier) ApricotStandardBlock(b *block.ApricotStandardBlock) error { var ( staticFeeConfig = v.txExecutorBackend.Config.StaticFeeConfig upgradeConfig = v.txExecutorBackend.Config.UpgradeConfig - timestamp = onAcceptState.GetTimestamp() + timestamp = onAcceptState.GetTimestamp() // Equal to parent timestamp feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, timestamp) ) return v.standardBlock(b, feeCalculator, onAcceptState) From 444a3e919f7b7e327a4d2f1fa17fd233ad9e6fca Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 15 Jul 2024 18:51:01 +0200 Subject: [PATCH 7/8] P-Chain: Block-level fee Calculator (#3032) Signed-off-by: Alberto Benegiamo Signed-off-by: Joshua Kim <20001595+joshua-kim@users.noreply.github.com> Co-authored-by: Joshua Kim <20001595+joshua-kim@users.noreply.github.com> Co-authored-by: Stephen Buttolph --- vms/platformvm/block/builder/builder.go | 13 +- vms/platformvm/block/builder/helpers_test.go | 11 +- vms/platformvm/block/executor/helpers_test.go | 14 +- vms/platformvm/block/executor/manager.go | 12 +- vms/platformvm/block/executor/verifier.go | 52 ++- vms/platformvm/service_test.go | 6 +- vms/platformvm/state/chain_time_helpers.go | 11 + .../txs/executor/advance_time_test.go | 42 +++ .../txs/executor/atomic_tx_executor.go | 9 +- .../txs/executor/create_chain_test.go | 52 ++- .../txs/executor/create_subnet_test.go | 10 +- vms/platformvm/txs/executor/export_test.go | 10 +- vms/platformvm/txs/executor/helpers_test.go | 10 +- vms/platformvm/txs/executor/import_test.go | 10 +- .../txs/executor/proposal_tx_executor.go | 7 +- .../txs/executor/proposal_tx_executor_test.go | 48 +++ .../txs/executor/reward_validator_test.go | 24 ++ .../txs/executor/staker_tx_verification.go | 14 +- .../executor/staker_tx_verification_test.go | 37 +- .../txs/executor/standard_tx_executor.go | 30 +- .../txs/executor/standard_tx_executor_test.go | 355 ++++++++++++------ vms/platformvm/txs/txstest/context.go | 6 +- 22 files changed, 573 insertions(+), 210 deletions(-) diff --git a/vms/platformvm/block/builder/builder.go b/vms/platformvm/block/builder/builder.go index a445bb52cb1b..28fb4958bb57 100644 --- a/vms/platformvm/block/builder/builder.go +++ b/vms/platformvm/block/builder/builder.go @@ -331,11 +331,15 @@ func packBlockTxs( return nil, err } + feeCalculator, err := state.PickFeeCalculator(backend.Config, stateDiff) + if err != nil { + return nil, err + } + var ( blockTxs []*txs.Tx inputs set.Set[ids.ID] ) - for { tx, exists := mempool.Peek() if !exists { @@ -355,9 +359,10 @@ func packBlockTxs( } executor := &txexecutor.StandardTxExecutor{ - Backend: backend, - State: txDiff, - Tx: tx, + Backend: backend, + State: txDiff, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(executor) diff --git a/vms/platformvm/block/builder/helpers_test.go b/vms/platformvm/block/builder/helpers_test.go index eb80a9ffc4d3..df2d620c6eed 100644 --- a/vms/platformvm/block/builder/helpers_test.go +++ b/vms/platformvm/block/builder/helpers_test.go @@ -259,15 +259,20 @@ func addSubnet(t *testing.T, env *environment) { stateDiff, err := state.NewDiff(genesisID, env.blkManager) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + require.NoError(err) + executor := txexecutor.StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: testSubnet1, + Backend: &env.backend, + State: stateDiff, + FeeCalculator: feeCalculator, + Tx: testSubnet1, } require.NoError(testSubnet1.Unsigned.Visit(&executor)) stateDiff.AddTx(testSubnet1, status.Committed) require.NoError(stateDiff.Apply(env.state)) + require.NoError(env.state.Commit()) } func defaultState( diff --git a/vms/platformvm/block/executor/helpers_test.go b/vms/platformvm/block/executor/helpers_test.go index a8c276579c08..80dca6745fcc 100644 --- a/vms/platformvm/block/executor/helpers_test.go +++ b/vms/platformvm/block/executor/helpers_test.go @@ -280,11 +280,16 @@ func addSubnet(env *environment) { if err != nil { panic(err) } + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + if err != nil { + panic(err) + } executor := executor.StandardTxExecutor{ - Backend: env.backend, - State: stateDiff, - Tx: testSubnet1, + Backend: env.backend, + State: stateDiff, + FeeCalculator: feeCalculator, + Tx: testSubnet1, } err = testSubnet1.Unsigned.Visit(&executor) if err != nil { @@ -295,6 +300,9 @@ func addSubnet(env *environment) { if err := stateDiff.Apply(env.state); err != nil { panic(err) } + if err := env.state.Commit(); err != nil { + panic(err) + } } func defaultState( diff --git a/vms/platformvm/block/executor/manager.go b/vms/platformvm/block/executor/manager.go index 80e3e4503139..82580c3b52b9 100644 --- a/vms/platformvm/block/executor/manager.go +++ b/vms/platformvm/block/executor/manager.go @@ -142,10 +142,16 @@ func (m *manager) VerifyTx(tx *txs.Tx) error { return err } + feeCalculator, err := state.PickFeeCalculator(m.txExecutorBackend.Config, stateDiff) + if err != nil { + return err + } + return tx.Unsigned.Visit(&executor.StandardTxExecutor{ - Backend: m.txExecutorBackend, - State: stateDiff, - Tx: tx, + Backend: m.txExecutorBackend, + State: stateDiff, + FeeCalculator: feeCalculator, + Tx: tx, }) } diff --git a/vms/platformvm/block/executor/verifier.go b/vms/platformvm/block/executor/verifier.go index 3feccf4e4c96..fcd38a9d72be 100644 --- a/vms/platformvm/block/executor/verifier.go +++ b/vms/platformvm/block/executor/verifier.go @@ -15,6 +15,7 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/platformvm/txs" "github.com/ava-labs/avalanchego/vms/platformvm/txs/executor" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/fee" ) var ( @@ -66,7 +67,17 @@ func (v *verifier) BanffProposalBlock(b *block.BanffProposalBlock) error { return err } - inputs, atomicRequests, onAcceptFunc, err := v.processStandardTxs(b.Transactions, onDecisionState, b.Parent()) + feeCalculator, err := state.PickFeeCalculator(v.txExecutorBackend.Config, onDecisionState) + if err != nil { + return err + } + + inputs, atomicRequests, onAcceptFunc, err := v.processStandardTxs( + b.Transactions, + feeCalculator, + onDecisionState, + b.Parent(), + ) if err != nil { return err } @@ -86,6 +97,7 @@ func (v *verifier) BanffProposalBlock(b *block.BanffProposalBlock) error { onDecisionState, onCommitState, onAbortState, + feeCalculator, inputs, atomicRequests, onAcceptFunc, @@ -119,7 +131,11 @@ func (v *verifier) BanffStandardBlock(b *block.BanffStandardBlock) error { return errBanffStandardBlockWithoutChanges } - return v.standardBlock(&b.ApricotStandardBlock, onAcceptState) + feeCalculator, err := state.PickFeeCalculator(v.txExecutorBackend.Config, onAcceptState) + if err != nil { + return err + } + return v.standardBlock(&b.ApricotStandardBlock, feeCalculator, onAcceptState) } func (v *verifier) ApricotAbortBlock(b *block.ApricotAbortBlock) error { @@ -151,7 +167,13 @@ func (v *verifier) ApricotProposalBlock(b *block.ApricotProposalBlock) error { return err } - return v.proposalBlock(b, nil, onCommitState, onAbortState, nil, nil, nil) + var ( + staticFeeConfig = v.txExecutorBackend.Config.StaticFeeConfig + upgradeConfig = v.txExecutorBackend.Config.UpgradeConfig + timestamp = onCommitState.GetTimestamp() // Equal to parent timestamp + feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, timestamp) + ) + return v.proposalBlock(b, nil, onCommitState, onAbortState, feeCalculator, nil, nil, nil) } func (v *verifier) ApricotStandardBlock(b *block.ApricotStandardBlock) error { @@ -165,7 +187,13 @@ func (v *verifier) ApricotStandardBlock(b *block.ApricotStandardBlock) error { return err } - return v.standardBlock(b, onAcceptState) + var ( + staticFeeConfig = v.txExecutorBackend.Config.StaticFeeConfig + upgradeConfig = v.txExecutorBackend.Config.UpgradeConfig + timestamp = onAcceptState.GetTimestamp() // Equal to parent timestamp + feeCalculator = fee.NewStaticCalculator(staticFeeConfig, upgradeConfig, timestamp) + ) + return v.standardBlock(b, feeCalculator, onAcceptState) } func (v *verifier) ApricotAtomicBlock(b *block.ApricotAtomicBlock) error { @@ -187,8 +215,10 @@ func (v *verifier) ApricotAtomicBlock(b *block.ApricotAtomicBlock) error { ) } + feeCalculator := fee.NewStaticCalculator(v.txExecutorBackend.Config.StaticFeeConfig, v.txExecutorBackend.Config.UpgradeConfig, currentTimestamp) atomicExecutor := executor.AtomicTxExecutor{ Backend: v.txExecutorBackend, + FeeCalculator: feeCalculator, ParentID: parentID, StateVersions: v, Tx: b.Tx, @@ -356,6 +386,7 @@ func (v *verifier) proposalBlock( onDecisionState state.Diff, onCommitState state.Diff, onAbortState state.Diff, + feeCalculator fee.Calculator, inputs set.Set[ids.ID], atomicRequests map[ids.ID]*atomic.Requests, onAcceptFunc func(), @@ -364,6 +395,7 @@ func (v *verifier) proposalBlock( OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: v.txExecutorBackend, + FeeCalculator: feeCalculator, Tx: b.Tx, } @@ -403,9 +435,10 @@ func (v *verifier) proposalBlock( // standardBlock populates the state of this block if [nil] is returned func (v *verifier) standardBlock( b *block.ApricotStandardBlock, + feeCalculator fee.Calculator, onAcceptState state.Diff, ) error { - inputs, atomicRequests, onAcceptFunc, err := v.processStandardTxs(b.Transactions, onAcceptState, b.Parent()) + inputs, atomicRequests, onAcceptFunc, err := v.processStandardTxs(b.Transactions, feeCalculator, onAcceptState, b.Parent()) if err != nil { return err } @@ -426,7 +459,7 @@ func (v *verifier) standardBlock( return nil } -func (v *verifier) processStandardTxs(txs []*txs.Tx, state state.Diff, parentID ids.ID) ( +func (v *verifier) processStandardTxs(txs []*txs.Tx, feeCalculator fee.Calculator, state state.Diff, parentID ids.ID) ( set.Set[ids.ID], map[ids.ID]*atomic.Requests, func(), @@ -440,9 +473,10 @@ func (v *verifier) processStandardTxs(txs []*txs.Tx, state state.Diff, parentID ) for _, tx := range txs { txExecutor := executor.StandardTxExecutor{ - Backend: v.txExecutorBackend, - State: state, - Tx: tx, + Backend: v.txExecutorBackend, + State: state, + FeeCalculator: feeCalculator, + Tx: tx, } if err := tx.Unsigned.Visit(&txExecutor); err != nil { txID := tx.ID() diff --git a/vms/platformvm/service_test.go b/vms/platformvm/service_test.go index 94558a75314a..ccda2c6c054b 100644 --- a/vms/platformvm/service_test.go +++ b/vms/platformvm/service_test.go @@ -38,7 +38,6 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/status" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/platformvm/txs/fee" "github.com/ava-labs/avalanchego/vms/platformvm/txs/txstest" "github.com/ava-labs/avalanchego/vms/secp256k1fx" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -376,8 +375,9 @@ func TestGetBalance(t *testing.T) { require := require.New(t) service, _, _ := defaultService(t) - feeCalc := fee.NewStaticCalculator(service.vm.Config.StaticFeeConfig, service.vm.Config.UpgradeConfig, service.vm.clock.Time()) - createSubnetFee, err := feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) + feeCalculator, err := state.PickFeeCalculator(&service.vm.Config, service.vm.state) + require.NoError(err) + createSubnetFee, err := feeCalculator.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) require.NoError(err) // Ensure GetStake is correct for each of the genesis validators diff --git a/vms/platformvm/state/chain_time_helpers.go b/vms/platformvm/state/chain_time_helpers.go index 036eb168d73d..22fa97a7ac3c 100644 --- a/vms/platformvm/state/chain_time_helpers.go +++ b/vms/platformvm/state/chain_time_helpers.go @@ -9,6 +9,8 @@ import ( "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/utils/timer/mockable" + "github.com/ava-labs/avalanchego/vms/platformvm/config" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/fee" ) func NextBlockTime(state Chain, clk *mockable.Clock) (time.Time, bool, error) { @@ -68,3 +70,12 @@ func GetNextStakerChangeTime(state Chain) (time.Time, error) { return time.Time{}, database.ErrNotFound } } + +// PickFeeCalculator creates either a static or a dynamic fee calculator, +// depending on the active upgrade. +// +// PickFeeCalculator does not modify [state]. +func PickFeeCalculator(cfg *config.Config, state Chain) (fee.Calculator, error) { + timestamp := state.GetTimestamp() + return fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig, timestamp), nil +} diff --git a/vms/platformvm/txs/executor/advance_time_test.go b/vms/platformvm/txs/executor/advance_time_test.go index 48f4426276b2..0f853cebcce7 100644 --- a/vms/platformvm/txs/executor/advance_time_test.go +++ b/vms/platformvm/txs/executor/advance_time_test.go @@ -66,10 +66,14 @@ func TestAdvanceTimeTxUpdatePrimaryNetworkStakers(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -112,10 +116,14 @@ func TestAdvanceTimeTxTimestampTooEarly(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -147,10 +155,14 @@ func TestAdvanceTimeTxTimestampTooLate(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -176,10 +188,14 @@ func TestAdvanceTimeTxTimestampTooLate(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -418,10 +434,14 @@ func TestAdvanceTimeTxUpdateStakers(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -552,10 +572,14 @@ func TestAdvanceTimeTxRemoveSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -631,10 +655,14 @@ func TestTrackedSubnet(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -679,10 +707,14 @@ func TestAdvanceTimeTxDelegatorStakerWeight(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -742,6 +774,7 @@ func TestAdvanceTimeTxDelegatorStakerWeight(t *testing.T) { OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -780,10 +813,14 @@ func TestAdvanceTimeTxDelegatorStakers(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -842,6 +879,7 @@ func TestAdvanceTimeTxDelegatorStakers(t *testing.T) { OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -877,10 +915,14 @@ func TestAdvanceTimeTxAfterBanff(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) + executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) diff --git a/vms/platformvm/txs/executor/atomic_tx_executor.go b/vms/platformvm/txs/executor/atomic_tx_executor.go index 2a35cb45eeab..f62abd21f818 100644 --- a/vms/platformvm/txs/executor/atomic_tx_executor.go +++ b/vms/platformvm/txs/executor/atomic_tx_executor.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/fee" ) var _ txs.Visitor = (*AtomicTxExecutor)(nil) @@ -18,6 +19,7 @@ var _ txs.Visitor = (*AtomicTxExecutor)(nil) type AtomicTxExecutor struct { // inputs, to be filled before visitor methods are called *Backend + FeeCalculator fee.Calculator ParentID ids.ID StateVersions state.Versions Tx *txs.Tx @@ -99,9 +101,10 @@ func (e *AtomicTxExecutor) atomicTx(tx txs.UnsignedTx) error { e.OnAccept = onAccept executor := StandardTxExecutor{ - Backend: e.Backend, - State: e.OnAccept, - Tx: e.Tx, + Backend: e.Backend, + State: e.OnAccept, + FeeCalculator: e.FeeCalculator, + Tx: e.Tx, } err = tx.Visit(&executor) e.Inputs = executor.Inputs diff --git a/vms/platformvm/txs/executor/create_chain_test.go b/vms/platformvm/txs/executor/create_chain_test.go index 4d52432ab8fa..7f29a03f6884 100644 --- a/vms/platformvm/txs/executor/create_chain_test.go +++ b/vms/platformvm/txs/executor/create_chain_test.go @@ -50,11 +50,14 @@ func TestCreateChainTxInsufficientControlSigs(t *testing.T) { stateDiff, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, errUnauthorizedSubnetModification) @@ -91,10 +94,13 @@ func TestCreateChainTxWrongControlSig(t *testing.T) { stateDiff, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, errUnauthorizedSubnetModification) @@ -125,10 +131,16 @@ func TestCreateChainTxNoSuchSubnet(t *testing.T) { stateDiff, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + builderDiff, err := state.NewDiffOn(stateDiff) + require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, builderDiff) + require.NoError(err) + executor := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, database.ErrNotFound) @@ -156,10 +168,16 @@ func TestCreateChainTxValid(t *testing.T) { stateDiff, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + builderDiff, err := state.NewDiffOn(stateDiff) + require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, builderDiff) + require.NoError(err) + executor := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) } @@ -226,10 +244,14 @@ func TestCreateChainTxAP3FeeChange(t *testing.T) { stateDiff.SetTimestamp(test.time) + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + require.NoError(err) + executor := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, test.expectedError) diff --git a/vms/platformvm/txs/executor/create_subnet_test.go b/vms/platformvm/txs/executor/create_subnet_test.go index 8ba9b529d565..9a579ec36376 100644 --- a/vms/platformvm/txs/executor/create_subnet_test.go +++ b/vms/platformvm/txs/executor/create_subnet_test.go @@ -80,10 +80,14 @@ func TestCreateSubnetTxAP3FeeChange(t *testing.T) { stateDiff.SetTimestamp(test.time) + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + require.NoError(err) + executor := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, test.expectedErr) diff --git a/vms/platformvm/txs/executor/export_test.go b/vms/platformvm/txs/executor/export_test.go index f962c1af8814..1c4dadd9002d 100644 --- a/vms/platformvm/txs/executor/export_test.go +++ b/vms/platformvm/txs/executor/export_test.go @@ -77,10 +77,14 @@ func TestNewExportTx(t *testing.T) { stateDiff.SetTimestamp(tt.timestamp) + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + require.NoError(err) + verifier := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: tx, } require.NoError(tx.Unsigned.Visit(&verifier)) }) diff --git a/vms/platformvm/txs/executor/helpers_test.go b/vms/platformvm/txs/executor/helpers_test.go index 557fb691417c..a3b3033df44a 100644 --- a/vms/platformvm/txs/executor/helpers_test.go +++ b/vms/platformvm/txs/executor/helpers_test.go @@ -230,10 +230,14 @@ func addSubnet(t *testing.T, env *environment) { stateDiff, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, env.state) + require.NoError(err) + executor := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: testSubnet1, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: testSubnet1, } require.NoError(testSubnet1.Unsigned.Visit(&executor)) diff --git a/vms/platformvm/txs/executor/import_test.go b/vms/platformvm/txs/executor/import_test.go index 7e8db3da48f0..b972d6d240c4 100644 --- a/vms/platformvm/txs/executor/import_test.go +++ b/vms/platformvm/txs/executor/import_test.go @@ -160,10 +160,14 @@ func TestNewImportTx(t *testing.T) { stateDiff.SetTimestamp(tt.timestamp) + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + require.NoError(err) + verifier := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: stateDiff, + Tx: tx, } require.NoError(tx.Unsigned.Visit(&verifier)) }) diff --git a/vms/platformvm/txs/executor/proposal_tx_executor.go b/vms/platformvm/txs/executor/proposal_tx_executor.go index c54b8207fb06..d7b76d10c615 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/reward" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/fee" ) const ( @@ -45,7 +46,8 @@ var ( type ProposalTxExecutor struct { // inputs, to be filled before visitor methods are called *Backend - Tx *txs.Tx + FeeCalculator fee.Calculator + Tx *txs.Tx // [OnCommitState] is the state used for validation. // [OnCommitState] is modified by this struct's methods to // reflect changes made to the state if the proposal is committed. @@ -114,6 +116,7 @@ func (e *ProposalTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { onAbortOuts, err := verifyAddValidatorTx( e.Backend, + e.FeeCalculator, e.OnCommitState, e.Tx, tx, @@ -161,6 +164,7 @@ func (e *ProposalTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) if err := verifyAddSubnetValidatorTx( e.Backend, + e.FeeCalculator, e.OnCommitState, e.Tx, tx, @@ -207,6 +211,7 @@ func (e *ProposalTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { onAbortOuts, err := verifyAddDelegatorTx( e.Backend, + e.FeeCalculator, e.OnCommitState, e.Tx, tx, diff --git a/vms/platformvm/txs/executor/proposal_tx_executor_test.go b/vms/platformvm/txs/executor/proposal_tx_executor_test.go index cb547d4d589d..af249e244e9a 100644 --- a/vms/platformvm/txs/executor/proposal_tx_executor_test.go +++ b/vms/platformvm/txs/executor/proposal_tx_executor_test.go @@ -271,10 +271,13 @@ func TestProposalTxExecuteAddDelegator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -316,10 +319,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -353,10 +359,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -410,10 +419,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -462,10 +474,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -497,10 +512,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -532,10 +550,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) @@ -569,10 +590,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -638,10 +662,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: duplicateSubnetTx, } err = duplicateSubnetTx.Unsigned.Visit(&executor) @@ -683,10 +710,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -722,10 +752,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -771,10 +804,13 @@ func TestProposalTxExecuteAddSubnetValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -817,10 +853,13 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -855,10 +894,13 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -907,10 +949,13 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) @@ -951,10 +996,13 @@ func TestProposalTxExecuteAddValidator(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) executor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&executor) diff --git a/vms/platformvm/txs/executor/reward_validator_test.go b/vms/platformvm/txs/executor/reward_validator_test.go index 88b7b0b8a368..017aaf739290 100644 --- a/vms/platformvm/txs/executor/reward_validator_test.go +++ b/vms/platformvm/txs/executor/reward_validator_test.go @@ -61,10 +61,13 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAbortState) + require.NoError(err) txExecutor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&txExecutor) @@ -87,6 +90,7 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&txExecutor) @@ -106,6 +110,7 @@ func TestRewardValidatorTxExecuteOnCommit(t *testing.T) { OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&txExecutor)) @@ -161,10 +166,13 @@ func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAbortState) + require.NoError(err) txExecutor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&txExecutor) @@ -181,6 +189,7 @@ func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } err = tx.Unsigned.Visit(&txExecutor) @@ -200,6 +209,7 @@ func TestRewardValidatorTxExecuteOnAbort(t *testing.T) { OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&txExecutor)) @@ -317,10 +327,13 @@ func TestRewardDelegatorTxExecuteOnCommitPreDelegateeDeferral(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) txExecutor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&txExecutor)) @@ -460,10 +473,13 @@ func TestRewardDelegatorTxExecuteOnCommitPostDelegateeDeferral(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) txExecutor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&txExecutor)) @@ -512,6 +528,7 @@ func TestRewardDelegatorTxExecuteOnCommitPostDelegateeDeferral(t *testing.T) { OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&txExecutor)) @@ -683,10 +700,13 @@ func TestRewardDelegatorTxAndValidatorTxExecuteOnCommitPostDelegateeDeferral(t * delOnAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, delOnCommitState) + require.NoError(err) txExecutor := ProposalTxExecutor{ OnCommitState: delOnCommitState, OnAbortState: delOnAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&txExecutor)) @@ -708,6 +728,7 @@ func TestRewardDelegatorTxAndValidatorTxExecuteOnCommitPostDelegateeDeferral(t * OnCommitState: vdrOnCommitState, OnAbortState: vdrOnAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&txExecutor)) @@ -845,10 +866,13 @@ func TestRewardDelegatorTxExecuteOnAbort(t *testing.T) { onAbortState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onCommitState) + require.NoError(err) txExecutor := ProposalTxExecutor{ OnCommitState: onCommitState, OnAbortState: onAbortState, Backend: &env.backend, + FeeCalculator: feeCalculator, Tx: tx, } require.NoError(tx.Unsigned.Visit(&txExecutor)) diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index eb50d200b3da..b31b73ce543b 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -90,6 +90,7 @@ func verifySubnetValidatorPrimaryNetworkRequirements( // added to the staking set. func verifyAddValidatorTx( backend *Backend, + feeCalculator fee.Calculator, chainState state.Chain, sTx *txs.Tx, tx *txs.AddValidatorTx, @@ -164,7 +165,6 @@ func verifyAddValidatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) fee, err := feeCalculator.CalculateFee(sTx) if err != nil { return nil, err @@ -189,6 +189,7 @@ func verifyAddValidatorTx( // AddSubnetValidatorTx. func verifyAddSubnetValidatorTx( backend *Backend, + feeCalculator fee.Calculator, chainState state.Chain, sTx *txs.Tx, tx *txs.AddSubnetValidatorTx, @@ -257,7 +258,6 @@ func verifyAddSubnetValidatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) fee, err := feeCalculator.CalculateFee(sTx) if err != nil { return err @@ -288,6 +288,7 @@ func verifyAddSubnetValidatorTx( // * The flow checker passes. func verifyRemoveSubnetValidatorTx( backend *Backend, + feeCalculator fee.Calculator, chainState state.Chain, sTx *txs.Tx, tx *txs.RemoveSubnetValidatorTx, @@ -337,7 +338,6 @@ func verifyRemoveSubnetValidatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) fee, err := feeCalculator.CalculateFee(sTx) if err != nil { return nil, false, err @@ -363,6 +363,7 @@ func verifyRemoveSubnetValidatorTx( // added to the staking set. func verifyAddDelegatorTx( backend *Backend, + feeCalculator fee.Calculator, chainState state.Chain, sTx *txs.Tx, tx *txs.AddDelegatorTx, @@ -457,7 +458,6 @@ func verifyAddDelegatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) fee, err := feeCalculator.CalculateFee(sTx) if err != nil { return nil, err @@ -482,6 +482,7 @@ func verifyAddDelegatorTx( // AddPermissionlessValidatorTx. func verifyAddPermissionlessValidatorTx( backend *Backend, + feeCalculator fee.Calculator, chainState state.Chain, sTx *txs.Tx, tx *txs.AddPermissionlessValidatorTx, @@ -579,7 +580,6 @@ func verifyAddPermissionlessValidatorTx( copy(outs[len(tx.Outs):], tx.StakeOuts) // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) fee, err := feeCalculator.CalculateFee(sTx) if err != nil { return err @@ -604,6 +604,7 @@ func verifyAddPermissionlessValidatorTx( // AddPermissionlessDelegatorTx. func verifyAddPermissionlessDelegatorTx( backend *Backend, + feeCalculator fee.Calculator, chainState state.Chain, sTx *txs.Tx, tx *txs.AddPermissionlessDelegatorTx, @@ -726,7 +727,6 @@ func verifyAddPermissionlessDelegatorTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, backend.Config.UpgradeConfig, currentTimestamp) fee, err := feeCalculator.CalculateFee(sTx) if err != nil { return err @@ -754,6 +754,7 @@ func verifyAddPermissionlessDelegatorTx( // * The flow checker passes. func verifyTransferSubnetOwnershipTx( backend *Backend, + feeCalculator fee.Calculator, chainState state.Chain, sTx *txs.Tx, tx *txs.TransferSubnetOwnershipTx, @@ -786,7 +787,6 @@ func verifyTransferSubnetOwnershipTx( } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(backend.Config.StaticFeeConfig, upgrades, currentTimestamp) fee, err := feeCalculator.CalculateFee(sTx) if err != nil { return err diff --git a/vms/platformvm/txs/executor/staker_tx_verification_test.go b/vms/platformvm/txs/executor/staker_tx_verification_test.go index bde3da64ad7a..deaf22435f77 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification_test.go +++ b/vms/platformvm/txs/executor/staker_tx_verification_test.go @@ -113,8 +113,10 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { Config: defaultTestConfig(t, durango, activeForkTime), } }, - stateF: func(*gomock.Controller) state.Chain { - return nil + stateF: func(ctrl *gomock.Controller) state.Chain { + mockState := state.NewMockChain(ctrl) + mockState.EXPECT().GetTimestamp().Return(now) + return mockState }, sTxF: func() *txs.Tx { return nil @@ -135,7 +137,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { mockState := state.NewMockChain(ctrl) - mockState.EXPECT().GetTimestamp().Return(now) // chain time is after Durango fork activation since now.After(activeForkTime) + mockState.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after Durango fork activation since now.After(activeForkTime) return mockState }, sTxF: func() *txs.Tx { @@ -159,7 +161,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { state := state.NewMockChain(ctrl) - state.EXPECT().GetTimestamp().Return(verifiedTx.StartTime()) + state.EXPECT().GetTimestamp().Return(verifiedTx.StartTime()).Times(2) return state }, sTxF: func() *txs.Tx { @@ -183,7 +185,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { state := state.NewMockChain(ctrl) - state.EXPECT().GetTimestamp().Return(now) // chain time is after latest fork activation since now.After(activeForkTime) + state.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after latest fork activation since now.After(activeForkTime) state.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) return state }, @@ -210,7 +212,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { state := state.NewMockChain(ctrl) - state.EXPECT().GetTimestamp().Return(now) // chain time is after latest fork activation since now.After(activeForkTime) + state.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after latest fork activation since now.After(activeForkTime) state.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) return state }, @@ -237,7 +239,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { state := state.NewMockChain(ctrl) - state.EXPECT().GetTimestamp().Return(now) // chain time is after latest fork activation since now.After(activeForkTime) + state.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after latest fork activation since now.After(activeForkTime) state.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) return state }, @@ -265,7 +267,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { state := state.NewMockChain(ctrl) - state.EXPECT().GetTimestamp().Return(now) // chain time is after latest fork activation since now.After(activeForkTime) + state.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after latest fork activation since now.After(activeForkTime) state.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) return state }, @@ -296,7 +298,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { state := state.NewMockChain(ctrl) - state.EXPECT().GetTimestamp().Return(time.Unix(1, 0)) // chain time is after fork activation since time.Unix(1, 0).After(activeForkTime) + state.EXPECT().GetTimestamp().Return(time.Unix(1, 0)).Times(2) // chain time is after fork activation since time.Unix(1, 0).After(activeForkTime) state.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) return state }, @@ -327,7 +329,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { mockState := state.NewMockChain(ctrl) - mockState.EXPECT().GetTimestamp().Return(now) // chain time is after latest fork activation since now.After(activeForkTime) + mockState.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after latest fork activation since now.After(activeForkTime) mockState.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) return mockState }, @@ -360,7 +362,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { mockState := state.NewMockChain(ctrl) - mockState.EXPECT().GetTimestamp().Return(now) // chain time is after latest fork activation since now.After(activeForkTime) + mockState.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after latest fork activation since now.After(activeForkTime) mockState.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) // State says validator exists mockState.EXPECT().GetCurrentValidator(subnetID, verifiedTx.NodeID()).Return(nil, nil) @@ -387,7 +389,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { mockState := state.NewMockChain(ctrl) - mockState.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after latest fork activation since now.After(activeForkTime) + mockState.EXPECT().GetTimestamp().Return(now).Times(3) // chain time is after latest fork activation since now.After(activeForkTime) mockState.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) mockState.EXPECT().GetCurrentValidator(subnetID, verifiedTx.NodeID()).Return(nil, database.ErrNotFound) mockState.EXPECT().GetPendingValidator(subnetID, verifiedTx.NodeID()).Return(nil, database.ErrNotFound) @@ -434,7 +436,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { mockState := state.NewMockChain(ctrl) - mockState.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after latest fork activation since now.After(activeForkTime) + mockState.EXPECT().GetTimestamp().Return(now).Times(3) // chain time is after latest fork activation since now.After(activeForkTime) mockState.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) mockState.EXPECT().GetCurrentValidator(subnetID, verifiedTx.NodeID()).Return(nil, database.ErrNotFound) mockState.EXPECT().GetPendingValidator(subnetID, verifiedTx.NodeID()).Return(nil, database.ErrNotFound) @@ -480,7 +482,7 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { }, stateF: func(ctrl *gomock.Controller) state.Chain { mockState := state.NewMockChain(ctrl) - mockState.EXPECT().GetTimestamp().Return(now).Times(2) // chain time is after Durango fork activation since now.After(activeForkTime) + mockState.EXPECT().GetTimestamp().Return(now).Times(3) // chain time is after Durango fork activation since now.After(activeForkTime) mockState.EXPECT().GetSubnetTransformation(subnetID).Return(&transformTx, nil) mockState.EXPECT().GetCurrentValidator(subnetID, verifiedTx.NodeID()).Return(nil, database.ErrNotFound) mockState.EXPECT().GetPendingValidator(subnetID, verifiedTx.NodeID()).Return(nil, database.ErrNotFound) @@ -506,12 +508,15 @@ func TestVerifyAddPermissionlessValidatorTx(t *testing.T) { var ( backend = tt.backendF(ctrl) - state = tt.stateF(ctrl) + chain = tt.stateF(ctrl) sTx = tt.sTxF() tx = tt.txF() ) - err := verifyAddPermissionlessValidatorTx(backend, state, sTx, tx) + feeCalculator, err := state.PickFeeCalculator(backend.Config, chain) + require.NoError(t, err) + + err = verifyAddPermissionlessValidatorTx(backend, feeCalculator, chain, sTx, tx) require.ErrorIs(t, err, tt.expectedErr) }) } diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 8de6893cba03..9ec40e506a1b 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -33,8 +33,9 @@ var ( type StandardTxExecutor struct { // inputs, to be filled before visitor methods are called *Backend - State state.Diff // state is expected to be modified - Tx *txs.Tx + State state.Diff // state is expected to be modified + FeeCalculator fee.Calculator + Tx *txs.Tx // outputs of visitor execution OnAccept func() // may be nil @@ -69,8 +70,7 @@ func (e *StandardTxExecutor) CreateChainTx(tx *txs.CreateChainTx) error { } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) - fee, err := feeCalculator.CalculateFee(e.Tx) + fee, err := e.FeeCalculator.CalculateFee(e.Tx) if err != nil { return err } @@ -119,8 +119,7 @@ func (e *StandardTxExecutor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) - fee, err := feeCalculator.CalculateFee(e.Tx) + fee, err := e.FeeCalculator.CalculateFee(e.Tx) if err != nil { return err } @@ -204,8 +203,7 @@ func (e *StandardTxExecutor) ImportTx(tx *txs.ImportTx) error { copy(ins[len(tx.Ins):], tx.ImportedInputs) // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) - fee, err := feeCalculator.CalculateFee(e.Tx) + fee, err := e.FeeCalculator.CalculateFee(e.Tx) if err != nil { return err } @@ -265,8 +263,7 @@ func (e *StandardTxExecutor) ExportTx(tx *txs.ExportTx) error { } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) - fee, err := feeCalculator.CalculateFee(e.Tx) + fee, err := e.FeeCalculator.CalculateFee(e.Tx) if err != nil { return err } @@ -334,6 +331,7 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { if _, err := verifyAddValidatorTx( e.Backend, + e.FeeCalculator, e.State, e.Tx, tx, @@ -363,6 +361,7 @@ func (e *StandardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { func (e *StandardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error { if err := verifyAddSubnetValidatorTx( e.Backend, + e.FeeCalculator, e.State, e.Tx, tx, @@ -383,6 +382,7 @@ func (e *StandardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) func (e *StandardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { if _, err := verifyAddDelegatorTx( e.Backend, + e.FeeCalculator, e.State, e.Tx, tx, @@ -408,6 +408,7 @@ func (e *StandardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { func (e *StandardTxExecutor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { staker, isCurrentValidator, err := verifyRemoveSubnetValidatorTx( e.Backend, + e.FeeCalculator, e.State, e.Tx, tx, @@ -456,8 +457,7 @@ func (e *StandardTxExecutor) TransformSubnetTx(tx *txs.TransformSubnetTx) error } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, e.Backend.Config.UpgradeConfig, currentTimestamp) - fee, err := feeCalculator.CalculateFee(e.Tx) + fee, err := e.FeeCalculator.CalculateFee(e.Tx) if err != nil { return err } @@ -494,6 +494,7 @@ func (e *StandardTxExecutor) TransformSubnetTx(tx *txs.TransformSubnetTx) error func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { if err := verifyAddPermissionlessValidatorTx( e.Backend, + e.FeeCalculator, e.State, e.Tx, tx, @@ -526,6 +527,7 @@ func (e *StandardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionl func (e *StandardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { if err := verifyAddPermissionlessDelegatorTx( e.Backend, + e.FeeCalculator, e.State, e.Tx, tx, @@ -550,6 +552,7 @@ func (e *StandardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionl func (e *StandardTxExecutor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { err := verifyTransferSubnetOwnershipTx( e.Backend, + e.FeeCalculator, e.State, e.Tx, tx, @@ -585,8 +588,7 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { } // Verify the flowcheck - feeCalculator := fee.NewStaticCalculator(e.Backend.Config.StaticFeeConfig, upgrades, currentTimestamp) - fee, err := feeCalculator.CalculateFee(e.Tx) + fee, err := e.FeeCalculator.CalculateFee(e.Tx) if err != nil { return err } diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index 1de00365723f..b6a22a59ea13 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -98,10 +98,13 @@ func TestStandardTxExecutorAddValidatorTxEmptyID(t *testing.T) { stateDiff, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, stateDiff) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: stateDiff, - Tx: tx, + Backend: &env.backend, + State: stateDiff, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, test.expectedError) @@ -354,10 +357,13 @@ func TestStandardTxExecutorAddDelegator(t *testing.T) { env.config.UpgradeConfig.BanffTime = onAcceptState.GetTimestamp() + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, tt.expectedExecutionErr) @@ -397,10 +403,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrPeriodMismatch) @@ -430,10 +439,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) } @@ -483,10 +495,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrNotValidator) @@ -531,10 +546,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrPeriodMismatch) @@ -562,10 +580,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrPeriodMismatch) @@ -592,10 +613,14 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } require.NoError(tx.Unsigned.Visit(&executor)) } @@ -625,10 +650,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrTimestampNotBeforeStartTime) @@ -691,10 +719,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrDuplicateValidator) @@ -733,10 +764,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, secp256k1fx.ErrInputIndicesNotSortedUnique) @@ -771,10 +805,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, errUnauthorizedSubnetModification) @@ -807,10 +844,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, errUnauthorizedSubnetModification) @@ -853,10 +893,13 @@ func TestApricotStandardTxExecutorAddSubnetValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrDuplicateValidator) @@ -894,10 +937,13 @@ func TestBanffStandardTxExecutorAddValidator(t *testing.T) { onAcceptState, err := state.NewDiff(lastAcceptedID, env) require.NoError(err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrTimestampNotBeforeStartTime) @@ -939,10 +985,13 @@ func TestBanffStandardTxExecutorAddValidator(t *testing.T) { onAcceptState.PutCurrentValidator(staker) onAcceptState.AddTx(tx, status.Committed) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrAlreadyValidator) @@ -981,10 +1030,13 @@ func TestBanffStandardTxExecutorAddValidator(t *testing.T) { onAcceptState.PutPendingValidator(staker) onAcceptState.AddTx(tx, status.Committed) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrAlreadyValidator) @@ -1022,10 +1074,13 @@ func TestBanffStandardTxExecutorAddValidator(t *testing.T) { onAcceptState.DeleteUTXO(utxoID) } + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) executor := StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + FeeCalculator: feeCalculator, + State: onAcceptState, + Tx: tx, } err = tx.Unsigned.Visit(&executor) require.ErrorIs(err, ErrFlowCheckFailed) @@ -1124,10 +1179,13 @@ func TestDurangoDisabledTransactions(t *testing.T) { tx := tt.buildTx(env) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(err) err = tx.Unsigned.Visit(&StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, }) require.ErrorIs(err, tt.expectedErr) }) @@ -1332,10 +1390,13 @@ func TestDurangoMemoField(t *testing.T) { onAcceptState, err := state.NewDiff(env.state.GetLastAccepted(), env) require.NoError(t, err) + feeCalculator, err := state.PickFeeCalculator(env.config, onAcceptState) + require.NoError(t, err) require.NoError(t, subnetValTx.Unsigned.Visit(&StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: subnetValTx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: subnetValTx, })) builder, signer = env.factory.NewWallet(preFundedKeys...) @@ -1532,21 +1593,26 @@ func TestDurangoMemoField(t *testing.T) { env.ctx.Lock.Lock() defer env.ctx.Lock.Unlock() + feeCalculator, err := state.PickFeeCalculator(env.config, env.state) + require.NoError(err) + // Populated memo field should error tx, onAcceptState := tt.setupTest(env, []byte{'m', 'e', 'm', 'o'}) - err := tx.Unsigned.Visit(&StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + err = tx.Unsigned.Visit(&StandardTxExecutor{ + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, }) require.ErrorIs(err, avax.ErrMemoTooLarge) // Empty memo field should not error tx, onAcceptState = tt.setupTest(env, []byte{}) require.NoError(tx.Unsigned.Visit(&StandardTxExecutor{ - Backend: &env.backend, - State: onAcceptState, - Tx: tx, + Backend: &env.backend, + State: onAcceptState, + FeeCalculator: feeCalculator, + Tx: tx, })) }) } @@ -1663,7 +1729,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { env := newValidRemoveSubnetValidatorTxVerifyEnv(t, ctrl) // Set dependency expectations. - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(env.staker, nil).Times(1) subnetOwner := fx.NewMockOwner(ctrl) env.state.EXPECT().GetSubnetOwner(env.unsignedTx.Subnet).Return(subnetOwner, nil).Times(1) @@ -1674,16 +1740,21 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { env.state.EXPECT().DeleteCurrentValidator(env.staker) env.state.EXPECT().DeleteUTXO(gomock.Any()).Times(len(env.unsignedTx.Ins)) env.state.EXPECT().AddUTXO(gomock.Any()).Times(len(env.unsignedTx.Outs)) + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -1697,16 +1768,22 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { // Setting the subnet ID to the Primary Network ID makes the tx fail syntactic verification env.tx.Unsigned.(*txs.RemoveSubnetValidatorTx).Subnet = constants.PrimaryNetworkID env.state = state.NewMockDiff(ctrl) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -1718,19 +1795,24 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { newExecutor: func(ctrl *gomock.Controller) (*txs.RemoveSubnetValidatorTx, *StandardTxExecutor) { env := newValidRemoveSubnetValidatorTxVerifyEnv(t, ctrl) env.state = state.NewMockDiff(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(nil, database.ErrNotFound) env.state.EXPECT().GetPendingValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(nil, database.ErrNotFound) + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -1746,18 +1828,23 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { staker.Priority = txs.SubnetPermissionlessValidatorCurrentPriority // Set dependency expectations. - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(&staker, nil).Times(1) + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -1771,18 +1858,23 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { // Remove credentials env.tx.Creds = nil env.state = state.NewMockDiff(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(env.staker, nil) + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -1794,19 +1886,24 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { newExecutor: func(ctrl *gomock.Controller) (*txs.RemoveSubnetValidatorTx, *StandardTxExecutor) { env := newValidRemoveSubnetValidatorTxVerifyEnv(t, ctrl) env.state = state.NewMockDiff(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(env.staker, nil) env.state.EXPECT().GetSubnetOwner(env.unsignedTx.Subnet).Return(nil, database.ErrNotFound) + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -1818,21 +1915,26 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { newExecutor: func(ctrl *gomock.Controller) (*txs.RemoveSubnetValidatorTx, *StandardTxExecutor) { env := newValidRemoveSubnetValidatorTxVerifyEnv(t, ctrl) env.state = state.NewMockDiff(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(env.staker, nil) subnetOwner := fx.NewMockOwner(ctrl) env.state.EXPECT().GetSubnetOwner(env.unsignedTx.Subnet).Return(subnetOwner, nil) env.fx.EXPECT().VerifyPermission(gomock.Any(), env.unsignedTx.SubnetAuth, env.tx.Creds[len(env.tx.Creds)-1], subnetOwner).Return(errTest) + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -1844,7 +1946,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { newExecutor: func(ctrl *gomock.Controller) (*txs.RemoveSubnetValidatorTx, *StandardTxExecutor) { env := newValidRemoveSubnetValidatorTxVerifyEnv(t, ctrl) env.state = state.NewMockDiff(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(env.staker, nil) subnetOwner := fx.NewMockOwner(ctrl) env.state.EXPECT().GetSubnetOwner(env.unsignedTx.Subnet).Return(subnetOwner, nil) @@ -1852,16 +1954,21 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { env.flowChecker.EXPECT().VerifySpend( gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), ).Return(errTest) + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -2005,16 +2112,22 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { // Setting the tx to nil makes the tx fail syntactic verification env.tx.Unsigned = (*txs.TransformSubnetTx)(nil) env.state = state.NewMockDiff(ctrl) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -2027,17 +2140,22 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { env := newValidTransformSubnetTxVerifyEnv(t, ctrl) env.unsignedTx.MaxStakeDuration = math.MaxUint32 env.state = state.NewMockDiff(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() + + cfg := defaultTestConfig(t, durango, env.latestForkTime) + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ - Config: defaultTestConfig(t, durango, env.latestForkTime), + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -2051,11 +2169,13 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { // Remove credentials env.tx.Creds = nil env.state = state.NewMockDiff(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() cfg := defaultTestConfig(t, durango, env.latestForkTime) cfg.MaxStakeDuration = math.MaxInt64 + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ Config: cfg, @@ -2064,8 +2184,9 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -2078,7 +2199,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { env := newValidTransformSubnetTxVerifyEnv(t, ctrl) env.state = state.NewMockDiff(ctrl) subnetOwner := fx.NewMockOwner(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetSubnetOwner(env.unsignedTx.Subnet).Return(subnetOwner, nil) env.state.EXPECT().GetSubnetTransformation(env.unsignedTx.Subnet).Return(nil, database.ErrNotFound).Times(1) env.fx.EXPECT().VerifyPermission(gomock.Any(), env.unsignedTx.SubnetAuth, env.tx.Creds[len(env.tx.Creds)-1], subnetOwner).Return(nil) @@ -2089,6 +2210,8 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { cfg := defaultTestConfig(t, durango, env.latestForkTime) cfg.MaxStakeDuration = math.MaxInt64 + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ Config: cfg, @@ -2097,8 +2220,9 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e @@ -2112,7 +2236,7 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { // Set dependency expectations. subnetOwner := fx.NewMockOwner(ctrl) - env.state.EXPECT().GetTimestamp().Return(env.latestForkTime) + env.state.EXPECT().GetTimestamp().Return(env.latestForkTime).AnyTimes() env.state.EXPECT().GetSubnetOwner(env.unsignedTx.Subnet).Return(subnetOwner, nil).Times(1) env.state.EXPECT().GetSubnetTransformation(env.unsignedTx.Subnet).Return(nil, database.ErrNotFound).Times(1) env.fx.EXPECT().VerifyPermission(env.unsignedTx, env.unsignedTx.SubnetAuth, env.tx.Creds[len(env.tx.Creds)-1], subnetOwner).Return(nil).Times(1) @@ -2127,6 +2251,8 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { cfg := defaultTestConfig(t, durango, env.latestForkTime) cfg.MaxStakeDuration = math.MaxInt64 + feeCalculator, err := state.PickFeeCalculator(cfg, env.state) + require.NoError(t, err) e := &StandardTxExecutor{ Backend: &Backend{ Config: cfg, @@ -2135,8 +2261,9 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { FlowChecker: env.flowChecker, Ctx: &snow.Context{}, }, - Tx: env.tx, - State: env.state, + FeeCalculator: feeCalculator, + Tx: env.tx, + State: env.state, } e.Bootstrapped.Set(true) return env.unsignedTx, e diff --git a/vms/platformvm/txs/txstest/context.go b/vms/platformvm/txs/txstest/context.go index d8ca8c32853d..fb8181f7e39c 100644 --- a/vms/platformvm/txs/txstest/context.go +++ b/vms/platformvm/txs/txstest/context.go @@ -19,9 +19,9 @@ func newContext( timestamp time.Time, ) *builder.Context { var ( - feeCalc = fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig, timestamp) - createSubnetFee, _ = feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) - createChainFee, _ = feeCalc.CalculateFee(&txs.Tx{Unsigned: &txs.CreateChainTx{}}) + feeCalculator = fee.NewStaticCalculator(cfg.StaticFeeConfig, cfg.UpgradeConfig, timestamp) + createSubnetFee, _ = feeCalculator.CalculateFee(&txs.Tx{Unsigned: &txs.CreateSubnetTx{}}) + createChainFee, _ = feeCalculator.CalculateFee(&txs.Tx{Unsigned: &txs.CreateChainTx{}}) ) return &builder.Context{ From 1e797c50a99edf0be7799f9bd22f37bc88e04665 Mon Sep 17 00:00:00 2001 From: marun Date: Mon, 15 Jul 2024 10:37:07 -0700 Subject: [PATCH 8/8] [ci] Allow antithesis test setups to be triggered independently (#3183) --- ...yml => trigger-antithesis-avalanchego.yml} | 21 +--------- .github/workflows/trigger-antithesis-xsvm.yml | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+), 19 deletions(-) rename .github/workflows/{trigger-antithesis-runs.yml => trigger-antithesis-avalanchego.yml} (56%) create mode 100644 .github/workflows/trigger-antithesis-xsvm.yml diff --git a/.github/workflows/trigger-antithesis-runs.yml b/.github/workflows/trigger-antithesis-avalanchego.yml similarity index 56% rename from .github/workflows/trigger-antithesis-runs.yml rename to .github/workflows/trigger-antithesis-avalanchego.yml index f893b88da9ec..23a972d778ae 100644 --- a/.github/workflows/trigger-antithesis-runs.yml +++ b/.github/workflows/trigger-antithesis-avalanchego.yml @@ -1,4 +1,4 @@ -name: Trigger Antithesis Test Runs +name: Trigger Antithesis Avalanchego Setup on: # TODO(marun) Add a schedule to execute regularly @@ -10,8 +10,7 @@ on: required: true type: string recipients: - description: 'Email recipients to send the test report to' - default: ${{ secrets.ANTITHESIS_RECIPIENTS }} + description: 'Comma-seperated email addresses to send the test report to' required: true type: string image_tag: @@ -37,19 +36,3 @@ jobs: email_recipients: ${{ github.event.inputs.recipients || secrets.ANTITHESIS_RECIPIENTS }} additional_parameters: |- custom.duration=${{ github.event.inputs.duration || '0.5' }} - antithesis_xsvm: - name: Run Antithesis XSVM Test Setup - runs-on: ubuntu-latest - steps: - - uses: antithesishq/antithesis-trigger-action@v0.5 - with: - notebook_name: avalanche - tenant: avalanche - username: ${{ secrets.ANTITHESIS_USERNAME }} - password: ${{ secrets.ANTITHESIS_PASSWORD }} - github_token: ${{ secrets.ANTITHESIS_GH_PAT }} - config_image: antithesis-xsvm-config@${{ github.event.inputs.image_tag || 'latest' }} - images: antithesis-xsvm-workload@${{ github.event.inputs.image_tag || 'latest' }};antithesis-xsvm-node@${{ github.event.inputs.image_tag || 'latest' }} - email_recipients: ${{ github.event.inputs.recipients || secrets.ANTITHESIS_RECIPIENTS }} - additional_parameters: |- - custom.duration=${{ github.event.inputs.duration || '0.5' }} diff --git a/.github/workflows/trigger-antithesis-xsvm.yml b/.github/workflows/trigger-antithesis-xsvm.yml new file mode 100644 index 000000000000..02b52566eb69 --- /dev/null +++ b/.github/workflows/trigger-antithesis-xsvm.yml @@ -0,0 +1,38 @@ +name: Trigger Antithesis XSVM Setup + +on: + # TODO(marun) Add a schedule to execute regularly + workflow_dispatch: + inputs: + duration: + description: 'The duration to run the test for' + default: '0.5' + required: true + type: string + recipients: + description: 'Comma-seperated email addresses to send the test report to' + required: true + type: string + image_tag: + description: 'The image tag to target' + default: latest + required: true + type: string + +jobs: + antithesis_xsvm: + name: Run Antithesis XSVM Test Setup + runs-on: ubuntu-latest + steps: + - uses: antithesishq/antithesis-trigger-action@v0.5 + with: + notebook_name: avalanche + tenant: avalanche + username: ${{ secrets.ANTITHESIS_USERNAME }} + password: ${{ secrets.ANTITHESIS_PASSWORD }} + github_token: ${{ secrets.ANTITHESIS_GH_PAT }} + config_image: antithesis-xsvm-config@${{ github.event.inputs.image_tag || 'latest' }} + images: antithesis-xsvm-workload@${{ github.event.inputs.image_tag || 'latest' }};antithesis-xsvm-node@${{ github.event.inputs.image_tag || 'latest' }} + email_recipients: ${{ github.event.inputs.recipients || secrets.ANTITHESIS_RECIPIENTS }} + additional_parameters: |- + custom.duration=${{ github.event.inputs.duration || '0.5' }}