diff --git a/vms/platformvm/block/executor/verifier_test.go b/vms/platformvm/block/executor/verifier_test.go index 2aa5e3ade0f..247703abc42 100644 --- a/vms/platformvm/block/executor/verifier_test.go +++ b/vms/platformvm/block/executor/verifier_test.go @@ -132,6 +132,7 @@ func TestVerifierVisitProposalBlock(t *testing.T) { } blkTx := txsmock.NewUnsignedTx(ctrl) + blkTx.EXPECT().Visit(gomock.AssignableToTypeOf(&executor.WarpVerifier{})).Return(nil).Times(1) blkTx.EXPECT().Visit(gomock.AssignableToTypeOf(&executor.ProposalTxExecutor{})).Return(nil).Times(1) // We can't serialize [blkTx] because it isn't @@ -214,6 +215,7 @@ func TestVerifierVisitAtomicBlock(t *testing.T) { onAccept := state.NewMockDiff(ctrl) blkTx := txsmock.NewUnsignedTx(ctrl) inputs := set.Of(ids.GenerateTestID()) + blkTx.EXPECT().Visit(gomock.AssignableToTypeOf(&executor.WarpVerifier{})).Return(nil).Times(1) blkTx.EXPECT().Visit(gomock.AssignableToTypeOf(&executor.AtomicTxExecutor{})).DoAndReturn( func(e *executor.AtomicTxExecutor) error { e.OnAccept = onAccept @@ -306,6 +308,7 @@ func TestVerifierVisitStandardBlock(t *testing.T) { }, }, } + blkTx.EXPECT().Visit(gomock.AssignableToTypeOf(&executor.WarpVerifier{})).Return(nil).Times(1) blkTx.EXPECT().Visit(gomock.AssignableToTypeOf(&executor.StandardTxExecutor{})).DoAndReturn( func(e *executor.StandardTxExecutor) error { e.OnAccept = func() {} diff --git a/vms/platformvm/txs/executor/standard_tx_executor.go b/vms/platformvm/txs/executor/standard_tx_executor.go index eaa23bb8b94..b80c79534b0 100644 --- a/vms/platformvm/txs/executor/standard_tx_executor.go +++ b/vms/platformvm/txs/executor/standard_tx_executor.go @@ -49,6 +49,8 @@ var ( errEtnaUpgradeNotActive = errors.New("attempting to use an Etna-upgrade feature prior to activation") errTransformSubnetTxPostEtna = errors.New("TransformSubnetTx is not permitted post-Etna") errMaxNumActiveValidators = errors.New("already at the max number of active validators") + + errStateCorruption = errors.New("state corruption") ) type StandardTxExecutor struct { @@ -877,9 +879,10 @@ func (e *StandardTxExecutor) SetSubnetValidatorWeightTx(tx *txs.SetSubnetValidat accruedFees := e.State.GetAccruedFees() if sov.EndAccumulatedFee <= accruedFees { - // This should never happen as the validator should have been - // evicted. - return fmt.Errorf("validator has insufficient funds to cover accrued fees") + // This check should be unreachable. However, including it ensures + // that AVAX can't get minted out of thin air due to state + // corruption. + return fmt.Errorf("%w: validator should have already been disabled", errStateCorruption) } remainingBalance := sov.EndAccumulatedFee - accruedFees diff --git a/vms/platformvm/txs/executor/warp_verifier.go b/vms/platformvm/txs/executor/warp_verifier.go index edf05aa61f0..7572a3dfe84 100644 --- a/vms/platformvm/txs/executor/warp_verifier.go +++ b/vms/platformvm/txs/executor/warp_verifier.go @@ -16,7 +16,7 @@ const ( WarpQuorumDenominator = 100 ) -var _ txs.Visitor = (*warpVerifier)(nil) +var _ txs.Visitor = (*WarpVerifier)(nil) // VerifyWarpMessages verifies all warp messages in the tx. If any of the warp // messages are invalid, an error is returned. @@ -27,109 +27,109 @@ func VerifyWarpMessages( pChainHeight uint64, tx txs.UnsignedTx, ) error { - return tx.Visit(&warpVerifier{ - ctx: ctx, - networkID: networkID, - validatorState: validatorState, - pChainHeight: pChainHeight, + return tx.Visit(&WarpVerifier{ + Context: ctx, + NetworkID: networkID, + ValidatorState: validatorState, + PChainHeight: pChainHeight, }) } -type warpVerifier struct { - ctx context.Context - networkID uint32 - validatorState validators.State - pChainHeight uint64 +type WarpVerifier struct { + Context context.Context + NetworkID uint32 + ValidatorState validators.State + PChainHeight uint64 } -func (*warpVerifier) AddValidatorTx(*txs.AddValidatorTx) error { +func (*WarpVerifier) AddValidatorTx(*txs.AddValidatorTx) error { return nil } -func (*warpVerifier) AddSubnetValidatorTx(*txs.AddSubnetValidatorTx) error { +func (*WarpVerifier) AddSubnetValidatorTx(*txs.AddSubnetValidatorTx) error { return nil } -func (*warpVerifier) AddDelegatorTx(*txs.AddDelegatorTx) error { +func (*WarpVerifier) AddDelegatorTx(*txs.AddDelegatorTx) error { return nil } -func (*warpVerifier) CreateChainTx(*txs.CreateChainTx) error { +func (*WarpVerifier) CreateChainTx(*txs.CreateChainTx) error { return nil } -func (*warpVerifier) CreateSubnetTx(*txs.CreateSubnetTx) error { +func (*WarpVerifier) CreateSubnetTx(*txs.CreateSubnetTx) error { return nil } -func (*warpVerifier) ImportTx(*txs.ImportTx) error { +func (*WarpVerifier) ImportTx(*txs.ImportTx) error { return nil } -func (*warpVerifier) ExportTx(*txs.ExportTx) error { +func (*WarpVerifier) ExportTx(*txs.ExportTx) error { return nil } -func (*warpVerifier) AdvanceTimeTx(*txs.AdvanceTimeTx) error { +func (*WarpVerifier) AdvanceTimeTx(*txs.AdvanceTimeTx) error { return nil } -func (*warpVerifier) RewardValidatorTx(*txs.RewardValidatorTx) error { +func (*WarpVerifier) RewardValidatorTx(*txs.RewardValidatorTx) error { return nil } -func (*warpVerifier) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { +func (*WarpVerifier) RemoveSubnetValidatorTx(*txs.RemoveSubnetValidatorTx) error { return nil } -func (*warpVerifier) TransformSubnetTx(*txs.TransformSubnetTx) error { +func (*WarpVerifier) TransformSubnetTx(*txs.TransformSubnetTx) error { return nil } -func (*warpVerifier) AddPermissionlessValidatorTx(*txs.AddPermissionlessValidatorTx) error { +func (*WarpVerifier) AddPermissionlessValidatorTx(*txs.AddPermissionlessValidatorTx) error { return nil } -func (*warpVerifier) AddPermissionlessDelegatorTx(*txs.AddPermissionlessDelegatorTx) error { +func (*WarpVerifier) AddPermissionlessDelegatorTx(*txs.AddPermissionlessDelegatorTx) error { return nil } -func (*warpVerifier) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { +func (*WarpVerifier) TransferSubnetOwnershipTx(*txs.TransferSubnetOwnershipTx) error { return nil } -func (*warpVerifier) BaseTx(*txs.BaseTx) error { +func (*WarpVerifier) BaseTx(*txs.BaseTx) error { return nil } -func (*warpVerifier) ConvertSubnetTx(*txs.ConvertSubnetTx) error { +func (*WarpVerifier) ConvertSubnetTx(*txs.ConvertSubnetTx) error { return nil } -func (w *warpVerifier) IncreaseBalanceTx(tx *txs.IncreaseBalanceTx) error { +func (w *WarpVerifier) IncreaseBalanceTx(*txs.IncreaseBalanceTx) error { return nil } -func (w *warpVerifier) RegisterSubnetValidatorTx(tx *txs.RegisterSubnetValidatorTx) error { +func (w *WarpVerifier) RegisterSubnetValidatorTx(tx *txs.RegisterSubnetValidatorTx) error { return w.verify(tx.Message) } -func (w *warpVerifier) SetSubnetValidatorWeightTx(tx *txs.SetSubnetValidatorWeightTx) error { +func (w *WarpVerifier) SetSubnetValidatorWeightTx(tx *txs.SetSubnetValidatorWeightTx) error { return w.verify(tx.Message) } -func (w *warpVerifier) verify(message []byte) error { +func (w *WarpVerifier) verify(message []byte) error { msg, err := warp.ParseMessage(message) if err != nil { return err } return msg.Signature.Verify( - w.ctx, + w.Context, &msg.UnsignedMessage, - w.networkID, - w.validatorState, - w.pChainHeight, + w.NetworkID, + w.ValidatorState, + w.PChainHeight, WarpQuorumNumerator, WarpQuorumDenominator, )