Files
chains/aivm/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

75 lines
2.1 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package aivm
import (
"context"
"errors"
"testing"
luxai "github.com/luxfi/ai/pkg/aivm"
"github.com/luxfi/chains/fee"
"github.com/luxfi/database/memdb"
"github.com/luxfi/ids"
"github.com/luxfi/log"
"github.com/luxfi/runtime"
vmcore "github.com/luxfi/vm"
)
func newAIVMForFeeTest(t *testing.T) *VM {
t.Helper()
logger := log.NewNoOpLogger()
rt := &runtime.Runtime{
ChainID: ids.GenerateTestID(),
NetworkID: 96369,
Log: logger,
}
v := &VM{}
if err := v.Initialize(context.Background(), vmcore.Init{
Runtime: rt,
DB: memdb.New(),
ToEngine: make(chan vmcore.Message, 8),
Log: logger,
Genesis: []byte(`{"timestamp":0,"version":1,"message":""}`),
}); err != nil {
t.Fatalf("init aivm: %v", err)
}
return v
}
func TestAIVM_FeePolicy_AttachedAtInit(t *testing.T) {
v := newAIVMForFeeTest(t)
defer v.Shutdown(context.Background())
if v.FeePolicy() == nil {
t.Fatal("FeePolicy() = nil; want non-nil FlatPolicy")
}
if got := v.FeePolicy().MinTxFee(); got != fee.MinTxFeeFloor {
t.Errorf("MinTxFee() = %d, want %d", got, fee.MinTxFeeFloor)
}
if err := fee.Validate(v.FeePolicy()); err != nil {
t.Errorf("fee.Validate = %v, want nil", err)
}
}
func TestAIVM_FeePolicy_RejectsZeroFee(t *testing.T) {
v := newAIVMForFeeTest(t)
defer v.Shutdown(context.Background())
task := &luxai.Task{ID: "t-zero", Fee: 0}
if err := v.SubmitTask(task); !errors.Is(err, fee.ErrInsufficientFee) {
t.Fatalf("SubmitTask(zero-fee) = %v, want ErrInsufficientFee", err)
}
}
func TestAIVM_FeePolicy_AcceptsMinFee(t *testing.T) {
v := newAIVMForFeeTest(t)
defer v.Shutdown(context.Background())
task := &luxai.Task{ID: "t-paid", Fee: fee.MinTxFeeFloor}
// gateUserTask must return nil; downstream core.SubmitTask may fail
// for reasons unrelated to fees (model not registered, etc.) — we
// assert on the fee gate path only.
if err := v.gateUserTask(task); err != nil {
t.Fatalf("gateUserTask(min-fee) = %v, want nil", err)
}
}