From 0d5b6189d2c12206b216323e9edcd854342ef9de Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 17 Jan 2024 13:14:48 +0100 Subject: [PATCH 1/7] added p-chain fees calculator --- .../txs/executor/staker_tx_verification.go | 80 ++++++-- .../txs/executor/standard_tx_executor.go | 56 +++++- .../txs/executor/standard_tx_executor_test.go | 190 ++++++++++-------- vms/platformvm/txs/fees/calculator.go | 161 +++++++++++++++ 4 files changed, 381 insertions(+), 106 deletions(-) create mode 100644 vms/platformvm/txs/fees/calculator.go diff --git a/vms/platformvm/txs/executor/staker_tx_verification.go b/vms/platformvm/txs/executor/staker_tx_verification.go index a17bbbffc14..bd83f5482a2 100644 --- a/vms/platformvm/txs/executor/staker_tx_verification.go +++ b/vms/platformvm/txs/executor/staker_tx_verification.go @@ -15,6 +15,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/fees" safemath "github.com/ava-labs/avalanchego/utils/math" ) @@ -160,6 +161,14 @@ func verifyAddValidatorTx( } // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: backend.Config, + ChainTime: currentTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return nil, err + } + if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -167,7 +176,7 @@ func verifyAddValidatorTx( outs, sTx.Creds, map[ids.ID]uint64{ - backend.Ctx.AVAXAssetID: backend.Config.AddPrimaryNetworkValidatorFee, + backend.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) @@ -246,6 +255,14 @@ func verifyAddSubnetValidatorTx( } // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: backend.Config, + ChainTime: currentTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -253,7 +270,7 @@ func verifyAddSubnetValidatorTx( tx.Outs, baseTxCreds, map[ids.ID]uint64{ - backend.Ctx.AVAXAssetID: backend.Config.AddSubnetValidatorFee, + backend.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) @@ -315,6 +332,14 @@ func verifyRemoveSubnetValidatorTx( } // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: backend.Config, + ChainTime: chainState.GetTimestamp(), + } + if err := tx.Visit(&feeCalculator); err != nil { + return nil, false, err + } + if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -322,7 +347,7 @@ func verifyRemoveSubnetValidatorTx( tx.Outs, baseTxCreds, map[ids.ID]uint64{ - backend.Ctx.AVAXAssetID: backend.Config.TxFee, + backend.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return nil, false, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) @@ -427,6 +452,14 @@ func verifyAddDelegatorTx( } // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: backend.Config, + ChainTime: chainState.GetTimestamp(), + } + if err := tx.Visit(&feeCalculator); err != nil { + return nil, err + } + if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -434,7 +467,7 @@ func verifyAddDelegatorTx( outs, sTx.Creds, map[ids.ID]uint64{ - backend.Ctx.AVAXAssetID: backend.Config.AddPrimaryNetworkDelegatorFee, + backend.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return nil, fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) @@ -531,15 +564,10 @@ func verifyAddPermissionlessValidatorTx( ) } - var txFee uint64 if tx.Subnet != constants.PrimaryNetworkID { if err := verifySubnetValidatorPrimaryNetworkRequirements(isDurangoActive, chainState, tx.Validator); err != nil { return err } - - txFee = backend.Config.AddSubnetValidatorFee - } else { - txFee = backend.Config.AddPrimaryNetworkValidatorFee } outs := make([]*avax.TransferableOutput, len(tx.Outs)+len(tx.StakeOuts)) @@ -547,6 +575,14 @@ func verifyAddPermissionlessValidatorTx( copy(outs[len(tx.Outs):], tx.StakeOuts) // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: backend.Config, + ChainTime: currentTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -554,7 +590,7 @@ func verifyAddPermissionlessValidatorTx( outs, sTx.Creds, map[ids.ID]uint64{ - backend.Ctx.AVAXAssetID: txFee, + backend.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) @@ -672,7 +708,6 @@ func verifyAddPermissionlessDelegatorTx( copy(outs, tx.Outs) copy(outs[len(tx.Outs):], tx.StakeOuts) - var txFee uint64 if tx.Subnet != constants.PrimaryNetworkID { // Invariant: Delegators must only be able to reference validator // transactions that implement [txs.ValidatorTx]. All @@ -683,10 +718,15 @@ func verifyAddPermissionlessDelegatorTx( if validator.Priority.IsPermissionedValidator() { return ErrDelegateToPermissionedValidator } + } - txFee = backend.Config.AddSubnetDelegatorFee - } else { - txFee = backend.Config.AddPrimaryNetworkDelegatorFee + // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: backend.Config, + ChainTime: currentTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err } // Verify the flowcheck @@ -697,7 +737,7 @@ func verifyAddPermissionlessDelegatorTx( outs, sTx.Creds, map[ids.ID]uint64{ - backend.Ctx.AVAXAssetID: txFee, + backend.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) @@ -739,6 +779,14 @@ func verifyTransferSubnetOwnershipTx( } // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: backend.Config, + ChainTime: chainState.GetTimestamp(), + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + if err := backend.FlowChecker.VerifySpend( tx, chainState, @@ -746,7 +794,7 @@ func verifyTransferSubnetOwnershipTx( tx.Outs, baseTxCreds, map[ids.ID]uint64{ - backend.Ctx.AVAXAssetID: backend.Config.TxFee, + backend.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return fmt.Errorf("%w: %w", ErrFlowCheckFailed, err) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index e780673e643..0298f0cddd6 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -19,6 +19,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/platformvm/state" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/platformvm/txs/fees" ) var ( @@ -60,8 +61,14 @@ func (e *StandardTxExecutor) CreateChainTx(tx *txs.CreateChainTx) error { } // Verify the flowcheck - timestamp := e.State.GetTimestamp() - createBlockchainTxFee := e.Config.GetCreateBlockchainTxFee(timestamp) + feeCalculator := fees.Calculator{ + Config: e.Backend.Config, + ChainTime: e.State.GetTimestamp(), + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + if err := e.FlowChecker.VerifySpend( tx, e.State, @@ -69,7 +76,7 @@ func (e *StandardTxExecutor) CreateChainTx(tx *txs.CreateChainTx) error { tx.Outs, baseTxCreds, map[ids.ID]uint64{ - e.Ctx.AVAXAssetID: createBlockchainTxFee, + e.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return err @@ -99,8 +106,14 @@ func (e *StandardTxExecutor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { } // Verify the flowcheck - timestamp := e.State.GetTimestamp() - createSubnetTxFee := e.Config.GetCreateSubnetTxFee(timestamp) + feeCalculator := fees.Calculator{ + Config: e.Backend.Config, + ChainTime: e.State.GetTimestamp(), + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + if err := e.FlowChecker.VerifySpend( tx, e.State, @@ -108,7 +121,7 @@ func (e *StandardTxExecutor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { tx.Outs, e.Tx.Creds, map[ids.ID]uint64{ - e.Ctx.AVAXAssetID: createSubnetTxFee, + e.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return err @@ -172,6 +185,15 @@ func (e *StandardTxExecutor) ImportTx(tx *txs.ImportTx) error { copy(ins, tx.Ins) copy(ins[len(tx.Ins):], tx.ImportedInputs) + // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: e.Backend.Config, + ChainTime: e.State.GetTimestamp(), + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + if err := e.FlowChecker.VerifySpendUTXOs( tx, utxos, @@ -179,7 +201,7 @@ func (e *StandardTxExecutor) ImportTx(tx *txs.ImportTx) error { tx.Outs, e.Tx.Creds, map[ids.ID]uint64{ - e.Ctx.AVAXAssetID: e.Config.TxFee, + e.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return err @@ -220,6 +242,14 @@ func (e *StandardTxExecutor) ExportTx(tx *txs.ExportTx) error { } // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: e.Backend.Config, + ChainTime: e.State.GetTimestamp(), + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + if err := e.FlowChecker.VerifySpend( tx, e.State, @@ -227,7 +257,7 @@ func (e *StandardTxExecutor) ExportTx(tx *txs.ExportTx) error { outs, e.Tx.Creds, map[ids.ID]uint64{ - e.Ctx.AVAXAssetID: e.Config.TxFee, + e.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); err != nil { return fmt.Errorf("failed verifySpend: %w", err) @@ -513,6 +543,14 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { } // Verify the flowcheck + feeCalculator := fees.Calculator{ + Config: e.Backend.Config, + ChainTime: e.State.GetTimestamp(), + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + if err := e.FlowChecker.VerifySpend( tx, e.State, @@ -520,7 +558,7 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { tx.Outs, e.Tx.Creds, map[ids.ID]uint64{ - e.Ctx.AVAXAssetID: e.Config.TxFee, + e.Ctx.AVAXAssetID: feeCalculator.Fee, }, ); 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 de0e3eebecc..d5a6f8cffa6 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -1136,6 +1136,7 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { // Set dependency expectations. env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(env.staker, nil).Times(1) + env.state.EXPECT().GetTimestamp().Return(time.Now()) subnetOwner := fx.NewMockOwner(ctrl) env.state.EXPECT().GetSubnetOwner(env.unsignedTx.Subnet).Return(subnetOwner, nil).Times(1) env.fx.EXPECT().VerifyPermission(env.unsignedTx, env.unsignedTx.SubnetAuth, env.tx.Creds[len(env.tx.Creds)-1], subnetOwner).Return(nil).Times(1) @@ -1145,14 +1146,16 @@ 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 := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1173,14 +1176,16 @@ 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) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1201,14 +1206,16 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { env.state = state.NewMockDiff(ctrl) 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 := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1232,14 +1239,16 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { // Set dependency expectations. env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(&staker, nil).Times(1) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1261,14 +1270,16 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { env.tx.Creds = nil env.state = state.NewMockDiff(ctrl) env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(env.staker, nil) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1289,14 +1300,16 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { env.state = state.NewMockDiff(ctrl) 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 := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1319,14 +1332,16 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { 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 := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1345,6 +1360,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(time.Now()) 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) @@ -1352,14 +1368,16 @@ func TestStandardExecutorRemoveSubnetValidatorTx(t *testing.T) { env.flowChecker.EXPECT().VerifySpend( gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), ).Return(errTest) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1510,14 +1528,16 @@ 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) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1537,14 +1557,16 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { env := newValidTransformSubnetTxVerifyEnv(t, ctrl) env.unsignedTx.MaxStakeDuration = math.MaxUint32 env.state = state.NewMockDiff(ctrl) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1565,15 +1587,17 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { // Remove credentials env.tx.Creds = nil env.state = state.NewMockDiff(ctrl) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + MaxStakeDuration: math.MaxInt64, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - MaxStakeDuration: math.MaxInt64, - EForkTime: mockable.MaxTime, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1599,15 +1623,17 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { env.flowChecker.EXPECT().VerifySpend( gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), ).Return(ErrFlowCheckFailed) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + MaxStakeDuration: math.MaxInt64, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - MaxStakeDuration: math.MaxInt64, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, @@ -1638,15 +1664,17 @@ func TestStandardExecutorTransformSubnetTx(t *testing.T) { env.state.EXPECT().SetCurrentSupply(env.unsignedTx.Subnet, env.unsignedTx.InitialSupply) env.state.EXPECT().DeleteUTXO(gomock.Any()).Times(len(env.unsignedTx.Ins)) env.state.EXPECT().AddUTXO(gomock.Any()).Times(len(env.unsignedTx.Outs)) + + cfg := &config.Config{ + BanffTime: env.latestForkTime, + CortinaTime: env.latestForkTime, + DurangoTime: env.latestForkTime, + EForkTime: mockable.MaxTime, + MaxStakeDuration: math.MaxInt64, + } e := &StandardTxExecutor{ Backend: &Backend{ - Config: &config.Config{ - BanffTime: env.latestForkTime, - CortinaTime: env.latestForkTime, - DurangoTime: env.latestForkTime, - EForkTime: mockable.MaxTime, - MaxStakeDuration: math.MaxInt64, - }, + Config: cfg, Bootstrapped: &utils.Atomic[bool]{}, Fx: env.fx, FlowChecker: env.flowChecker, diff --git a/vms/platformvm/txs/fees/calculator.go b/vms/platformvm/txs/fees/calculator.go new file mode 100644 index 00000000000..5ee928102cb --- /dev/null +++ b/vms/platformvm/txs/fees/calculator.go @@ -0,0 +1,161 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package fees + +import ( + "errors" + "time" + + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/vms/platformvm/config" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" +) + +var ( + _ txs.Visitor = (*Calculator)(nil) + + errEForkFeesNotDefinedYet = errors.New("fees in E fork not defined yet") +) + +type Calculator struct { + // setup, to be filled before visitor methods are called + Config *config.Config + ChainTime time.Time + + // outputs of visitor execution + Fee uint64 +} + +func (fc *Calculator) AddValidatorTx(*txs.AddValidatorTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.AddPrimaryNetworkValidatorFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) AddSubnetValidatorTx(*txs.AddSubnetValidatorTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.AddSubnetValidatorFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) AddDelegatorTx(*txs.AddDelegatorTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.AddPrimaryNetworkDelegatorFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) CreateChainTx(*txs.CreateChainTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.GetCreateBlockchainTxFee(fc.ChainTime) + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) CreateSubnetTx(*txs.CreateSubnetTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.GetCreateSubnetTxFee(fc.ChainTime) + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (*Calculator) AdvanceTimeTx(*txs.AdvanceTimeTx) error { + return nil // no fees +} + +func (*Calculator) RewardValidatorTx(*txs.RewardValidatorTx) error { + return nil // no fees +} + +func (fc *Calculator) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) TransformSubnetTx(*txs.TransformSubnetTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TransformSubnetTxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + if tx.Subnet != constants.PrimaryNetworkID { + fc.Fee = fc.Config.AddSubnetValidatorFee + } else { + fc.Fee = fc.Config.AddPrimaryNetworkValidatorFee + } + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + if tx.Subnet != constants.PrimaryNetworkID { + fc.Fee = fc.Config.AddSubnetDelegatorFee + } else { + fc.Fee = fc.Config.AddPrimaryNetworkDelegatorFee + } + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) BaseTx(*txs.BaseTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) ImportTx(*txs.ImportTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) ExportTx(*txs.ExportTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} From 8623d08c47e73e18aebeffd9beac87b48babcb12 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 17 Jan 2024 13:52:45 +0100 Subject: [PATCH 2/7] added x-chain fees calculator --- vms/avm/block/executor/block.go | 5 +- vms/avm/block/executor/manager.go | 5 +- vms/avm/block/executor/manager_test.go | 11 ++-- vms/avm/txs/executor/syntactic_verifier.go | 55 +++++++++++++++-- vms/avm/txs/fees/calculator.go | 72 ++++++++++++++++++++++ vms/avm/vm.go | 5 +- 6 files changed, 137 insertions(+), 16 deletions(-) create mode 100644 vms/avm/txs/fees/calculator.go diff --git a/vms/avm/block/executor/block.go b/vms/avm/block/executor/block.go index 8663f27ba12..e49f1f482f8 100644 --- a/vms/avm/block/executor/block.go +++ b/vms/avm/block/executor/block.go @@ -77,8 +77,9 @@ func (b *Block) Verify(context.Context) error { // before performing any possible DB reads. for _, tx := range txs { err := tx.Unsigned.Visit(&executor.SyntacticVerifier{ - Backend: b.manager.backend, - Tx: tx, + Backend: b.manager.backend, + BlkTimestamp: newChainTime, + Tx: tx, }) if err != nil { txID := tx.ID() diff --git a/vms/avm/block/executor/manager.go b/vms/avm/block/executor/manager.go index 9822743b7fd..a2a981c5185 100644 --- a/vms/avm/block/executor/manager.go +++ b/vms/avm/block/executor/manager.go @@ -148,8 +148,9 @@ func (m *manager) VerifyTx(tx *txs.Tx) error { } err := tx.Unsigned.Visit(&executor.SyntacticVerifier{ - Backend: m.backend, - Tx: tx, + Backend: m.backend, + BlkTimestamp: m.state.GetTimestamp(), + Tx: tx, }) if err != nil { return err diff --git a/vms/avm/block/executor/manager_test.go b/vms/avm/block/executor/manager_test.go index 89b547eed96..de09f434d90 100644 --- a/vms/avm/block/executor/manager_test.go +++ b/vms/avm/block/executor/manager_test.go @@ -145,7 +145,9 @@ func TestManagerVerifyTx(t *testing.T) { Unsigned: unsigned, } }, - managerF: func(*gomock.Controller) *manager { + managerF: func(ctrl *gomock.Controller) *manager { + state := state.NewMockState(ctrl) + state.EXPECT().GetTimestamp().Return(time.Time{}) return &manager{ backend: &executor.Backend{ Bootstrapped: true, @@ -154,6 +156,7 @@ func TestManagerVerifyTx(t *testing.T) { EForkTime: mockable.MaxTime, }, }, + state: state, } }, expectedErr: errTestSyntacticVerifyFail, @@ -176,7 +179,7 @@ func TestManagerVerifyTx(t *testing.T) { // These values don't matter for this test state := state.NewMockState(ctrl) state.EXPECT().GetLastAccepted().Return(lastAcceptedID) - state.EXPECT().GetTimestamp().Return(time.Time{}) + state.EXPECT().GetTimestamp().Return(time.Time{}).Times(2) return &manager{ backend: &executor.Backend{ @@ -212,7 +215,7 @@ func TestManagerVerifyTx(t *testing.T) { // These values don't matter for this test state := state.NewMockState(ctrl) state.EXPECT().GetLastAccepted().Return(lastAcceptedID) - state.EXPECT().GetTimestamp().Return(time.Time{}) + state.EXPECT().GetTimestamp().Return(time.Time{}).Times(2) return &manager{ backend: &executor.Backend{ @@ -248,7 +251,7 @@ func TestManagerVerifyTx(t *testing.T) { // These values don't matter for this test state := state.NewMockState(ctrl) state.EXPECT().GetLastAccepted().Return(lastAcceptedID) - state.EXPECT().GetTimestamp().Return(time.Time{}) + state.EXPECT().GetTimestamp().Return(time.Time{}).Times(2) return &manager{ backend: &executor.Backend{ diff --git a/vms/avm/txs/executor/syntactic_verifier.go b/vms/avm/txs/executor/syntactic_verifier.go index 81a2f2a715f..2bb1fc6c5aa 100644 --- a/vms/avm/txs/executor/syntactic_verifier.go +++ b/vms/avm/txs/executor/syntactic_verifier.go @@ -7,12 +7,14 @@ import ( "errors" "fmt" "strings" + "time" "unicode" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/avm/txs/fees" "github.com/ava-labs/avalanchego/vms/components/avax" ) @@ -47,7 +49,8 @@ var ( type SyntacticVerifier struct { *Backend - Tx *txs.Tx + BlkTimestamp time.Time + Tx *txs.Tx } func (v *SyntacticVerifier) BaseTx(tx *txs.BaseTx) error { @@ -55,8 +58,16 @@ func (v *SyntacticVerifier) BaseTx(tx *txs.BaseTx) error { return err } + feeCalculator := fees.Calculator{ + Config: v.Config, + ChainTime: v.BlkTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + err := avax.VerifyTx( - v.Config.TxFee, + feeCalculator.Fee, v.FeeAssetID, [][]*avax.TransferableInput{tx.Ins}, [][]*avax.TransferableOutput{tx.Outs}, @@ -118,8 +129,16 @@ func (v *SyntacticVerifier) CreateAssetTx(tx *txs.CreateAssetTx) error { return err } + feeCalculator := fees.Calculator{ + Config: v.Config, + ChainTime: v.BlkTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + err := avax.VerifyTx( - v.Config.CreateAssetTxFee, + feeCalculator.Fee, v.FeeAssetID, [][]*avax.TransferableInput{tx.Ins}, [][]*avax.TransferableOutput{tx.Outs}, @@ -166,8 +185,16 @@ func (v *SyntacticVerifier) OperationTx(tx *txs.OperationTx) error { return err } + feeCalculator := fees.Calculator{ + Config: v.Config, + ChainTime: v.BlkTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + err := avax.VerifyTx( - v.Config.TxFee, + feeCalculator.Fee, v.FeeAssetID, [][]*avax.TransferableInput{tx.Ins}, [][]*avax.TransferableOutput{tx.Outs}, @@ -226,8 +253,16 @@ func (v *SyntacticVerifier) ImportTx(tx *txs.ImportTx) error { return err } + feeCalculator := fees.Calculator{ + Config: v.Config, + ChainTime: v.BlkTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + err := avax.VerifyTx( - v.Config.TxFee, + feeCalculator.Fee, v.FeeAssetID, [][]*avax.TransferableInput{ tx.Ins, @@ -268,8 +303,16 @@ func (v *SyntacticVerifier) ExportTx(tx *txs.ExportTx) error { return err } + feeCalculator := fees.Calculator{ + Config: v.Config, + ChainTime: v.BlkTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + err := avax.VerifyTx( - v.Config.TxFee, + feeCalculator.Fee, v.FeeAssetID, [][]*avax.TransferableInput{tx.Ins}, [][]*avax.TransferableOutput{ diff --git a/vms/avm/txs/fees/calculator.go b/vms/avm/txs/fees/calculator.go new file mode 100644 index 00000000000..dad73ae3607 --- /dev/null +++ b/vms/avm/txs/fees/calculator.go @@ -0,0 +1,72 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package fees + +import ( + "errors" + "time" + + "github.com/ava-labs/avalanchego/vms/avm/config" + "github.com/ava-labs/avalanchego/vms/avm/txs" +) + +var ( + _ txs.Visitor = (*Calculator)(nil) + + errEForkFeesNotDefinedYet = errors.New("fees in E fork not defined yet") +) + +type Calculator struct { + // setup, to be filled before visitor methods are called + Config *config.Config + ChainTime time.Time + + // outputs of visitor execution + Fee uint64 +} + +func (fc *Calculator) BaseTx(*txs.BaseTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) CreateAssetTx(*txs.CreateAssetTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.CreateAssetTxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) OperationTx(*txs.OperationTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) ImportTx(*txs.ImportTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} + +func (fc *Calculator) ExportTx(*txs.ExportTx) error { + if !fc.Config.IsEForkActivated(fc.ChainTime) { + fc.Fee = fc.Config.TxFee + return nil + } + + return errEForkFeesNotDefinedYet +} diff --git a/vms/avm/vm.go b/vms/avm/vm.go index 59907c934e9..e739a352a48 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -501,8 +501,9 @@ func (vm *VM) ParseTx(_ context.Context, bytes []byte) (snowstorm.Tx, error) { } err = tx.Unsigned.Visit(&txexecutor.SyntacticVerifier{ - Backend: vm.txBackend, - Tx: tx, + Backend: vm.txBackend, + BlkTimestamp: vm.state.GetTimestamp(), + Tx: tx, }) if err != nil { return nil, err From d984b3be2b3332a1daa33c801e5822607b6a6910 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Fri, 26 Jan 2024 16:01:36 +0100 Subject: [PATCH 3/7] fixed merge --- vms/platformvm/txs/executor/standard_tx_executor_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vms/platformvm/txs/executor/standard_tx_executor_test.go b/vms/platformvm/txs/executor/standard_tx_executor_test.go index 1dab25b2743..08f01c6ea59 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor_test.go +++ b/vms/platformvm/txs/executor/standard_tx_executor_test.go @@ -1697,9 +1697,8 @@ 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).Times(2) env.state.EXPECT().GetCurrentValidator(env.unsignedTx.Subnet, env.unsignedTx.NodeID).Return(env.staker, nil).Times(1) - env.state.EXPECT().GetTimestamp().Return(time.Now()) subnetOwner := fx.NewMockOwner(ctrl) env.state.EXPECT().GetSubnetOwner(env.unsignedTx.Subnet).Return(subnetOwner, nil).Times(1) env.fx.EXPECT().VerifyPermission(env.unsignedTx, env.unsignedTx.SubnetAuth, env.tx.Creds[len(env.tx.Creds)-1], subnetOwner).Return(nil).Times(1) From 25b942460a0b7a81624e19c103f6c685f9710507 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 29 Jan 2024 13:50:14 +0100 Subject: [PATCH 4/7] reduced diffs --- vms/avm/txs/fees/calculator.go | 47 +++------- vms/platformvm/txs/fees/calculator.go | 123 +++++++------------------- 2 files changed, 44 insertions(+), 126 deletions(-) diff --git a/vms/avm/txs/fees/calculator.go b/vms/avm/txs/fees/calculator.go index dad73ae3607..9d956486dec 100644 --- a/vms/avm/txs/fees/calculator.go +++ b/vms/avm/txs/fees/calculator.go @@ -4,18 +4,13 @@ package fees import ( - "errors" "time" "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" ) -var ( - _ txs.Visitor = (*Calculator)(nil) - - errEForkFeesNotDefinedYet = errors.New("fees in E fork not defined yet") -) +var _ txs.Visitor = (*Calculator)(nil) type Calculator struct { // setup, to be filled before visitor methods are called @@ -27,46 +22,26 @@ type Calculator struct { } func (fc *Calculator) BaseTx(*txs.BaseTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } func (fc *Calculator) CreateAssetTx(*txs.CreateAssetTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.CreateAssetTxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.CreateAssetTxFee + return nil } func (fc *Calculator) OperationTx(*txs.OperationTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } func (fc *Calculator) ImportTx(*txs.ImportTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } func (fc *Calculator) ExportTx(*txs.ExportTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } diff --git a/vms/platformvm/txs/fees/calculator.go b/vms/platformvm/txs/fees/calculator.go index 5ee928102cb..b35568d4229 100644 --- a/vms/platformvm/txs/fees/calculator.go +++ b/vms/platformvm/txs/fees/calculator.go @@ -4,7 +4,6 @@ package fees import ( - "errors" "time" "github.com/ava-labs/avalanchego/utils/constants" @@ -12,11 +11,7 @@ import ( "github.com/ava-labs/avalanchego/vms/platformvm/txs" ) -var ( - _ txs.Visitor = (*Calculator)(nil) - - errEForkFeesNotDefinedYet = errors.New("fees in E fork not defined yet") -) +var _ txs.Visitor = (*Calculator)(nil) type Calculator struct { // setup, to be filled before visitor methods are called @@ -28,48 +23,28 @@ type Calculator struct { } func (fc *Calculator) AddValidatorTx(*txs.AddValidatorTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.AddPrimaryNetworkValidatorFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.AddPrimaryNetworkValidatorFee + return nil } func (fc *Calculator) AddSubnetValidatorTx(*txs.AddSubnetValidatorTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.AddSubnetValidatorFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.AddSubnetValidatorFee + return nil } func (fc *Calculator) AddDelegatorTx(*txs.AddDelegatorTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.AddPrimaryNetworkDelegatorFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.AddPrimaryNetworkDelegatorFee + return nil } func (fc *Calculator) CreateChainTx(*txs.CreateChainTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.GetCreateBlockchainTxFee(fc.ChainTime) - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.GetCreateBlockchainTxFee(fc.ChainTime) + return nil } func (fc *Calculator) CreateSubnetTx(*txs.CreateSubnetTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.GetCreateSubnetTxFee(fc.ChainTime) - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.GetCreateSubnetTxFee(fc.ChainTime) + return nil } func (*Calculator) AdvanceTimeTx(*txs.AdvanceTimeTx) error { @@ -81,81 +56,49 @@ func (*Calculator) RewardValidatorTx(*txs.RewardValidatorTx) error { } func (fc *Calculator) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } func (fc *Calculator) TransformSubnetTx(*txs.TransformSubnetTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TransformSubnetTxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TransformSubnetTxFee + return nil } func (fc *Calculator) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } func (fc *Calculator) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - if tx.Subnet != constants.PrimaryNetworkID { - fc.Fee = fc.Config.AddSubnetValidatorFee - } else { - fc.Fee = fc.Config.AddPrimaryNetworkValidatorFee - } - return nil + if tx.Subnet != constants.PrimaryNetworkID { + fc.Fee = fc.Config.AddSubnetValidatorFee + } else { + fc.Fee = fc.Config.AddPrimaryNetworkValidatorFee } - - return errEForkFeesNotDefinedYet + return nil } func (fc *Calculator) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - if tx.Subnet != constants.PrimaryNetworkID { - fc.Fee = fc.Config.AddSubnetDelegatorFee - } else { - fc.Fee = fc.Config.AddPrimaryNetworkDelegatorFee - } - return nil + if tx.Subnet != constants.PrimaryNetworkID { + fc.Fee = fc.Config.AddSubnetDelegatorFee + } else { + fc.Fee = fc.Config.AddPrimaryNetworkDelegatorFee } - - return errEForkFeesNotDefinedYet + return nil } func (fc *Calculator) BaseTx(*txs.BaseTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } func (fc *Calculator) ImportTx(*txs.ImportTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } func (fc *Calculator) ExportTx(*txs.ExportTx) error { - if !fc.Config.IsEForkActivated(fc.ChainTime) { - fc.Fee = fc.Config.TxFee - return nil - } - - return errEForkFeesNotDefinedYet + fc.Fee = fc.Config.TxFee + return nil } From c2509f38e384b615189e756c35d5ab12b838c8bb Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 1 Feb 2024 23:00:57 +0100 Subject: [PATCH 5/7] nit --- .../txs/executor/standard_tx_executor.go | 17 ++++++++++++++--- vms/platformvm/txs/fees/calculator.go | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index b42f66969b5..29220ffee0b 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -468,6 +468,13 @@ func (e *StandardTxExecutor) TransformSubnetTx(tx *txs.TransformSubnetTx) error } totalRewardAmount := tx.MaximumSupply - tx.InitialSupply + feeCalculator := fees.Calculator{ + Config: e.Backend.Config, + ChainTime: currentTimestamp, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } if err := e.Backend.FlowChecker.VerifySpend( tx, e.State, @@ -478,7 +485,7 @@ func (e *StandardTxExecutor) TransformSubnetTx(tx *txs.TransformSubnetTx) error // entry in this map literal from being overwritten by the // second entry. map[ids.ID]uint64{ - e.Ctx.AVAXAssetID: e.Config.TransformSubnetTxFee, + e.Ctx.AVAXAssetID: feeCalculator.Fee, tx.AssetID: totalRewardAmount, }, ); err != nil { @@ -587,9 +594,13 @@ func (e *StandardTxExecutor) BaseTx(tx *txs.BaseTx) error { } // Verify the flowcheck + var ( + cfg = e.Backend.Config + currentTimestamp = e.State.GetTimestamp() + ) feeCalculator := fees.Calculator{ - Config: e.Backend.Config, - ChainTime: e.State.GetTimestamp(), + Config: cfg, + ChainTime: currentTimestamp, } if err := tx.Visit(&feeCalculator); err != nil { return err diff --git a/vms/platformvm/txs/fees/calculator.go b/vms/platformvm/txs/fees/calculator.go index b35568d4229..123052577e5 100644 --- a/vms/platformvm/txs/fees/calculator.go +++ b/vms/platformvm/txs/fees/calculator.go @@ -14,7 +14,7 @@ import ( var _ txs.Visitor = (*Calculator)(nil) type Calculator struct { - // setup, to be filled before visitor methods are called + // Pre E-fork inputs Config *config.Config ChainTime time.Time From ca8e6c73d4ade602307f1a70dbb7399a487a0558 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 1 Feb 2024 23:07:46 +0100 Subject: [PATCH 6/7] nit --- vms/avm/txs/executor/syntactic_verifier.go | 15 +++++---------- vms/avm/txs/fees/calculator.go | 7 ++----- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/vms/avm/txs/executor/syntactic_verifier.go b/vms/avm/txs/executor/syntactic_verifier.go index 2bb1fc6c5aa..58a0e0661aa 100644 --- a/vms/avm/txs/executor/syntactic_verifier.go +++ b/vms/avm/txs/executor/syntactic_verifier.go @@ -59,8 +59,7 @@ func (v *SyntacticVerifier) BaseTx(tx *txs.BaseTx) error { } feeCalculator := fees.Calculator{ - Config: v.Config, - ChainTime: v.BlkTimestamp, + Config: v.Config, } if err := tx.Visit(&feeCalculator); err != nil { return err @@ -130,8 +129,7 @@ func (v *SyntacticVerifier) CreateAssetTx(tx *txs.CreateAssetTx) error { } feeCalculator := fees.Calculator{ - Config: v.Config, - ChainTime: v.BlkTimestamp, + Config: v.Config, } if err := tx.Visit(&feeCalculator); err != nil { return err @@ -186,8 +184,7 @@ func (v *SyntacticVerifier) OperationTx(tx *txs.OperationTx) error { } feeCalculator := fees.Calculator{ - Config: v.Config, - ChainTime: v.BlkTimestamp, + Config: v.Config, } if err := tx.Visit(&feeCalculator); err != nil { return err @@ -254,8 +251,7 @@ func (v *SyntacticVerifier) ImportTx(tx *txs.ImportTx) error { } feeCalculator := fees.Calculator{ - Config: v.Config, - ChainTime: v.BlkTimestamp, + Config: v.Config, } if err := tx.Visit(&feeCalculator); err != nil { return err @@ -304,8 +300,7 @@ func (v *SyntacticVerifier) ExportTx(tx *txs.ExportTx) error { } feeCalculator := fees.Calculator{ - Config: v.Config, - ChainTime: v.BlkTimestamp, + Config: v.Config, } if err := tx.Visit(&feeCalculator); err != nil { return err diff --git a/vms/avm/txs/fees/calculator.go b/vms/avm/txs/fees/calculator.go index 9d956486dec..5bcf9d77099 100644 --- a/vms/avm/txs/fees/calculator.go +++ b/vms/avm/txs/fees/calculator.go @@ -4,8 +4,6 @@ package fees import ( - "time" - "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/txs" ) @@ -13,9 +11,8 @@ import ( var _ txs.Visitor = (*Calculator)(nil) type Calculator struct { - // setup, to be filled before visitor methods are called - Config *config.Config - ChainTime time.Time + // Pre E-fork inputs + Config *config.Config // outputs of visitor execution Fee uint64 From fcf8fc2c7e263f4276151b480dd86755de2b23a6 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 1 Feb 2024 23:49:19 +0100 Subject: [PATCH 7/7] wip: moving avm fees checks from syntactic to semantic verifier --- vms/avm/txs/executor/semantic_verifier.go | 77 +- vms/avm/txs/executor/syntactic_verifier.go | 98 - .../txs/executor/syntactic_verifier_test.go | 2209 ++++++++--------- 3 files changed, 1155 insertions(+), 1229 deletions(-) diff --git a/vms/avm/txs/executor/semantic_verifier.go b/vms/avm/txs/executor/semantic_verifier.go index 946346bc064..0b807008e0d 100644 --- a/vms/avm/txs/executor/semantic_verifier.go +++ b/vms/avm/txs/executor/semantic_verifier.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" + "github.com/ava-labs/avalanchego/vms/avm/txs/fees" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" ) @@ -31,28 +32,7 @@ type SemanticVerifier struct { } func (v *SemanticVerifier) BaseTx(tx *txs.BaseTx) error { - for i, in := range tx.Ins { - // Note: Verification of the length of [t.tx.Creds] happens during - // syntactic verification, which happens before semantic verification. - cred := v.Tx.Creds[i].Credential - if err := v.verifyTransfer(tx, in, cred); err != nil { - return err - } - } - - for _, out := range tx.Outs { - fxIndex, err := v.getFx(out.Out) - if err != nil { - return err - } - - assetID := out.AssetID() - if err := v.verifyFxUsage(fxIndex, assetID); err != nil { - return err - } - } - - return nil + return v.verifyBaseTx(tx, nil, nil) } func (v *SemanticVerifier) CreateAssetTx(tx *txs.CreateAssetTx) error { @@ -60,7 +40,7 @@ func (v *SemanticVerifier) CreateAssetTx(tx *txs.CreateAssetTx) error { } func (v *SemanticVerifier) OperationTx(tx *txs.OperationTx) error { - if err := v.BaseTx(&tx.BaseTx); err != nil { + if err := v.verifyBaseTx(&tx.BaseTx, nil, nil); err != nil { return err } @@ -81,7 +61,7 @@ func (v *SemanticVerifier) OperationTx(tx *txs.OperationTx) error { } func (v *SemanticVerifier) ImportTx(tx *txs.ImportTx) error { - if err := v.BaseTx(&tx.BaseTx); err != nil { + if err := v.verifyBaseTx(&tx.BaseTx, tx.ImportedIns, nil); err != nil { return err } @@ -122,7 +102,7 @@ func (v *SemanticVerifier) ImportTx(tx *txs.ImportTx) error { } func (v *SemanticVerifier) ExportTx(tx *txs.ExportTx) error { - if err := v.BaseTx(&tx.BaseTx); err != nil { + if err := v.verifyBaseTx(&tx.BaseTx, nil, tx.ExportedOuts); err != nil { return err } @@ -146,6 +126,53 @@ func (v *SemanticVerifier) ExportTx(tx *txs.ExportTx) error { return nil } +func (v *SemanticVerifier) verifyBaseTx( + tx *txs.BaseTx, + importedIns []*avax.TransferableInput, + exportedOuts []*avax.TransferableOutput, +) error { + feeCalculator := fees.Calculator{ + Config: v.Config, + } + if err := tx.Visit(&feeCalculator); err != nil { + return err + } + + err := avax.VerifyTx( + feeCalculator.Fee, + v.FeeAssetID, + [][]*avax.TransferableInput{tx.Ins, importedIns}, + [][]*avax.TransferableOutput{tx.Outs, exportedOuts}, + v.Codec, + ) + if err != nil { + return err + } + + for i, in := range tx.Ins { + // Note: Verification of the length of [t.tx.Creds] happens during + // syntactic verification, which happens before semantic verification. + cred := v.Tx.Creds[i].Credential + if err := v.verifyTransfer(tx, in, cred); err != nil { + return err + } + } + + for _, out := range tx.Outs { + fxIndex, err := v.getFx(out.Out) + if err != nil { + return err + } + + assetID := out.AssetID() + if err := v.verifyFxUsage(fxIndex, assetID); err != nil { + return err + } + } + + return nil +} + func (v *SemanticVerifier) verifyTransfer( tx txs.UnsignedTx, in *avax.TransferableInput, diff --git a/vms/avm/txs/executor/syntactic_verifier.go b/vms/avm/txs/executor/syntactic_verifier.go index 58a0e0661aa..b253aba427e 100644 --- a/vms/avm/txs/executor/syntactic_verifier.go +++ b/vms/avm/txs/executor/syntactic_verifier.go @@ -14,8 +14,6 @@ import ( "github.com/ava-labs/avalanchego/utils" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/txs" - "github.com/ava-labs/avalanchego/vms/avm/txs/fees" - "github.com/ava-labs/avalanchego/vms/components/avax" ) const ( @@ -58,24 +56,6 @@ func (v *SyntacticVerifier) BaseTx(tx *txs.BaseTx) error { return err } - feeCalculator := fees.Calculator{ - Config: v.Config, - } - if err := tx.Visit(&feeCalculator); err != nil { - return err - } - - err := avax.VerifyTx( - feeCalculator.Fee, - v.FeeAssetID, - [][]*avax.TransferableInput{tx.Ins}, - [][]*avax.TransferableOutput{tx.Outs}, - v.Codec, - ) - if err != nil { - return err - } - for _, cred := range v.Tx.Creds { if err := cred.Verify(); err != nil { return err @@ -128,24 +108,6 @@ func (v *SyntacticVerifier) CreateAssetTx(tx *txs.CreateAssetTx) error { return err } - feeCalculator := fees.Calculator{ - Config: v.Config, - } - if err := tx.Visit(&feeCalculator); err != nil { - return err - } - - err := avax.VerifyTx( - feeCalculator.Fee, - v.FeeAssetID, - [][]*avax.TransferableInput{tx.Ins}, - [][]*avax.TransferableOutput{tx.Outs}, - v.Codec, - ) - if err != nil { - return err - } - for _, state := range tx.States { if err := state.Verify(v.Codec, len(v.Fxs)); err != nil { return err @@ -183,24 +145,6 @@ func (v *SyntacticVerifier) OperationTx(tx *txs.OperationTx) error { return err } - feeCalculator := fees.Calculator{ - Config: v.Config, - } - if err := tx.Visit(&feeCalculator); err != nil { - return err - } - - err := avax.VerifyTx( - feeCalculator.Fee, - v.FeeAssetID, - [][]*avax.TransferableInput{tx.Ins}, - [][]*avax.TransferableOutput{tx.Outs}, - v.Codec, - ) - if err != nil { - return err - } - inputs := set.NewSet[ids.ID](len(tx.Ins)) for _, in := range tx.Ins { inputs.Add(in.InputID()) @@ -250,27 +194,6 @@ func (v *SyntacticVerifier) ImportTx(tx *txs.ImportTx) error { return err } - feeCalculator := fees.Calculator{ - Config: v.Config, - } - if err := tx.Visit(&feeCalculator); err != nil { - return err - } - - err := avax.VerifyTx( - feeCalculator.Fee, - v.FeeAssetID, - [][]*avax.TransferableInput{ - tx.Ins, - tx.ImportedIns, - }, - [][]*avax.TransferableOutput{tx.Outs}, - v.Codec, - ) - if err != nil { - return err - } - for _, cred := range v.Tx.Creds { if err := cred.Verify(); err != nil { return err @@ -299,27 +222,6 @@ func (v *SyntacticVerifier) ExportTx(tx *txs.ExportTx) error { return err } - feeCalculator := fees.Calculator{ - Config: v.Config, - } - if err := tx.Visit(&feeCalculator); err != nil { - return err - } - - err := avax.VerifyTx( - feeCalculator.Fee, - v.FeeAssetID, - [][]*avax.TransferableInput{tx.Ins}, - [][]*avax.TransferableOutput{ - tx.Outs, - tx.ExportedOuts, - }, - v.Codec, - ) - if err != nil { - return err - } - for _, cred := range v.Tx.Creds { if err := cred.Verify(); err != nil { return err diff --git a/vms/avm/txs/executor/syntactic_verifier_test.go b/vms/avm/txs/executor/syntactic_verifier_test.go index cc160ed7982..30a36fadc18 100644 --- a/vms/avm/txs/executor/syntactic_verifier_test.go +++ b/vms/avm/txs/executor/syntactic_verifier_test.go @@ -4,7 +4,6 @@ package executor import ( - "math" "strings" "testing" "time" @@ -22,8 +21,6 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" "github.com/ava-labs/avalanchego/vms/secp256k1fx" - - safemath "github.com/ava-labs/avalanchego/utils/math" ) var ( @@ -163,177 +160,177 @@ func TestSyntacticVerifierBaseTx(t *testing.T) { }, err: avax.ErrMemoTooLarge, }, - { - name: "invalid output", - txFunc: func() *txs.Tx { - output := output - output.Out = &secp256k1fx.TransferOutput{ - Amt: 0, - OutputOwners: outputOwners, - } - - baseTx := baseTx - baseTx.Outs = []*avax.TransferableOutput{ - &output, - } - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: creds, - } - }, - err: secp256k1fx.ErrNoValueOutput, - }, - { - name: "unsorted outputs", - txFunc: func() *txs.Tx { - output0 := output - output0.Out = &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: outputOwners, - } - - output1 := output - output1.Out = &secp256k1fx.TransferOutput{ - Amt: 2, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output0, - &output1, - } - avax.SortTransferableOutputs(outputs, codec) - outputs[0], outputs[1] = outputs[1], outputs[0] - - baseTx := baseTx - baseTx.Outs = outputs - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: creds, - } - }, - err: avax.ErrOutputsNotSorted, - }, - { - name: "invalid input", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 0, - Input: inputSigners, - } - - baseTx := baseTx - baseTx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: creds, - } - }, - err: secp256k1fx.ErrNoValueInput, - }, - { - name: "duplicate inputs", - txFunc: func() *txs.Tx { - baseTx := baseTx - baseTx.Ins = []*avax.TransferableInput{ - &input, - &input, - } - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: avax.ErrInputsNotSortedUnique, - }, - { - name: "input overflow", - txFunc: func() *txs.Tx { - input0 := input - input0.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - input1 := input - input1.UTXOID.OutputIndex++ - input1.In = &secp256k1fx.TransferInput{ - Amt: math.MaxUint64, - Input: inputSigners, - } - - baseTx := baseTx - baseTx.Ins = []*avax.TransferableInput{ - &input0, - &input1, - } - avax.SortTransferableInputsWithSigners(baseTx.Ins, make([][]*secp256k1.PrivateKey, 2)) - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "output overflow", - txFunc: func() *txs.Tx { - output0 := output - output0.Out = &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: outputOwners, - } - - output1 := output - output1.Out = &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output0, - &output1, - } - avax.SortTransferableOutputs(outputs, codec) - - baseTx := baseTx - baseTx.Outs = outputs - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: creds, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - baseTx := baseTx - baseTx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "invalid output", + // txFunc: func() *txs.Tx { + // output := output + // output.Out = &secp256k1fx.TransferOutput{ + // Amt: 0, + // OutputOwners: outputOwners, + // } + + // baseTx := baseTx + // baseTx.Outs = []*avax.TransferableOutput{ + // &output, + // } + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueOutput, + // }, + // { + // name: "unsorted outputs", + // txFunc: func() *txs.Tx { + // output0 := output + // output0.Out = &secp256k1fx.TransferOutput{ + // Amt: 1, + // OutputOwners: outputOwners, + // } + + // output1 := output + // output1.Out = &secp256k1fx.TransferOutput{ + // Amt: 2, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output0, + // &output1, + // } + // avax.SortTransferableOutputs(outputs, codec) + // outputs[0], outputs[1] = outputs[1], outputs[0] + + // baseTx := baseTx + // baseTx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: creds, + // } + // }, + // err: avax.ErrOutputsNotSorted, + // }, + // { + // name: "invalid input", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 0, + // Input: inputSigners, + // } + + // baseTx := baseTx + // baseTx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueInput, + // }, + // { + // name: "duplicate inputs", + // txFunc: func() *txs.Tx { + // baseTx := baseTx + // baseTx.Ins = []*avax.TransferableInput{ + // &input, + // &input, + // } + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: avax.ErrInputsNotSortedUnique, + // }, + // { + // name: "input overflow", + // txFunc: func() *txs.Tx { + // input0 := input + // input0.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // input1 := input + // input1.UTXOID.OutputIndex++ + // input1.In = &secp256k1fx.TransferInput{ + // Amt: math.MaxUint64, + // Input: inputSigners, + // } + + // baseTx := baseTx + // baseTx.Ins = []*avax.TransferableInput{ + // &input0, + // &input1, + // } + // avax.SortTransferableInputsWithSigners(baseTx.Ins, make([][]*secp256k1.PrivateKey, 2)) + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "output overflow", + // txFunc: func() *txs.Tx { + // output0 := output + // output0.Out = &secp256k1fx.TransferOutput{ + // Amt: 1, + // OutputOwners: outputOwners, + // } + + // output1 := output + // output1.Out = &secp256k1fx.TransferOutput{ + // Amt: math.MaxUint64, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output0, + // &output1, + // } + // avax.SortTransferableOutputs(outputs, codec) + + // baseTx := baseTx + // baseTx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: creds, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // baseTx := baseTx + // baseTx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, { name: "invalid credential", txFunc: func() *txs.Tx { @@ -355,46 +352,46 @@ func TestSyntacticVerifierBaseTx(t *testing.T) { }, err: errWrongNumberOfCredentials, }, - { - name: "barely sufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.TxFee, - Input: inputSigners, - } - - baseTx := baseTx - baseTx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: creds, - } - }, - err: nil, - }, - { - name: "barely insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.TxFee - 1, - Input: inputSigners, - } - - baseTx := baseTx - baseTx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &txs.BaseTx{BaseTx: baseTx}, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "barely sufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.TxFee, + // Input: inputSigners, + // } + + // baseTx := baseTx + // baseTx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: creds, + // } + // }, + // err: nil, + // }, + // { + // name: "barely insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.TxFee - 1, + // Input: inputSigners, + // } + + // baseTx := baseTx + // baseTx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &txs.BaseTx{BaseTx: baseTx}, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -659,177 +656,177 @@ func TestSyntacticVerifierCreateAssetTx(t *testing.T) { }, err: avax.ErrMemoTooLarge, }, - { - name: "invalid output", - txFunc: func() *txs.Tx { - output := output - output.Out = &secp256k1fx.TransferOutput{ - Amt: 0, - OutputOwners: outputOwners, - } - - tx := tx - tx.Outs = []*avax.TransferableOutput{ - &output, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: secp256k1fx.ErrNoValueOutput, - }, - { - name: "unsorted outputs", - txFunc: func() *txs.Tx { - output0 := output - output0.Out = &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: outputOwners, - } - - output1 := output - output1.Out = &secp256k1fx.TransferOutput{ - Amt: 2, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output0, - &output1, - } - avax.SortTransferableOutputs(outputs, codec) - outputs[0], outputs[1] = outputs[1], outputs[0] - - tx := tx - tx.Outs = outputs - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrOutputsNotSorted, - }, - { - name: "invalid input", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 0, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: secp256k1fx.ErrNoValueInput, - }, - { - name: "duplicate inputs", - txFunc: func() *txs.Tx { - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: avax.ErrInputsNotSortedUnique, - }, - { - name: "input overflow", - txFunc: func() *txs.Tx { - input0 := input - input0.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - input1 := input - input1.UTXOID.OutputIndex++ - input1.In = &secp256k1fx.TransferInput{ - Amt: math.MaxUint64, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input0, - &input1, - } - avax.SortTransferableInputsWithSigners(baseTx.Ins, make([][]*secp256k1.PrivateKey, 2)) - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "output overflow", - txFunc: func() *txs.Tx { - output0 := output - output0.Out = &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: outputOwners, - } - - output1 := output - output1.Out = &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output0, - &output1, - } - avax.SortTransferableOutputs(outputs, codec) - - tx := tx - tx.Outs = outputs - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "invalid output", + // txFunc: func() *txs.Tx { + // output := output + // output.Out = &secp256k1fx.TransferOutput{ + // Amt: 0, + // OutputOwners: outputOwners, + // } + + // tx := tx + // tx.Outs = []*avax.TransferableOutput{ + // &output, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueOutput, + // }, + // { + // name: "unsorted outputs", + // txFunc: func() *txs.Tx { + // output0 := output + // output0.Out = &secp256k1fx.TransferOutput{ + // Amt: 1, + // OutputOwners: outputOwners, + // } + + // output1 := output + // output1.Out = &secp256k1fx.TransferOutput{ + // Amt: 2, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output0, + // &output1, + // } + // avax.SortTransferableOutputs(outputs, codec) + // outputs[0], outputs[1] = outputs[1], outputs[0] + + // tx := tx + // tx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrOutputsNotSorted, + // }, + // { + // name: "invalid input", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 0, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueInput, + // }, + // { + // name: "duplicate inputs", + // txFunc: func() *txs.Tx { + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: avax.ErrInputsNotSortedUnique, + // }, + // { + // name: "input overflow", + // txFunc: func() *txs.Tx { + // input0 := input + // input0.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // input1 := input + // input1.UTXOID.OutputIndex++ + // input1.In = &secp256k1fx.TransferInput{ + // Amt: math.MaxUint64, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input0, + // &input1, + // } + // avax.SortTransferableInputsWithSigners(baseTx.Ins, make([][]*secp256k1.PrivateKey, 2)) + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "output overflow", + // txFunc: func() *txs.Tx { + // output0 := output + // output0.Out = &secp256k1fx.TransferOutput{ + // Amt: 1, + // OutputOwners: outputOwners, + // } + + // output1 := output + // output1.Out = &secp256k1fx.TransferOutput{ + // Amt: math.MaxUint64, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output0, + // &output1, + // } + // avax.SortTransferableOutputs(outputs, codec) + + // tx := tx + // tx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, { name: "invalid nil state", txFunc: func() *txs.Tx { @@ -965,46 +962,46 @@ func TestSyntacticVerifierCreateAssetTx(t *testing.T) { }, err: errWrongNumberOfCredentials, }, - { - name: "barely sufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.CreateAssetTxFee, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: nil, - }, - { - name: "barely insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.CreateAssetTxFee - 1, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "barely sufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.CreateAssetTxFee, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: nil, + // }, + // { + // name: "barely insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.CreateAssetTxFee - 1, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -1181,220 +1178,220 @@ func TestSyntacticVerifierOperationTx(t *testing.T) { }, err: avax.ErrMemoTooLarge, }, + // { + // name: "invalid output", + // txFunc: func() *txs.Tx { + // output := output + // output.Out = &secp256k1fx.TransferOutput{ + // Amt: 0, + // OutputOwners: outputOwners, + // } + + // tx := tx + // tx.Outs = []*avax.TransferableOutput{ + // &output, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueOutput, + // }, + // { + // name: "unsorted outputs", + // txFunc: func() *txs.Tx { + // output0 := output + // output0.Out = &secp256k1fx.TransferOutput{ + // Amt: 1, + // OutputOwners: outputOwners, + // } + + // output1 := output + // output1.Out = &secp256k1fx.TransferOutput{ + // Amt: 2, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output0, + // &output1, + // } + // avax.SortTransferableOutputs(outputs, codec) + // outputs[0], outputs[1] = outputs[1], outputs[0] + + // tx := tx + // tx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrOutputsNotSorted, + // }, + // { + // name: "invalid input", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 0, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueInput, + // }, + // { + // name: "duplicate inputs", + // txFunc: func() *txs.Tx { + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: avax.ErrInputsNotSortedUnique, + // }, + // { + // name: "input overflow", + // txFunc: func() *txs.Tx { + // input0 := input + // input0.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // input1 := input + // input1.UTXOID.OutputIndex++ + // input1.In = &secp256k1fx.TransferInput{ + // Amt: math.MaxUint64, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input0, + // &input1, + // } + // avax.SortTransferableInputsWithSigners(tx.Ins, make([][]*secp256k1.PrivateKey, 2)) + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "output overflow", + // txFunc: func() *txs.Tx { + // output := output + // output.Out = &secp256k1fx.TransferOutput{ + // Amt: math.MaxUint64, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output, + // } + // avax.SortTransferableOutputs(outputs, codec) + + // tx := tx + // tx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, { - name: "invalid output", + name: "invalid nil op", txFunc: func() *txs.Tx { - output := output - output.Out = &secp256k1fx.TransferOutput{ - Amt: 0, - OutputOwners: outputOwners, - } - tx := tx - tx.Outs = []*avax.TransferableOutput{ - &output, + tx.Ops = []*txs.Operation{ + nil, } return &txs.Tx{ Unsigned: &tx, Creds: creds, } }, - err: secp256k1fx.ErrNoValueOutput, + err: txs.ErrNilOperation, }, { - name: "unsorted outputs", + name: "invalid nil fx op", txFunc: func() *txs.Tx { - output0 := output - output0.Out = &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: outputOwners, - } - - output1 := output - output1.Out = &secp256k1fx.TransferOutput{ - Amt: 2, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output0, - &output1, - } - avax.SortTransferableOutputs(outputs, codec) - outputs[0], outputs[1] = outputs[1], outputs[0] + op := op + op.Op = nil tx := tx - tx.Outs = outputs + tx.Ops = []*txs.Operation{ + &op, + } return &txs.Tx{ Unsigned: &tx, Creds: creds, } }, - err: avax.ErrOutputsNotSorted, + err: txs.ErrNilFxOperation, }, { - name: "invalid input", + name: "invalid duplicated op UTXOs", txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 0, - Input: inputSigners, + op := op + op.UTXOIDs = []*avax.UTXOID{ + &opUTXOID, + &opUTXOID, } tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, + tx.Ops = []*txs.Operation{ + &op, } return &txs.Tx{ Unsigned: &tx, Creds: creds, } }, - err: secp256k1fx.ErrNoValueInput, - }, - { - name: "duplicate inputs", - txFunc: func() *txs.Tx { - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: avax.ErrInputsNotSortedUnique, - }, - { - name: "input overflow", - txFunc: func() *txs.Tx { - input0 := input - input0.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - input1 := input - input1.UTXOID.OutputIndex++ - input1.In = &secp256k1fx.TransferInput{ - Amt: math.MaxUint64, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input0, - &input1, - } - avax.SortTransferableInputsWithSigners(tx.Ins, make([][]*secp256k1.PrivateKey, 2)) - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "output overflow", - txFunc: func() *txs.Tx { - output := output - output.Out = &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output, - } - avax.SortTransferableOutputs(outputs, codec) - - tx := tx - tx.Outs = outputs - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, - { - name: "invalid nil op", - txFunc: func() *txs.Tx { - tx := tx - tx.Ops = []*txs.Operation{ - nil, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: txs.ErrNilOperation, - }, - { - name: "invalid nil fx op", - txFunc: func() *txs.Tx { - op := op - op.Op = nil - - tx := tx - tx.Ops = []*txs.Operation{ - &op, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: txs.ErrNilFxOperation, - }, - { - name: "invalid duplicated op UTXOs", - txFunc: func() *txs.Tx { - op := op - op.UTXOIDs = []*avax.UTXOID{ - &opUTXOID, - &opUTXOID, - } - - tx := tx - tx.Ops = []*txs.Operation{ - &op, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: txs.ErrNotSortedAndUniqueUTXOIDs, + err: txs.ErrNotSortedAndUniqueUTXOIDs, }, { name: "invalid duplicated UTXOs across ops", @@ -1455,46 +1452,46 @@ func TestSyntacticVerifierOperationTx(t *testing.T) { }, err: errWrongNumberOfCredentials, }, - { - name: "barely sufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.TxFee, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: nil, - }, - { - name: "barely insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.TxFee - 1, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "barely sufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.TxFee, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: nil, + // }, + // { + // name: "barely insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.TxFee - 1, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -1652,189 +1649,189 @@ func TestSyntacticVerifierImportTx(t *testing.T) { }, err: avax.ErrMemoTooLarge, }, - { - name: "invalid output", - txFunc: func() *txs.Tx { - output := output - output.Out = &secp256k1fx.TransferOutput{ - Amt: 0, - OutputOwners: outputOwners, - } - - tx := tx - tx.Outs = []*avax.TransferableOutput{ - &output, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: secp256k1fx.ErrNoValueOutput, - }, - { - name: "unsorted outputs", - txFunc: func() *txs.Tx { - output0 := output - output0.Out = &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: outputOwners, - } - - output1 := output - output1.Out = &secp256k1fx.TransferOutput{ - Amt: 2, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output0, - &output1, - } - avax.SortTransferableOutputs(outputs, codec) - outputs[0], outputs[1] = outputs[1], outputs[0] - - tx := tx - tx.Outs = outputs - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrOutputsNotSorted, - }, - { - name: "invalid input", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 0, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: secp256k1fx.ErrNoValueInput, - }, - { - name: "duplicate inputs", - txFunc: func() *txs.Tx { - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - &cred, - }, - } - }, - err: avax.ErrInputsNotSortedUnique, - }, - { - name: "duplicate imported inputs", - txFunc: func() *txs.Tx { - tx := tx - tx.ImportedIns = []*avax.TransferableInput{ - &input, - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: avax.ErrInputsNotSortedUnique, - }, - { - name: "input overflow", - txFunc: func() *txs.Tx { - input0 := input - input0.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - input1 := input - input1.UTXOID.OutputIndex++ - input1.In = &secp256k1fx.TransferInput{ - Amt: math.MaxUint64, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input0, - &input1, - } - avax.SortTransferableInputsWithSigners(tx.Ins, make([][]*secp256k1.PrivateKey, 2)) - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "output overflow", - txFunc: func() *txs.Tx { - output := output - output.Out = &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output, - } - avax.SortTransferableOutputs(outputs, codec) - - tx := tx - tx.Outs = outputs - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - tx := tx - tx.ImportedIns = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "invalid output", + // txFunc: func() *txs.Tx { + // output := output + // output.Out = &secp256k1fx.TransferOutput{ + // Amt: 0, + // OutputOwners: outputOwners, + // } + + // tx := tx + // tx.Outs = []*avax.TransferableOutput{ + // &output, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueOutput, + // }, + // { + // name: "unsorted outputs", + // txFunc: func() *txs.Tx { + // output0 := output + // output0.Out = &secp256k1fx.TransferOutput{ + // Amt: 1, + // OutputOwners: outputOwners, + // } + + // output1 := output + // output1.Out = &secp256k1fx.TransferOutput{ + // Amt: 2, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output0, + // &output1, + // } + // avax.SortTransferableOutputs(outputs, codec) + // outputs[0], outputs[1] = outputs[1], outputs[0] + + // tx := tx + // tx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrOutputsNotSorted, + // }, + // { + // name: "invalid input", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 0, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueInput, + // }, + // { + // name: "duplicate inputs", + // txFunc: func() *txs.Tx { + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // &cred, + // }, + // } + // }, + // err: avax.ErrInputsNotSortedUnique, + // }, + // { + // name: "duplicate imported inputs", + // txFunc: func() *txs.Tx { + // tx := tx + // tx.ImportedIns = []*avax.TransferableInput{ + // &input, + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: avax.ErrInputsNotSortedUnique, + // }, + // { + // name: "input overflow", + // txFunc: func() *txs.Tx { + // input0 := input + // input0.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // input1 := input + // input1.UTXOID.OutputIndex++ + // input1.In = &secp256k1fx.TransferInput{ + // Amt: math.MaxUint64, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input0, + // &input1, + // } + // avax.SortTransferableInputsWithSigners(tx.Ins, make([][]*secp256k1.PrivateKey, 2)) + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "output overflow", + // txFunc: func() *txs.Tx { + // output := output + // output.Out = &secp256k1fx.TransferOutput{ + // Amt: math.MaxUint64, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output, + // } + // avax.SortTransferableOutputs(outputs, codec) + + // tx := tx + // tx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // tx := tx + // tx.ImportedIns = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, { name: "invalid credential", txFunc: func() *txs.Tx { @@ -1856,46 +1853,46 @@ func TestSyntacticVerifierImportTx(t *testing.T) { }, err: errWrongNumberOfCredentials, }, - { - name: "barely sufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.TxFee, - Input: inputSigners, - } - - tx := tx - tx.ImportedIns = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: nil, - }, - { - name: "barely insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.TxFee - 1, - Input: inputSigners, - } - - tx := tx - tx.ImportedIns = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "barely sufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.TxFee, + // Input: inputSigners, + // } + + // tx := tx + // tx.ImportedIns = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: nil, + // }, + // { + // name: "barely insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.TxFee - 1, + // Input: inputSigners, + // } + + // tx := tx + // tx.ImportedIns = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -2053,201 +2050,201 @@ func TestSyntacticVerifierExportTx(t *testing.T) { }, err: avax.ErrMemoTooLarge, }, - { - name: "invalid output", - txFunc: func() *txs.Tx { - output := output - output.Out = &secp256k1fx.TransferOutput{ - Amt: 0, - OutputOwners: outputOwners, - } - - tx := tx - tx.Outs = []*avax.TransferableOutput{ - &output, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: secp256k1fx.ErrNoValueOutput, - }, - { - name: "unsorted outputs", - txFunc: func() *txs.Tx { - output0 := output - output0.Out = &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: outputOwners, - } - - output1 := output - output1.Out = &secp256k1fx.TransferOutput{ - Amt: 2, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output0, - &output1, - } - avax.SortTransferableOutputs(outputs, codec) - outputs[0], outputs[1] = outputs[1], outputs[0] - - tx := tx - tx.Outs = outputs - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrOutputsNotSorted, - }, - { - name: "unsorted exported outputs", - txFunc: func() *txs.Tx { - output0 := output - output0.Out = &secp256k1fx.TransferOutput{ - Amt: 1, - OutputOwners: outputOwners, - } - - output1 := output - output1.Out = &secp256k1fx.TransferOutput{ - Amt: 2, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output0, - &output1, - } - avax.SortTransferableOutputs(outputs, codec) - outputs[0], outputs[1] = outputs[1], outputs[0] - - tx := tx - tx.ExportedOuts = outputs - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrOutputsNotSorted, - }, - { - name: "invalid input", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 0, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: secp256k1fx.ErrNoValueInput, - }, - { - name: "duplicate inputs", - txFunc: func() *txs.Tx { - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: avax.ErrInputsNotSortedUnique, - }, - { - name: "input overflow", - txFunc: func() *txs.Tx { - input0 := input - input0.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - input1 := input - input1.UTXOID.OutputIndex++ - input1.In = &secp256k1fx.TransferInput{ - Amt: math.MaxUint64, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input0, - &input1, - } - avax.SortTransferableInputsWithSigners(tx.Ins, make([][]*secp256k1.PrivateKey, 2)) - return &txs.Tx{ - Unsigned: &tx, - Creds: []*fxs.FxCredential{ - &cred, - &cred, - }, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "output overflow", - txFunc: func() *txs.Tx { - output := output - output.Out = &secp256k1fx.TransferOutput{ - Amt: math.MaxUint64, - OutputOwners: outputOwners, - } - - outputs := []*avax.TransferableOutput{ - &output, - } - avax.SortTransferableOutputs(outputs, codec) - - tx := tx - tx.Outs = outputs - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: safemath.ErrOverflow, - }, - { - name: "insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: 1, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "invalid output", + // txFunc: func() *txs.Tx { + // output := output + // output.Out = &secp256k1fx.TransferOutput{ + // Amt: 0, + // OutputOwners: outputOwners, + // } + + // tx := tx + // tx.Outs = []*avax.TransferableOutput{ + // &output, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueOutput, + // }, + // { + // name: "unsorted outputs", + // txFunc: func() *txs.Tx { + // output0 := output + // output0.Out = &secp256k1fx.TransferOutput{ + // Amt: 1, + // OutputOwners: outputOwners, + // } + + // output1 := output + // output1.Out = &secp256k1fx.TransferOutput{ + // Amt: 2, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output0, + // &output1, + // } + // avax.SortTransferableOutputs(outputs, codec) + // outputs[0], outputs[1] = outputs[1], outputs[0] + + // tx := tx + // tx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrOutputsNotSorted, + // }, + // { + // name: "unsorted exported outputs", + // txFunc: func() *txs.Tx { + // output0 := output + // output0.Out = &secp256k1fx.TransferOutput{ + // Amt: 1, + // OutputOwners: outputOwners, + // } + + // output1 := output + // output1.Out = &secp256k1fx.TransferOutput{ + // Amt: 2, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output0, + // &output1, + // } + // avax.SortTransferableOutputs(outputs, codec) + // outputs[0], outputs[1] = outputs[1], outputs[0] + + // tx := tx + // tx.ExportedOuts = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrOutputsNotSorted, + // }, + // { + // name: "invalid input", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 0, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: secp256k1fx.ErrNoValueInput, + // }, + // { + // name: "duplicate inputs", + // txFunc: func() *txs.Tx { + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: avax.ErrInputsNotSortedUnique, + // }, + // { + // name: "input overflow", + // txFunc: func() *txs.Tx { + // input0 := input + // input0.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // input1 := input + // input1.UTXOID.OutputIndex++ + // input1.In = &secp256k1fx.TransferInput{ + // Amt: math.MaxUint64, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input0, + // &input1, + // } + // avax.SortTransferableInputsWithSigners(tx.Ins, make([][]*secp256k1.PrivateKey, 2)) + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: []*fxs.FxCredential{ + // &cred, + // &cred, + // }, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "output overflow", + // txFunc: func() *txs.Tx { + // output := output + // output.Out = &secp256k1fx.TransferOutput{ + // Amt: math.MaxUint64, + // OutputOwners: outputOwners, + // } + + // outputs := []*avax.TransferableOutput{ + // &output, + // } + // avax.SortTransferableOutputs(outputs, codec) + + // tx := tx + // tx.Outs = outputs + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: safemath.ErrOverflow, + // }, + // { + // name: "insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: 1, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, { name: "invalid credential", txFunc: func() *txs.Tx { @@ -2269,46 +2266,46 @@ func TestSyntacticVerifierExportTx(t *testing.T) { }, err: errWrongNumberOfCredentials, }, - { - name: "barely sufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.TxFee, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: nil, - }, - { - name: "barely insufficient funds", - txFunc: func() *txs.Tx { - input := input - input.In = &secp256k1fx.TransferInput{ - Amt: fxOutput.Amt + feeConfig.TxFee - 1, - Input: inputSigners, - } - - tx := tx - tx.Ins = []*avax.TransferableInput{ - &input, - } - return &txs.Tx{ - Unsigned: &tx, - Creds: creds, - } - }, - err: avax.ErrInsufficientFunds, - }, + // { + // name: "barely sufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.TxFee, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: nil, + // }, + // { + // name: "barely insufficient funds", + // txFunc: func() *txs.Tx { + // input := input + // input.In = &secp256k1fx.TransferInput{ + // Amt: fxOutput.Amt + feeConfig.TxFee - 1, + // Input: inputSigners, + // } + + // tx := tx + // tx.Ins = []*avax.TransferableInput{ + // &input, + // } + // return &txs.Tx{ + // Unsigned: &tx, + // Creds: creds, + // } + // }, + // err: avax.ErrInsufficientFunds, + // }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) {