mirror of
https://github.com/luxfi/chains.git
synced 2026-09-24 00:26:00 +00:00
chain: keep only what something calls
Two pieces of the new package had no caller. Pool.Holds was the read side of a claim set that Add already enforces, so nothing ever needed to ask; it is gone, and the tests that used it now assert the same property through Add, which is the behaviour that matters. chain.Closed had no caller because M-Chain still declared its own NoUserTxPolicy. It declares chain.Closed() now — one fewer copy of a policy five chains state identically, and the one no-user-tx chain in this pass exercises the value that describes it.
This commit is contained in:
@@ -114,14 +114,6 @@ func (p *Pool[T, K]) Drop(entries []T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Holds reports whether a queued entry already claims c.
|
||||
func (p *Pool[T, K]) Holds(c K) bool {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
_, ok := p.held[c]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Len is how many entries are waiting.
|
||||
func (p *Pool[T, K]) Len() int {
|
||||
p.mu.Lock()
|
||||
|
||||
+4
-8
@@ -50,8 +50,6 @@ func TestASecondClaimOnQueuedWorkIsRefused(t *testing.T) {
|
||||
require.NoError(t, p.Add(at(1)))
|
||||
require.ErrorIs(t, p.Add(at(1)), ErrHeld)
|
||||
require.Equal(t, 1, p.Len())
|
||||
require.True(t, p.Holds(ids.ID{1}))
|
||||
require.False(t, p.Holds(ids.ID{2}))
|
||||
}
|
||||
|
||||
func TestAFullPoolRefusesRatherThanGrows(t *testing.T) {
|
||||
@@ -74,9 +72,8 @@ func TestAClaimDoesNotOutliveItsEntry(t *testing.T) {
|
||||
p.Drop([]entry{at(1)})
|
||||
|
||||
require.Equal(t, []entry{at(2)}, p.Take(0))
|
||||
require.False(t, p.Holds(ids.ID{1}), "the dropped entry holds nothing")
|
||||
require.True(t, p.Holds(ids.ID{2}), "the one still queued does")
|
||||
require.NoError(t, p.Add(at(1)), "and its claim can be made again")
|
||||
require.NoError(t, p.Add(at(1)), "the dropped entry's claim can be made again")
|
||||
require.ErrorIs(t, p.Add(at(2)), ErrHeld, "the one still queued still holds its own")
|
||||
}
|
||||
|
||||
func TestDroppingNothingChangesNothing(t *testing.T) {
|
||||
@@ -84,7 +81,7 @@ func TestDroppingNothingChangesNothing(t *testing.T) {
|
||||
require.NoError(t, p.Add(at(1)))
|
||||
p.Drop(nil)
|
||||
require.Equal(t, 1, p.Len())
|
||||
require.True(t, p.Holds(ids.ID{1}))
|
||||
require.ErrorIs(t, p.Add(at(1)), ErrHeld)
|
||||
}
|
||||
|
||||
func TestDroppingWhatWasNeverQueuedLeavesTheRestAlone(t *testing.T) {
|
||||
@@ -92,7 +89,7 @@ func TestDroppingWhatWasNeverQueuedLeavesTheRestAlone(t *testing.T) {
|
||||
require.NoError(t, p.Add(at(1)))
|
||||
p.Drop([]entry{at(9)})
|
||||
require.Equal(t, []entry{at(1)}, p.Take(0))
|
||||
require.True(t, p.Holds(ids.ID{1}))
|
||||
require.ErrorIs(t, p.Add(at(1)), ErrHeld)
|
||||
}
|
||||
|
||||
func TestAddingTellsConsensusThereIsSomethingToBuild(t *testing.T) {
|
||||
@@ -128,7 +125,6 @@ func TestConcurrentUseOfAPoolDoesNotRace(t *testing.T) {
|
||||
default:
|
||||
p.Take(4)
|
||||
p.Len()
|
||||
p.Holds(ids.ID{1})
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
+9
-25
@@ -7,29 +7,13 @@ import (
|
||||
"github.com/luxfi/node/vms/types/fee"
|
||||
)
|
||||
|
||||
// newFeePolicy returns the canonical M-Chain FeePolicy. M-Chain is a
|
||||
// committee-driven service VM — keygen / signing requests come from
|
||||
// validators via consensus, not a user mempool — so it declares the
|
||||
// NoUserTxPolicy sentinel. See vms/types/fee/policy.go.
|
||||
//
|
||||
// Any tx that reaches the fee gate on a NoUserTx chain is a wiring
|
||||
// bug; ValidateFee returns ErrChainAcceptsNoUserTxs.
|
||||
func newFeePolicy() fee.Policy {
|
||||
return fee.NoUserTxPolicy{}
|
||||
}
|
||||
// gateUserTx refuses every caller — M-Chain accepts no user txs. It is a
|
||||
// committee-driven service VM: keygen and signing requests come from validators
|
||||
// through consensus, not a user mempool. Any service entry that exposes itself
|
||||
// as user-callable MUST route through this gate, so the refusal is explicit
|
||||
// rather than a path nobody happened to write.
|
||||
func (vm *VM) gateUserTx() error { return vm.fee.Admit(0) }
|
||||
|
||||
// gateUserTx refuses every caller — M-Chain accepts no user txs.
|
||||
// Any service entry that exposes itself as user-callable MUST route
|
||||
// through this gate so the refusal is explicit, not implicit.
|
||||
func (vm *VM) gateUserTx() error {
|
||||
if vm.feePolicy == nil {
|
||||
return fee.ErrChainAcceptsNoUserTxs
|
||||
}
|
||||
// NoUserTxPolicy.ValidateFee ignores the args and always returns
|
||||
// ErrChainAcceptsNoUserTxs.
|
||||
return vm.feePolicy.ValidateFee(0, fee.NoUserTxPolicy{}.FeeAssetID())
|
||||
}
|
||||
|
||||
// FeePolicy exposes the chain's declared fee policy for diagnostics
|
||||
// and the boot-time Validate gate.
|
||||
func (vm *VM) FeePolicy() fee.Policy { return vm.feePolicy }
|
||||
// FeePolicy exposes the chain's declared fee policy for diagnostics and the
|
||||
// boot-time Validate gate.
|
||||
func (vm *VM) FeePolicy() fee.Policy { return vm.fee.Policy() }
|
||||
|
||||
@@ -7,12 +7,13 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/chains/chain"
|
||||
"github.com/luxfi/log"
|
||||
"github.com/luxfi/node/vms/types/fee"
|
||||
)
|
||||
|
||||
func TestThresholdVM_FeePolicy_IsNoUserTxSentinel(t *testing.T) {
|
||||
v := &VM{log: log.NewNoOpLogger(), feePolicy: newFeePolicy()}
|
||||
v := &VM{log: log.NewNoOpLogger(), fee: chain.Closed()}
|
||||
if v.FeePolicy() == nil {
|
||||
t.Fatal("FeePolicy() = nil; want NoUserTxPolicy")
|
||||
}
|
||||
@@ -25,7 +26,7 @@ func TestThresholdVM_FeePolicy_IsNoUserTxSentinel(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestThresholdVM_FeePolicy_RejectsAllUserTx(t *testing.T) {
|
||||
v := &VM{log: log.NewNoOpLogger(), feePolicy: newFeePolicy()}
|
||||
v := &VM{log: log.NewNoOpLogger(), fee: chain.Closed()}
|
||||
if err := v.gateUserTx(); !errors.Is(err, fee.ErrChainAcceptsNoUserTxs) {
|
||||
t.Fatalf("gateUserTx() = %v, want ErrChainAcceptsNoUserTxs", err)
|
||||
}
|
||||
|
||||
+5
-3
@@ -180,7 +180,9 @@ type VM struct {
|
||||
|
||||
// Fee policy. M-Chain is service-only (committee-driven, no
|
||||
// user mempool) so this is the NoUserTxPolicy sentinel.
|
||||
feePolicy fee.Policy
|
||||
// fee is what this chain charges to admit a user transaction, which is
|
||||
// nothing: M-Chain takes none.
|
||||
fee chain.Fee
|
||||
|
||||
// mu guards State and the VM's own maps. State is deliberately not safe for
|
||||
// concurrent use — a state machine with its own locking invites callers to
|
||||
@@ -238,8 +240,8 @@ func (vm *VM) Initialize(
|
||||
// Pin fee policy. M-Chain is service-only (committee-driven, no
|
||||
// user mempool) so attach the NoUserTxPolicy sentinel.
|
||||
// fee.Validate passes for the sentinel even with zero MinTxFee.
|
||||
vm.feePolicy = newFeePolicy()
|
||||
if err := fee.Validate(vm.feePolicy); err != nil {
|
||||
vm.fee = chain.Closed()
|
||||
if err := fee.Validate(vm.fee.Policy()); err != nil {
|
||||
return fmt.Errorf("mpcvm: fee policy: %w", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user