From 5b06d93a84847414ca151aeff55f4be03514c3aa Mon Sep 17 00:00:00 2001 From: Stephen Buttolph Date: Thu, 7 Nov 2024 15:43:16 -0500 Subject: [PATCH] Standardize P-Chain tx visitor order (#3529) --- vms/platformvm/metrics/tx_metrics.go | 8 +- .../txs/executor/atomic_tx_executor.go | 6 +- .../txs/executor/standard_tx_executor.go | 368 +++++++++--------- vms/platformvm/txs/fee/complexity.go | 232 +++++------ vms/platformvm/txs/fee/static_calculator.go | 22 +- vms/platformvm/txs/visitor.go | 9 +- wallet/chain/p/signer/visitor.go | 32 +- wallet/chain/p/wallet/backend_visitor.go | 40 +- 8 files changed, 362 insertions(+), 355 deletions(-) diff --git a/vms/platformvm/metrics/tx_metrics.go b/vms/platformvm/metrics/tx_metrics.go index fd6c63494f7c..7957cb6ab2e9 100644 --- a/vms/platformvm/metrics/tx_metrics.go +++ b/vms/platformvm/metrics/tx_metrics.go @@ -132,16 +132,16 @@ func (m *txMetrics) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) er return nil } -func (m *txMetrics) ConvertSubnetTx(*txs.ConvertSubnetTx) error { +func (m *txMetrics) BaseTx(*txs.BaseTx) error { m.numTxs.With(prometheus.Labels{ - txLabel: "convert_subnet", + txLabel: "base", }).Inc() return nil } -func (m *txMetrics) BaseTx(*txs.BaseTx) error { +func (m *txMetrics) ConvertSubnetTx(*txs.ConvertSubnetTx) error { m.numTxs.With(prometheus.Labels{ - txLabel: "base", + txLabel: "convert_subnet", }).Inc() return nil } diff --git a/vms/platformvm/txs/executor/atomic_tx_executor.go b/vms/platformvm/txs/executor/atomic_tx_executor.go index ea5294c2559c..1977608d09c1 100644 --- a/vms/platformvm/txs/executor/atomic_tx_executor.go +++ b/vms/platformvm/txs/executor/atomic_tx_executor.go @@ -92,15 +92,15 @@ func (*atomicTxExecutor) TransformSubnetTx(*txs.TransformSubnetTx) error { return ErrWrongTxType } -func (*atomicTxExecutor) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { +func (*atomicTxExecutor) AddPermissionlessValidatorTx(*txs.AddPermissionlessValidatorTx) error { return ErrWrongTxType } -func (*atomicTxExecutor) AddPermissionlessValidatorTx(*txs.AddPermissionlessValidatorTx) error { +func (*atomicTxExecutor) AddPermissionlessDelegatorTx(*txs.AddPermissionlessDelegatorTx) error { return ErrWrongTxType } -func (*atomicTxExecutor) AddPermissionlessDelegatorTx(*txs.AddPermissionlessDelegatorTx) error { +func (*atomicTxExecutor) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { return ErrWrongTxType } diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index 7c561473a7bd..3ccc059bfa8e 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -88,6 +88,82 @@ func (*standardTxExecutor) RewardValidatorTx(*txs.RewardValidatorTx) error { return ErrWrongTxType } +func (e *standardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { + if tx.Validator.NodeID == ids.EmptyNodeID { + return errEmptyNodeID + } + + if _, err := verifyAddValidatorTx( + e.backend, + e.feeCalculator, + e.state, + e.tx, + tx, + ); err != nil { + return err + } + + if err := e.putStaker(tx); err != nil { + return err + } + + txID := e.tx.ID() + avax.Consume(e.state, tx.Ins) + avax.Produce(e.state, txID, tx.Outs) + + if e.backend.Config.PartialSyncPrimaryNetwork && tx.Validator.NodeID == e.backend.Ctx.NodeID { + e.backend.Ctx.Log.Warn("verified transaction that would cause this node to become unhealthy", + zap.String("reason", "primary network is not being fully synced"), + zap.Stringer("txID", txID), + zap.String("txType", "addValidator"), + zap.Stringer("nodeID", tx.Validator.NodeID), + ) + } + return nil +} + +func (e *standardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error { + if err := verifyAddSubnetValidatorTx( + e.backend, + e.feeCalculator, + e.state, + e.tx, + tx, + ); err != nil { + return err + } + + if err := e.putStaker(tx); err != nil { + return err + } + + txID := e.tx.ID() + avax.Consume(e.state, tx.Ins) + avax.Produce(e.state, txID, tx.Outs) + return nil +} + +func (e *standardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { + if _, err := verifyAddDelegatorTx( + e.backend, + e.feeCalculator, + e.state, + e.tx, + tx, + ); err != nil { + return err + } + + if err := e.putStaker(tx); err != nil { + return err + } + + txID := e.tx.ID() + avax.Consume(e.state, tx.Ins) + avax.Produce(e.state, txID, tx.Outs) + return nil +} + func (e *standardTxExecutor) CreateChainTx(tx *txs.CreateChainTx) error { if err := e.tx.SyntacticVerify(e.backend.Ctx); err != nil { return err @@ -361,42 +437,101 @@ func (e *standardTxExecutor) ExportTx(tx *txs.ExportTx) error { return nil } -func (e *standardTxExecutor) AddValidatorTx(tx *txs.AddValidatorTx) error { - if tx.Validator.NodeID == ids.EmptyNodeID { - return errEmptyNodeID - } - - if _, err := verifyAddValidatorTx( +// Verifies a [*txs.RemoveSubnetValidatorTx] and, if it passes, executes it on +// [e.State]. For verification rules, see [verifyRemoveSubnetValidatorTx]. This +// transaction will result in [tx.NodeID] being removed as a validator of +// [tx.SubnetID]. +// Note: [tx.NodeID] may be either a current or pending validator. +func (e *standardTxExecutor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { + staker, isCurrentValidator, err := verifyRemoveSubnetValidatorTx( e.backend, e.feeCalculator, e.state, e.tx, tx, - ); err != nil { + ) + if err != nil { return err } - if err := e.putStaker(tx); err != nil { - return err + if isCurrentValidator { + e.state.DeleteCurrentValidator(staker) + } else { + e.state.DeletePendingValidator(staker) } + // Invariant: There are no permissioned subnet delegators to remove. + txID := e.tx.ID() avax.Consume(e.state, tx.Ins) avax.Produce(e.state, txID, tx.Outs) - if e.backend.Config.PartialSyncPrimaryNetwork && tx.Validator.NodeID == e.backend.Ctx.NodeID { - e.backend.Ctx.Log.Warn("verified transaction that would cause this node to become unhealthy", - zap.String("reason", "primary network is not being fully synced"), - zap.Stringer("txID", txID), - zap.String("txType", "addValidator"), - zap.Stringer("nodeID", tx.Validator.NodeID), - ) + return nil +} + +func (e *standardTxExecutor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { + currentTimestamp := e.state.GetTimestamp() + if e.backend.Config.UpgradeConfig.IsEtnaActivated(currentTimestamp) { + return errTransformSubnetTxPostEtna + } + + if err := e.tx.SyntacticVerify(e.backend.Ctx); err != nil { + return err + } + + isDurangoActive := e.backend.Config.UpgradeConfig.IsDurangoActivated(currentTimestamp) + if err := avax.VerifyMemoFieldLength(tx.Memo, isDurangoActive); err != nil { + return err + } + + // Note: math.MaxInt32 * time.Second < math.MaxInt64 - so this can never + // overflow. + if time.Duration(tx.MaxStakeDuration)*time.Second > e.backend.Config.MaxStakeDuration { + return errMaxStakeDurationTooLarge + } + + baseTxCreds, err := verifyPoASubnetAuthorization(e.backend, e.state, e.tx, tx.Subnet, tx.SubnetAuth) + if err != nil { + return err + } + + // Verify the flowcheck + fee, err := e.feeCalculator.CalculateFee(tx) + if err != nil { + return err } + totalRewardAmount := tx.MaximumSupply - tx.InitialSupply + if err := e.backend.FlowChecker.VerifySpend( + tx, + e.state, + tx.Ins, + tx.Outs, + baseTxCreds, + // Invariant: [tx.AssetID != e.Ctx.AVAXAssetID]. This prevents the first + // entry in this map literal from being overwritten by the + // second entry. + map[ids.ID]uint64{ + e.backend.Ctx.AVAXAssetID: fee, + tx.AssetID: totalRewardAmount, + }, + ); err != nil { + return err + } + + txID := e.tx.ID() + + // Consume the UTXOS + avax.Consume(e.state, tx.Ins) + // Produce the UTXOS + avax.Produce(e.state, txID, tx.Outs) + // Transform the new subnet in the database + e.state.AddSubnetTransformation(e.tx) + e.state.SetCurrentSupply(tx.Subnet, tx.InitialSupply) return nil } -func (e *standardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error { - if err := verifyAddSubnetValidatorTx( +func (e *standardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { + if err := verifyAddPermissionlessValidatorTx( e.backend, e.feeCalculator, e.state, @@ -413,11 +548,23 @@ func (e *standardTxExecutor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) txID := e.tx.ID() avax.Consume(e.state, tx.Ins) avax.Produce(e.state, txID, tx.Outs) + + if e.backend.Config.PartialSyncPrimaryNetwork && + tx.Subnet == constants.PrimaryNetworkID && + tx.Validator.NodeID == e.backend.Ctx.NodeID { + e.backend.Ctx.Log.Warn("verified transaction that would cause this node to become unhealthy", + zap.String("reason", "primary network is not being fully synced"), + zap.Stringer("txID", txID), + zap.String("txType", "addPermissionlessValidator"), + zap.Stringer("nodeID", tx.Validator.NodeID), + ) + } + return nil } -func (e *standardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { - if _, err := verifyAddDelegatorTx( +func (e *standardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { + if err := verifyAddPermissionlessDelegatorTx( e.backend, e.feeCalculator, e.state, @@ -437,13 +584,12 @@ func (e *standardTxExecutor) AddDelegatorTx(tx *txs.AddDelegatorTx) error { return nil } -// Verifies a [*txs.RemoveSubnetValidatorTx] and, if it passes, executes it on -// [e.State]. For verification rules, see [verifyRemoveSubnetValidatorTx]. This -// transaction will result in [tx.NodeID] being removed as a validator of -// [tx.SubnetID]. -// Note: [tx.NodeID] may be either a current or pending validator. -func (e *standardTxExecutor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { - staker, isCurrentValidator, err := verifyRemoveSubnetValidatorTx( +// Verifies a [*txs.TransferSubnetOwnershipTx] and, if it passes, executes it on +// [e.State]. For verification rules, see [verifyTransferSubnetOwnershipTx]. +// This transaction will result in the ownership of [tx.Subnet] being transferred +// to [tx.Owner]. +func (e *standardTxExecutor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { + err := verifyTransferSubnetOwnershipTx( e.backend, e.feeCalculator, e.state, @@ -454,44 +600,29 @@ func (e *standardTxExecutor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidat return err } - if isCurrentValidator { - e.state.DeleteCurrentValidator(staker) - } else { - e.state.DeletePendingValidator(staker) - } - - // Invariant: There are no permissioned subnet delegators to remove. + e.state.SetSubnetOwner(tx.Subnet, tx.Owner) txID := e.tx.ID() avax.Consume(e.state, tx.Ins) avax.Produce(e.state, txID, tx.Outs) - return nil } -func (e *standardTxExecutor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { - currentTimestamp := e.state.GetTimestamp() - if e.backend.Config.UpgradeConfig.IsEtnaActivated(currentTimestamp) { - return errTransformSubnetTxPostEtna +func (e *standardTxExecutor) BaseTx(tx *txs.BaseTx) error { + var ( + currentTimestamp = e.state.GetTimestamp() + upgrades = e.backend.Config.UpgradeConfig + ) + if !upgrades.IsDurangoActivated(currentTimestamp) { + return ErrDurangoUpgradeNotActive } + // Verify the tx is well-formed if err := e.tx.SyntacticVerify(e.backend.Ctx); err != nil { return err } - isDurangoActive := e.backend.Config.UpgradeConfig.IsDurangoActivated(currentTimestamp) - if err := avax.VerifyMemoFieldLength(tx.Memo, isDurangoActive); err != nil { - return err - } - - // Note: math.MaxInt32 * time.Second < math.MaxInt64 - so this can never - // overflow. - if time.Duration(tx.MaxStakeDuration)*time.Second > e.backend.Config.MaxStakeDuration { - return errMaxStakeDurationTooLarge - } - - baseTxCreds, err := verifyPoASubnetAuthorization(e.backend, e.state, e.tx, tx.Subnet, tx.SubnetAuth) - if err != nil { + if err := avax.VerifyMemoFieldLength(tx.Memo, true /*=isDurangoActive*/); err != nil { return err } @@ -500,33 +631,24 @@ func (e *standardTxExecutor) TransformSubnetTx(tx *txs.TransformSubnetTx) error if err != nil { return err } - totalRewardAmount := tx.MaximumSupply - tx.InitialSupply if err := e.backend.FlowChecker.VerifySpend( tx, e.state, tx.Ins, tx.Outs, - baseTxCreds, - // Invariant: [tx.AssetID != e.Ctx.AVAXAssetID]. This prevents the first - // entry in this map literal from being overwritten by the - // second entry. + e.tx.Creds, map[ids.ID]uint64{ e.backend.Ctx.AVAXAssetID: fee, - tx.AssetID: totalRewardAmount, }, ); err != nil { return err } txID := e.tx.ID() - // Consume the UTXOS avax.Consume(e.state, tx.Ins) // Produce the UTXOS avax.Produce(e.state, txID, tx.Outs) - // Transform the new subnet in the database - e.state.AddSubnetTransformation(e.tx) - e.state.SetCurrentSupply(tx.Subnet, tx.InitialSupply) return nil } @@ -658,128 +780,6 @@ func (e *standardTxExecutor) ConvertSubnetTx(tx *txs.ConvertSubnetTx) error { return nil } -func (e *standardTxExecutor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { - if err := verifyAddPermissionlessValidatorTx( - e.backend, - e.feeCalculator, - e.state, - e.tx, - tx, - ); err != nil { - return err - } - - if err := e.putStaker(tx); err != nil { - return err - } - - txID := e.tx.ID() - avax.Consume(e.state, tx.Ins) - avax.Produce(e.state, txID, tx.Outs) - - if e.backend.Config.PartialSyncPrimaryNetwork && - tx.Subnet == constants.PrimaryNetworkID && - tx.Validator.NodeID == e.backend.Ctx.NodeID { - e.backend.Ctx.Log.Warn("verified transaction that would cause this node to become unhealthy", - zap.String("reason", "primary network is not being fully synced"), - zap.Stringer("txID", txID), - zap.String("txType", "addPermissionlessValidator"), - zap.Stringer("nodeID", tx.Validator.NodeID), - ) - } - - return nil -} - -func (e *standardTxExecutor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { - if err := verifyAddPermissionlessDelegatorTx( - e.backend, - e.feeCalculator, - e.state, - e.tx, - tx, - ); err != nil { - return err - } - - if err := e.putStaker(tx); err != nil { - return err - } - - txID := e.tx.ID() - avax.Consume(e.state, tx.Ins) - avax.Produce(e.state, txID, tx.Outs) - return nil -} - -// Verifies a [*txs.TransferSubnetOwnershipTx] and, if it passes, executes it on -// [e.State]. For verification rules, see [verifyTransferSubnetOwnershipTx]. -// This transaction will result in the ownership of [tx.Subnet] being transferred -// to [tx.Owner]. -func (e *standardTxExecutor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { - err := verifyTransferSubnetOwnershipTx( - e.backend, - e.feeCalculator, - e.state, - e.tx, - tx, - ) - if err != nil { - return err - } - - e.state.SetSubnetOwner(tx.Subnet, tx.Owner) - - txID := e.tx.ID() - avax.Consume(e.state, tx.Ins) - avax.Produce(e.state, txID, tx.Outs) - return nil -} - -func (e *standardTxExecutor) BaseTx(tx *txs.BaseTx) error { - var ( - currentTimestamp = e.state.GetTimestamp() - upgrades = e.backend.Config.UpgradeConfig - ) - if !upgrades.IsDurangoActivated(currentTimestamp) { - return ErrDurangoUpgradeNotActive - } - - // Verify the tx is well-formed - if err := e.tx.SyntacticVerify(e.backend.Ctx); err != nil { - return err - } - - if err := avax.VerifyMemoFieldLength(tx.Memo, true /*=isDurangoActive*/); err != nil { - return err - } - - // Verify the flowcheck - fee, err := e.feeCalculator.CalculateFee(tx) - if err != nil { - return err - } - if err := e.backend.FlowChecker.VerifySpend( - tx, - e.state, - tx.Ins, - tx.Outs, - e.tx.Creds, - map[ids.ID]uint64{ - e.backend.Ctx.AVAXAssetID: fee, - }, - ); err != nil { - return err - } - - txID := e.tx.ID() - // Consume the UTXOS - avax.Consume(e.state, tx.Ins) - // Produce the UTXOS - avax.Produce(e.state, txID, tx.Outs) - return nil -} - // Creates the staker as defined in [stakerTx] and adds it to [e.State]. func (e *standardTxExecutor) putStaker(stakerTx txs.Staker) error { var ( diff --git a/vms/platformvm/txs/fee/complexity.go b/vms/platformvm/txs/fee/complexity.go index 5683ac6b3b6a..e1891a3d51a1 100644 --- a/vms/platformvm/txs/fee/complexity.go +++ b/vms/platformvm/txs/fee/complexity.go @@ -83,29 +83,6 @@ const ( var ( _ txs.Visitor = (*complexityVisitor)(nil) - IntrinsicAddPermissionlessValidatorTxComplexities = gas.Dimensions{ - gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + - intrinsicValidatorBandwidth + // validator - ids.IDLen + // subnetID - wrappers.IntLen + // signer typeID - wrappers.IntLen + // num stake outs - wrappers.IntLen + // validator rewards typeID - wrappers.IntLen + // delegator rewards typeID - wrappers.IntLen, // delegation shares - gas.DBRead: 1, - gas.DBWrite: 1, - gas.Compute: 0, - } - IntrinsicAddPermissionlessDelegatorTxComplexities = gas.Dimensions{ - gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + - intrinsicValidatorBandwidth + // validator - ids.IDLen + // subnetID - wrappers.IntLen + // num stake outs - wrappers.IntLen, // delegator rewards typeID - gas.DBRead: 1, - gas.DBWrite: 1, - gas.Compute: 0, - } IntrinsicAddSubnetValidatorTxComplexities = gas.Dimensions{ gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + intrinsicSubnetValidatorBandwidth + // subnetValidator @@ -115,19 +92,6 @@ var ( gas.DBWrite: 1, gas.Compute: 0, } - IntrinsicBaseTxComplexities = gas.Dimensions{ - gas.Bandwidth: codec.VersionSize + // codecVersion - wrappers.IntLen + // typeID - wrappers.IntLen + // networkID - ids.IDLen + // blockchainID - wrappers.IntLen + // number of outputs - wrappers.IntLen + // number of inputs - wrappers.IntLen + // length of memo - wrappers.IntLen, // number of credentials - gas.DBRead: 0, - gas.DBWrite: 0, - gas.Compute: 0, - } IntrinsicCreateChainTxComplexities = gas.Dimensions{ gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + ids.IDLen + // subnetID @@ -148,18 +112,18 @@ var ( gas.DBWrite: 1, gas.Compute: 0, } - IntrinsicExportTxComplexities = gas.Dimensions{ + IntrinsicImportTxComplexities = gas.Dimensions{ gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + - ids.IDLen + // destination chainID - wrappers.IntLen, // num exported outputs + ids.IDLen + // source chainID + wrappers.IntLen, // num importing inputs gas.DBRead: 0, gas.DBWrite: 0, gas.Compute: 0, } - IntrinsicImportTxComplexities = gas.Dimensions{ + IntrinsicExportTxComplexities = gas.Dimensions{ gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + - ids.IDLen + // source chainID - wrappers.IntLen, // num importing inputs + ids.IDLen + // destination chainID + wrappers.IntLen, // num exported outputs gas.DBRead: 0, gas.DBWrite: 0, gas.Compute: 0, @@ -174,6 +138,29 @@ var ( gas.DBWrite: 1, gas.Compute: 0, } + IntrinsicAddPermissionlessValidatorTxComplexities = gas.Dimensions{ + gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + + intrinsicValidatorBandwidth + // validator + ids.IDLen + // subnetID + wrappers.IntLen + // signer typeID + wrappers.IntLen + // num stake outs + wrappers.IntLen + // validator rewards typeID + wrappers.IntLen + // delegator rewards typeID + wrappers.IntLen, // delegation shares + gas.DBRead: 1, + gas.DBWrite: 1, + gas.Compute: 0, + } + IntrinsicAddPermissionlessDelegatorTxComplexities = gas.Dimensions{ + gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + + intrinsicValidatorBandwidth + // validator + ids.IDLen + // subnetID + wrappers.IntLen + // num stake outs + wrappers.IntLen, // delegator rewards typeID + gas.DBRead: 1, + gas.DBWrite: 1, + gas.Compute: 0, + } IntrinsicTransferSubnetOwnershipTxComplexities = gas.Dimensions{ gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + ids.IDLen + // subnetID @@ -184,6 +171,19 @@ var ( gas.DBWrite: 1, gas.Compute: 0, } + IntrinsicBaseTxComplexities = gas.Dimensions{ + gas.Bandwidth: codec.VersionSize + // codecVersion + wrappers.IntLen + // typeID + wrappers.IntLen + // networkID + ids.IDLen + // blockchainID + wrappers.IntLen + // number of outputs + wrappers.IntLen + // number of inputs + wrappers.IntLen + // length of memo + wrappers.IntLen, // number of credentials + gas.DBRead: 0, + gas.DBWrite: 0, + gas.Compute: 0, + } IntrinsicConvertSubnetTxComplexities = gas.Dimensions{ gas.Bandwidth: IntrinsicBaseTxComplexities[gas.Bandwidth] + ids.IDLen + // subnetID @@ -440,11 +440,11 @@ type complexityVisitor struct { output gas.Dimensions } -func (*complexityVisitor) AddDelegatorTx(*txs.AddDelegatorTx) error { +func (*complexityVisitor) AddValidatorTx(*txs.AddValidatorTx) error { return ErrUnsupportedTx } -func (*complexityVisitor) AddValidatorTx(*txs.AddValidatorTx) error { +func (*complexityVisitor) AddDelegatorTx(*txs.AddDelegatorTx) error { return ErrUnsupportedTx } @@ -460,60 +460,6 @@ func (*complexityVisitor) TransformSubnetTx(*txs.TransformSubnetTx) error { return ErrUnsupportedTx } -func (c *complexityVisitor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { - // TODO: Should we include additional complexity for subnets? - baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) - if err != nil { - return err - } - signerComplexity, err := SignerComplexity(tx.Signer) - if err != nil { - return err - } - outputsComplexity, err := OutputComplexity(tx.StakeOuts...) - if err != nil { - return err - } - validatorOwnerComplexity, err := OwnerComplexity(tx.ValidatorRewardsOwner) - if err != nil { - return err - } - delegatorOwnerComplexity, err := OwnerComplexity(tx.DelegatorRewardsOwner) - if err != nil { - return err - } - c.output, err = IntrinsicAddPermissionlessValidatorTxComplexities.Add( - &baseTxComplexity, - &signerComplexity, - &outputsComplexity, - &validatorOwnerComplexity, - &delegatorOwnerComplexity, - ) - return err -} - -func (c *complexityVisitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { - // TODO: Should we include additional complexity for subnets? - baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) - if err != nil { - return err - } - ownerComplexity, err := OwnerComplexity(tx.DelegationRewardsOwner) - if err != nil { - return err - } - outputsComplexity, err := OutputComplexity(tx.StakeOuts...) - if err != nil { - return err - } - c.output, err = IntrinsicAddPermissionlessDelegatorTxComplexities.Add( - &baseTxComplexity, - &ownerComplexity, - &outputsComplexity, - ) - return err -} - func (c *complexityVisitor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) error { baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) if err != nil { @@ -530,15 +476,6 @@ func (c *complexityVisitor) AddSubnetValidatorTx(tx *txs.AddSubnetValidatorTx) e return err } -func (c *complexityVisitor) BaseTx(tx *txs.BaseTx) error { - baseTxComplexity, err := baseTxComplexity(tx) - if err != nil { - return err - } - c.output, err = IntrinsicBaseTxComplexities.Add(&baseTxComplexity) - return err -} - func (c *complexityVisitor) CreateChainTx(tx *txs.CreateChainTx) error { bandwidth, err := math.Mul(uint64(len(tx.FxIDs)), ids.IDLen) if err != nil { @@ -591,6 +528,23 @@ func (c *complexityVisitor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { return err } +func (c *complexityVisitor) ImportTx(tx *txs.ImportTx) error { + baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) + if err != nil { + return err + } + // TODO: Should imported inputs be more complex? + inputsComplexity, err := InputComplexity(tx.ImportedInputs...) + if err != nil { + return err + } + c.output, err = IntrinsicImportTxComplexities.Add( + &baseTxComplexity, + &inputsComplexity, + ) + return err +} + func (c *complexityVisitor) ExportTx(tx *txs.ExportTx) error { baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) if err != nil { @@ -608,35 +562,72 @@ func (c *complexityVisitor) ExportTx(tx *txs.ExportTx) error { return err } -func (c *complexityVisitor) ImportTx(tx *txs.ImportTx) error { +func (c *complexityVisitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) if err != nil { return err } - // TODO: Should imported inputs be more complex? - inputsComplexity, err := InputComplexity(tx.ImportedInputs...) + authComplexity, err := AuthComplexity(tx.SubnetAuth) if err != nil { return err } - c.output, err = IntrinsicImportTxComplexities.Add( + c.output, err = IntrinsicRemoveSubnetValidatorTxComplexities.Add( &baseTxComplexity, - &inputsComplexity, + &authComplexity, ) return err } -func (c *complexityVisitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { +func (c *complexityVisitor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { + // TODO: Should we include additional complexity for subnets? baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) if err != nil { return err } - authComplexity, err := AuthComplexity(tx.SubnetAuth) + signerComplexity, err := SignerComplexity(tx.Signer) if err != nil { return err } - c.output, err = IntrinsicRemoveSubnetValidatorTxComplexities.Add( + outputsComplexity, err := OutputComplexity(tx.StakeOuts...) + if err != nil { + return err + } + validatorOwnerComplexity, err := OwnerComplexity(tx.ValidatorRewardsOwner) + if err != nil { + return err + } + delegatorOwnerComplexity, err := OwnerComplexity(tx.DelegatorRewardsOwner) + if err != nil { + return err + } + c.output, err = IntrinsicAddPermissionlessValidatorTxComplexities.Add( &baseTxComplexity, - &authComplexity, + &signerComplexity, + &outputsComplexity, + &validatorOwnerComplexity, + &delegatorOwnerComplexity, + ) + return err +} + +func (c *complexityVisitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { + // TODO: Should we include additional complexity for subnets? + baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) + if err != nil { + return err + } + ownerComplexity, err := OwnerComplexity(tx.DelegationRewardsOwner) + if err != nil { + return err + } + outputsComplexity, err := OutputComplexity(tx.StakeOuts...) + if err != nil { + return err + } + c.output, err = IntrinsicAddPermissionlessDelegatorTxComplexities.Add( + &baseTxComplexity, + &ownerComplexity, + &outputsComplexity, ) return err } @@ -662,6 +653,15 @@ func (c *complexityVisitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwne return err } +func (c *complexityVisitor) BaseTx(tx *txs.BaseTx) error { + baseTxComplexity, err := baseTxComplexity(tx) + if err != nil { + return err + } + c.output, err = IntrinsicBaseTxComplexities.Add(&baseTxComplexity) + return err +} + func (c *complexityVisitor) ConvertSubnetTx(tx *txs.ConvertSubnetTx) error { baseTxComplexity, err := baseTxComplexity(&tx.BaseTx) if err != nil { diff --git a/vms/platformvm/txs/fee/static_calculator.go b/vms/platformvm/txs/fee/static_calculator.go index 888ccba8621c..1b97349ce2cb 100644 --- a/vms/platformvm/txs/fee/static_calculator.go +++ b/vms/platformvm/txs/fee/static_calculator.go @@ -76,21 +76,26 @@ func (c *staticVisitor) CreateSubnetTx(*txs.CreateSubnetTx) error { return nil } -func (c *staticVisitor) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { +func (c *staticVisitor) ImportTx(*txs.ImportTx) error { c.fee = c.config.TxFee return nil } -func (c *staticVisitor) TransformSubnetTx(*txs.TransformSubnetTx) error { - c.fee = c.config.TransformSubnetTxFee +func (c *staticVisitor) ExportTx(*txs.ExportTx) error { + c.fee = c.config.TxFee return nil } -func (c *staticVisitor) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { +func (c *staticVisitor) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { c.fee = c.config.TxFee return nil } +func (c *staticVisitor) TransformSubnetTx(*txs.TransformSubnetTx) error { + c.fee = c.config.TransformSubnetTxFee + return nil +} + func (c *staticVisitor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { if tx.Subnet != constants.PrimaryNetworkID { c.fee = c.config.AddSubnetValidatorFee @@ -109,17 +114,12 @@ func (c *staticVisitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDe return nil } -func (c *staticVisitor) BaseTx(*txs.BaseTx) error { - c.fee = c.config.TxFee - return nil -} - -func (c *staticVisitor) ImportTx(*txs.ImportTx) error { +func (c *staticVisitor) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { c.fee = c.config.TxFee return nil } -func (c *staticVisitor) ExportTx(*txs.ExportTx) error { +func (c *staticVisitor) BaseTx(*txs.BaseTx) error { c.fee = c.config.TxFee return nil } diff --git a/vms/platformvm/txs/visitor.go b/vms/platformvm/txs/visitor.go index 142a6115d7af..21c46476fa5f 100644 --- a/vms/platformvm/txs/visitor.go +++ b/vms/platformvm/txs/visitor.go @@ -5,6 +5,7 @@ package txs // Allow vm to execute custom logic against the underlying transaction types. type Visitor interface { + // Apricot Transactions: AddValidatorTx(*AddValidatorTx) error AddSubnetValidatorTx(*AddSubnetValidatorTx) error AddDelegatorTx(*AddDelegatorTx) error @@ -14,11 +15,17 @@ type Visitor interface { ExportTx(*ExportTx) error AdvanceTimeTx(*AdvanceTimeTx) error RewardValidatorTx(*RewardValidatorTx) error + + // Banff Transactions: RemoveSubnetValidatorTx(*RemoveSubnetValidatorTx) error TransformSubnetTx(*TransformSubnetTx) error AddPermissionlessValidatorTx(*AddPermissionlessValidatorTx) error AddPermissionlessDelegatorTx(*AddPermissionlessDelegatorTx) error + + // Durango Transactions: TransferSubnetOwnershipTx(*TransferSubnetOwnershipTx) error - ConvertSubnetTx(*ConvertSubnetTx) error BaseTx(*BaseTx) error + + // Etna Transactions: + ConvertSubnetTx(*ConvertSubnetTx) error } diff --git a/wallet/chain/p/signer/visitor.go b/wallet/chain/p/signer/visitor.go index 38d501c908b0..b358e1f5d5ea 100644 --- a/wallet/chain/p/signer/visitor.go +++ b/wallet/chain/p/signer/visitor.go @@ -51,14 +51,6 @@ func (*visitor) RewardValidatorTx(*txs.RewardValidatorTx) error { return ErrUnsupportedTxType } -func (s *visitor) BaseTx(tx *txs.BaseTx) error { - txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) - if err != nil { - return err - } - return sign(s.tx, false, txSigners) -} - func (s *visitor) AddValidatorTx(tx *txs.AddValidatorTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { @@ -143,7 +135,7 @@ func (s *visitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error return sign(s.tx, true, txSigners) } -func (s *visitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { +func (s *visitor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -156,20 +148,23 @@ func (s *visitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) e return sign(s.tx, true, txSigners) } -func (s *visitor) ConvertSubnetTx(tx *txs.ConvertSubnetTx) error { +func (s *visitor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err } - subnetAuthSigners, err := s.getSubnetSigners(tx.Subnet, tx.SubnetAuth) + return sign(s.tx, true, txSigners) +} + +func (s *visitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { + txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err } - txSigners = append(txSigners, subnetAuthSigners) return sign(s.tx, true, txSigners) } -func (s *visitor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { +func (s *visitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err @@ -182,19 +177,24 @@ func (s *visitor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { return sign(s.tx, true, txSigners) } -func (s *visitor) AddPermissionlessValidatorTx(tx *txs.AddPermissionlessValidatorTx) error { +func (s *visitor) BaseTx(tx *txs.BaseTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err } - return sign(s.tx, true, txSigners) + return sign(s.tx, false, txSigners) } -func (s *visitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessDelegatorTx) error { +func (s *visitor) ConvertSubnetTx(tx *txs.ConvertSubnetTx) error { txSigners, err := s.getSigners(constants.PlatformChainID, tx.Ins) if err != nil { return err } + subnetAuthSigners, err := s.getSubnetSigners(tx.Subnet, tx.SubnetAuth) + if err != nil { + return err + } + txSigners = append(txSigners, subnetAuthSigners) return sign(s.tx, true, txSigners) } diff --git a/wallet/chain/p/wallet/backend_visitor.go b/wallet/chain/p/wallet/backend_visitor.go index 8e44ee3b5e2d..f2f9e646edf8 100644 --- a/wallet/chain/p/wallet/backend_visitor.go +++ b/wallet/chain/p/wallet/backend_visitor.go @@ -58,26 +58,6 @@ func (b *backendVisitor) CreateSubnetTx(tx *txs.CreateSubnetTx) error { return b.baseTx(&tx.BaseTx) } -func (b *backendVisitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { - return b.baseTx(&tx.BaseTx) -} - -func (b *backendVisitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { - b.b.setSubnetOwner( - tx.Subnet, - tx.Owner, - ) - return b.baseTx(&tx.BaseTx) -} - -func (b *backendVisitor) ConvertSubnetTx(tx *txs.ConvertSubnetTx) error { - return b.baseTx(&tx.BaseTx) -} - -func (b *backendVisitor) BaseTx(tx *txs.BaseTx) error { - return b.baseTx(tx) -} - func (b *backendVisitor) ImportTx(tx *txs.ImportTx) error { err := b.b.removeUTXOs( b.ctx, @@ -111,6 +91,10 @@ func (b *backendVisitor) ExportTx(tx *txs.ExportTx) error { return b.baseTx(&tx.BaseTx) } +func (b *backendVisitor) RemoveSubnetValidatorTx(tx *txs.RemoveSubnetValidatorTx) error { + return b.baseTx(&tx.BaseTx) +} + func (b *backendVisitor) TransformSubnetTx(tx *txs.TransformSubnetTx) error { return b.baseTx(&tx.BaseTx) } @@ -123,6 +107,22 @@ func (b *backendVisitor) AddPermissionlessDelegatorTx(tx *txs.AddPermissionlessD return b.baseTx(&tx.BaseTx) } +func (b *backendVisitor) TransferSubnetOwnershipTx(tx *txs.TransferSubnetOwnershipTx) error { + b.b.setSubnetOwner( + tx.Subnet, + tx.Owner, + ) + return b.baseTx(&tx.BaseTx) +} + +func (b *backendVisitor) BaseTx(tx *txs.BaseTx) error { + return b.baseTx(tx) +} + +func (b *backendVisitor) ConvertSubnetTx(tx *txs.ConvertSubnetTx) error { + return b.baseTx(&tx.BaseTx) +} + func (b *backendVisitor) baseTx(tx *txs.BaseTx) error { return b.b.removeUTXOs( b.ctx,