diff --git a/vms/platformvm/block/executor/verifier.go b/vms/platformvm/block/executor/verifier.go index 7d13bb038f1..6616fd58bad 100644 --- a/vms/platformvm/block/executor/verifier.go +++ b/vms/platformvm/block/executor/verifier.go @@ -93,7 +93,8 @@ func (v *verifier) BanffProposalBlock(b *block.BanffProposalBlock) error { } return v.proposalBlock( - &b.ApricotProposalBlock, + b, + b.Tx, onDecisionState, onCommitState, onAbortState, @@ -132,7 +133,12 @@ func (v *verifier) BanffStandardBlock(b *block.BanffStandardBlock) error { } feeCalculator := state.PickFeeCalculator(v.txExecutorBackend.Config, onAcceptState) - return v.standardBlock(&b.ApricotStandardBlock, feeCalculator, onAcceptState) + return v.standardBlock( + b, + b.Transactions, + feeCalculator, + onAcceptState, + ) } func (v *verifier) ApricotAbortBlock(b *block.ApricotAbortBlock) error { @@ -168,7 +174,17 @@ func (v *verifier) ApricotProposalBlock(b *block.ApricotProposalBlock) error { timestamp = onCommitState.GetTimestamp() // Equal to parent timestamp feeCalculator = state.NewStaticFeeCalculator(v.txExecutorBackend.Config, timestamp) ) - return v.proposalBlock(b, nil, onCommitState, onAbortState, feeCalculator, nil, nil, nil) + return v.proposalBlock( + b, + b.Tx, + nil, + onCommitState, + onAbortState, + feeCalculator, + nil, + nil, + nil, + ) } func (v *verifier) ApricotStandardBlock(b *block.ApricotStandardBlock) error { @@ -186,7 +202,12 @@ func (v *verifier) ApricotStandardBlock(b *block.ApricotStandardBlock) error { timestamp = onAcceptState.GetTimestamp() // Equal to parent timestamp feeCalculator = state.NewStaticFeeCalculator(v.txExecutorBackend.Config, timestamp) ) - return v.standardBlock(b, feeCalculator, onAcceptState) + return v.standardBlock( + b, + b.Transactions, + feeCalculator, + onAcceptState, + ) } func (v *verifier) ApricotAtomicBlock(b *block.ApricotAtomicBlock) error { @@ -364,7 +385,8 @@ func (v *verifier) commitBlock(b block.Block) error { // proposalBlock populates the state of this block if [nil] is returned func (v *verifier) proposalBlock( - b *block.ApricotProposalBlock, + b block.Block, + tx *txs.Tx, onDecisionState state.Diff, onCommitState state.Diff, onAbortState state.Diff, @@ -378,19 +400,19 @@ func (v *verifier) proposalBlock( OnAbortState: onAbortState, Backend: v.txExecutorBackend, FeeCalculator: feeCalculator, - Tx: b.Tx, + Tx: tx, } - if err := b.Tx.Unsigned.Visit(&txExecutor); err != nil { - txID := b.Tx.ID() + if err := tx.Unsigned.Visit(&txExecutor); err != nil { + txID := tx.ID() v.MarkDropped(txID, err) // cache tx as dropped return err } - onCommitState.AddTx(b.Tx, status.Committed) - onAbortState.AddTx(b.Tx, status.Aborted) + onCommitState.AddTx(tx, status.Committed) + onAbortState.AddTx(tx, status.Aborted) - v.Mempool.Remove(b.Tx) + v.Mempool.Remove(tx) blkID := b.ID() v.blkIDToState[blkID] = &blockState{ @@ -417,16 +439,22 @@ func (v *verifier) proposalBlock( // standardBlock populates the state of this block if [nil] is returned func (v *verifier) standardBlock( - b *block.ApricotStandardBlock, + b block.Block, + txs []*txs.Tx, feeCalculator fee.Calculator, onAcceptState state.Diff, ) error { - inputs, atomicRequests, onAcceptFunc, err := v.processStandardTxs(b.Transactions, feeCalculator, onAcceptState, b.Parent()) + inputs, atomicRequests, onAcceptFunc, err := v.processStandardTxs( + txs, + feeCalculator, + onAcceptState, + b.Parent(), + ) if err != nil { return err } - v.Mempool.Remove(b.Transactions...) + v.Mempool.Remove(txs...) blkID := b.ID() v.blkIDToState[blkID] = &blockState{ diff --git a/vms/platformvm/block/executor/verifier_test.go b/vms/platformvm/block/executor/verifier_test.go index da3ef3e330f..8606f42127c 100644 --- a/vms/platformvm/block/executor/verifier_test.go +++ b/vms/platformvm/block/executor/verifier_test.go @@ -1208,8 +1208,9 @@ func TestBlockExecutionWithComplexity(t *testing.T) { } require.Contains(verifier.blkIDToState, blkID) - onAcceptState := verifier.blkIDToState[blkID].onAcceptState - require.Equal(test.expectedFeeState, onAcceptState.GetFeeState()) + blockState := verifier.blkIDToState[blkID] + require.Equal(blk, blockState.statelessBlock) + require.Equal(test.expectedFeeState, blockState.onAcceptState.GetFeeState()) }) } } diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 129d210b120..bede6daaea8 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -2261,9 +2261,11 @@ func (s *state) writeSubnetOnlyValidators(updateValidators bool, height uint64) return err } - subnetIDNodeIDKey := make([]byte, len(sov.SubnetID)+len(sov.NodeID)) - copy(subnetIDNodeIDKey, sov.SubnetID[:]) - copy(subnetIDNodeIDKey[len(sov.SubnetID):], sov.NodeID[:]) + subnetIDNodeID := subnetIDNodeID{ + subnetID: sov.SubnetID, + nodeID: sov.NodeID, + } + subnetIDNodeIDKey := subnetIDNodeID.Marshal() if err := s.subnetIDNodeIDDB.Delete(subnetIDNodeIDKey); err != nil { return err } @@ -2375,9 +2377,11 @@ func (s *state) writeSubnetOnlyValidators(updateValidators bool, height uint64) for validationID, sov := range sovChanges { validationID := validationID - subnetIDNodeIDKey := make([]byte, len(sov.SubnetID)+len(sov.NodeID)) - copy(subnetIDNodeIDKey, sov.SubnetID[:]) - copy(subnetIDNodeIDKey[len(sov.SubnetID):], sov.NodeID[:]) + subnetIDNodeID := subnetIDNodeID{ + subnetID: sov.SubnetID, + nodeID: sov.NodeID, + } + subnetIDNodeIDKey := subnetIDNodeID.Marshal() if err := s.subnetIDNodeIDDB.Put(subnetIDNodeIDKey, validationID[:]); err != nil { return err } diff --git a/vms/platformvm/state/subnet_only_validator.go b/vms/platformvm/state/subnet_only_validator.go index 487471a5f2b..180528bbb9e 100644 --- a/vms/platformvm/state/subnet_only_validator.go +++ b/vms/platformvm/state/subnet_only_validator.go @@ -18,11 +18,16 @@ import ( safemath "github.com/ava-labs/avalanchego/utils/math" ) +// subnetIDNodeID = [subnetID] + [nodeID] +const subnetIDNodeIDEntryLength = ids.IDLen + ids.NodeIDLen + var ( _ btree.LessFunc[SubnetOnlyValidator] = SubnetOnlyValidator.Less ErrMutatedSubnetOnlyValidator = errors.New("subnet only validator contains mutated constant fields") ErrDuplicateSubnetOnlyValidator = errors.New("subnet only validator contains conflicting subnetID + nodeID pair") + + errUnexpectedSubnetIDNodeIDLength = fmt.Errorf("expected subnetID+nodeID entry length %d", subnetIDNodeIDEntryLength) ) type SubnetOnlyValidators interface { @@ -172,6 +177,23 @@ type subnetIDNodeID struct { nodeID ids.NodeID } +func (s *subnetIDNodeID) Marshal() []byte { + data := make([]byte, subnetIDNodeIDEntryLength) + copy(data, s.subnetID[:]) + copy(data[ids.IDLen:], s.nodeID[:]) + return data +} + +func (s *subnetIDNodeID) Unmarshal(data []byte) error { + if len(data) != subnetIDNodeIDEntryLength { + return errUnexpectedSubnetIDNodeIDLength + } + + copy(s.subnetID[:], data) + copy(s.nodeID[:], data[ids.IDLen:]) + return nil +} + type subnetOnlyValidatorsDiff struct { numAddedActive int // May be negative modifiedTotalWeight map[ids.ID]uint64 // subnetID -> totalWeight