Files
chains/mpcvm/feegate_test.go
T
zeekay a93f6e3dec build the VMs without the daemon in their closure
A plugin is its own binary; the daemon that loads it has no business being
linked into it. Twelve VMs reached into github.com/luxfi/node for four things,
and each one now programs against a home that is actually its own:

- fee admission (Policy, FlatPolicy, NoUserTxPolicy, Validate) joins the
  settlement half already in chains/fee. One fee package, and the nodefee alias
  that marked the split is gone.
- the cross-chain artifact types move to chains/artifacts.
- the factory the daemon registers is luxfi/vm/manager.Factory, and the version
  types are luxfi/version. Both are ordinary modules the daemon reads too, so a
  VM imports them directly rather than through anything of ours.

The GPU switch is deleted, not moved. It was a global set during daemon startup
that a separate process could never observe, so every plugin read its default;
FHEOptions.Backend is the switch that was really there.

go list -deps names no luxfi/node for aivm, bridgevm, dexvm, evm, fhevm,
graphvm, identityvm, keyvm, mpcvm, quantumvm, schain or zkvm, and the built
plugin binaries carry no such string. oraclevm and relayvm still do: they are
re-export shims over luxfi/oracle and luxfi/relay, which build their fee
policies upstream. Their tests keep naming the daemon's fee package because
that is the type their value has.
2026-09-03 21:10:40 -07:00

58 lines
1.9 KiB
Go

// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package mpcvm
import (
"errors"
"testing"
"github.com/luxfi/chains/fee"
)
// M-Chain declares the closed policy: it is a committee-driven service VM and
// there is no mempool to admit anything into. The node's boot-time
// nodefee.Validate reads this declaration, and it passes for the sentinel with
// no minimum fee — which for any OTHER policy would be flagged as a zero-fee
// user-facing chain.
func TestMChainDeclaresItTakesNoUserTransactions(t *testing.T) {
vm := newVM(t)
policy := vm.Fee()
if policy == nil {
t.Fatal("Fee() = nil; a chain that declares no policy is a chain with no declared cost")
}
if _, ok := policy.(fee.NoUserTxPolicy); !ok {
t.Fatalf("Fee() = %T, want NoUserTxPolicy", policy)
}
if err := fee.Validate(policy); err != nil {
t.Fatalf("the node's boot gate rejects M-Chain's own declaration: %v", err)
}
}
// Refusal does not depend on how much is offered. A policy that admitted a
// large enough payment would make "M-Chain has no user entry" a matter of
// price.
func TestNoPaymentBuysAdmission(t *testing.T) {
vm := newVM(t)
for _, paid := range []uint64{0, 1, 1_000_000, 1 << 62} {
if err := vm.AdmitUserTx(paid); !errors.Is(err, fee.ErrChainAcceptsNoUserTxs) {
t.Errorf("AdmitUserTx(%d) = %v, want ErrChainAcceptsNoUserTxs", paid, err)
}
}
}
// A VM that never ran Initialize holds the zero Fee, and the zero Fee admits
// nothing. That is the direction the default must fail in: a chain that forgot
// to declare a policy refuses every caller rather than admitting every caller.
func TestAnUndeclaredPolicyRefusesEveryone(t *testing.T) {
var vm VM
if err := vm.AdmitUserTx(0); !errors.Is(err, fee.ErrChainAcceptsNoUserTxs) {
t.Fatalf("the zero Fee admitted a caller: %v", err)
}
if vm.Fee() != nil {
t.Fatalf("the zero Fee reports a policy: %v", vm.Fee())
}
}