Files
zeekay 9e6defb3e5 aivmbridge: native compute-proof precompile (computeattest op) — closes audit G10
verifyComputeProof at 0x0300…0004 selector 0x12000000: decodes a proof-of-inference opening
(crypto/poi wire v1.19.24) and returns (included | freivaldsOK<<1) — Merkle inclusion under the
committed transcript root + Freivalds C==A·B over F_p, native via crypto/poi.CheckOpening. One call
serves both paths (genuine = included&ok, fraud = included&!ok). Gas = base + per-field-op, priced
so a 256-slice ~1M gas and a full layer is unaffordable (forces bounded slices); RequiredGas==Run.
This is what makes a real-model-sized opening verifiable on-chain (Solidity Freivalds is too heavy).
Tests 5/5; full aivmbridge suite green. luxfi/crypto v1.19.22→v1.19.24.
2026-06-23 22:40:01 -07:00

94 lines
3.0 KiB
Go

package aivmbridge
import (
"testing"
"github.com/luxfi/crypto/poi"
)
// buildOpening makes a small proof-of-inference transcript and returns the wire-encoded opening of
// its first matmul. With fabricate=true that matmul's output has one entry flipped (a claimed
// result never produced by A·B).
func buildOpening(fabricate bool) []byte {
s := uint64(0x1234)
rnd := func(rows, cols int) poi.Mat {
d := make([]int64, rows*cols)
for i := range d {
s = s*6364136223846793005 + 1442695040888963407
d[i] = int64((s>>33)%127) - 63
}
return poi.NewMat(rows, cols, d)
}
tr := poi.NewTranscript()
a, b := rnd(4, 16), rnd(16, 8)
if fabricate {
c := poi.ExactMatmul(a, b)
c.Data[3]++ // fabricate one output entry
tr.CommitClaimed(a, b, c)
} else {
tr.Matmul(a, b)
}
tr.Matmul(rnd(2, 4), rnd(4, 3)) // a second matmul so the tree has a real proof path
root := tr.Root()
return poi.EncodeOpening(root, []byte("beacon:precompile"), tr.Open(0))
}
// An honest opening verifies natively: included AND Freivalds-OK → verdict 0b11.
func TestPrecompile_VerifyComputeProof_Honest(t *testing.T) {
ret, rem, err := verifyComputeProof(buildOpening(false), 50_000_000)
if err != nil {
t.Fatalf("verify: %v", err)
}
if ret[31] != resultIncluded|resultFreivaldsOK {
t.Fatalf("honest verdict = %d, want %d (included|ok)", ret[31], resultIncluded|resultFreivaldsOK)
}
if rem >= 50_000_000 {
t.Fatal("gas must be consumed")
}
}
// A fabricated output is caught natively: included but NOT Freivalds-OK → verdict 0b01 (= fraud).
func TestPrecompile_VerifyComputeProof_Fraud(t *testing.T) {
ret, _, err := verifyComputeProof(buildOpening(true), 50_000_000)
if err != nil {
t.Fatalf("verify: %v", err)
}
if ret[31] != resultIncluded {
t.Fatalf("fraud verdict = %d, want %d (included, not ok)", ret[31], resultIncluded)
}
}
// Below the base, the op is out of gas (bounds griefing on a malformed/huge frame).
func TestPrecompile_VerifyComputeProof_OOG(t *testing.T) {
if _, _, err := verifyComputeProof(buildOpening(false), GasVerifyComputeProofBase-1); err == nil {
t.Fatal("must be out of gas below the base")
}
}
// RequiredGas (the EVM's pre-charge) matches what Run actually consumes.
func TestPrecompile_GasAccountingConsistent(t *testing.T) {
in := buildOpening(false)
want := computeProofRequiredGas(in)
if want <= GasVerifyComputeProofBase {
t.Fatal("a real opening must cost more than the base")
}
_, rem, err := verifyComputeProof(in, want)
if err != nil {
t.Fatalf("verify at RequiredGas budget: %v", err)
}
if rem != 0 {
t.Fatalf("Run consumed %d less than RequiredGas estimated (rem=%d) — accounting drift", want-rem, rem)
}
}
// A garbage frame decodes-errs and consumes only the base (no panic, no over-charge).
func TestPrecompile_VerifyComputeProof_Garbage(t *testing.T) {
_, rem, err := verifyComputeProof([]byte{1, 2, 3, 4, 5}, 1_000_000)
if err == nil {
t.Fatal("garbage frame must error")
}
if rem != 1_000_000-GasVerifyComputeProofBase {
t.Fatalf("garbage frame must consume exactly the base, rem=%d", rem)
}
}