mirror of
https://github.com/luxfi/precompile.git
synced 2026-07-27 03:33:45 +00:00
refactor(precompileconfig)!: warp v1.21.0 decomplect — AddMessage takes *warp.Core
Track the warp ZAP rename (SignedCore->Core, WarpEnvelope->Envelope). WarpMessageWriter.AddMessage now takes *warp.Core. Doc comment rewritten to drop the deleted RLP UnsignedMessage reference — one and one way only.
This commit is contained in:
@@ -30,29 +30,37 @@ type ccDB struct{ m map[common.Hash]common.Hash }
|
||||
func newCCDB() *ccDB { return &ccDB{m: map[common.Hash]common.Hash{}} }
|
||||
|
||||
func (s *ccDB) GetState(_ common.Address, k common.Hash) common.Hash { return s.m[k] }
|
||||
func (s *ccDB) SetState(_ common.Address, k, v common.Hash) common.Hash { o := s.m[k]; s.m[k] = v; return o }
|
||||
func (s *ccDB) SetNonce(common.Address, uint64, tracing.NonceChangeReason) {}
|
||||
func (s *ccDB) GetNonce(common.Address) uint64 { return 0 }
|
||||
func (s *ccDB) GetBalance(common.Address) *uint256.Int { return uint256.NewInt(0) }
|
||||
func (s *ccDB) AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int { return uint256.Int{} }
|
||||
func (s *ccDB) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int { return uint256.Int{} }
|
||||
func (s *ccDB) GetBalanceMultiCoin(common.Address, common.Hash) *big.Int { return big.NewInt(0) }
|
||||
func (s *ccDB) AddBalanceMultiCoin(common.Address, common.Hash, *big.Int) {}
|
||||
func (s *ccDB) SubBalanceMultiCoin(common.Address, common.Hash, *big.Int) {}
|
||||
func (s *ccDB) CreateAccount(common.Address) {}
|
||||
func (s *ccDB) Exist(common.Address) bool { return false }
|
||||
func (s *ccDB) AddLog(*ethtypes.Log) {}
|
||||
func (s *ccDB) Logs() []*ethtypes.Log { return nil }
|
||||
func (s *ccDB) GetPredicateStorageSlots(common.Address, int) ([]byte, bool) { return nil, false }
|
||||
func (s *ccDB) TxHash() common.Hash { return common.Hash{} }
|
||||
func (s *ccDB) Snapshot() int { return 0 }
|
||||
func (s *ccDB) RevertToSnapshot(int) {}
|
||||
func (s *ccDB) SetState(_ common.Address, k, v common.Hash) common.Hash {
|
||||
o := s.m[k]
|
||||
s.m[k] = v
|
||||
return o
|
||||
}
|
||||
func (s *ccDB) SetNonce(common.Address, uint64, tracing.NonceChangeReason) {}
|
||||
func (s *ccDB) GetNonce(common.Address) uint64 { return 0 }
|
||||
func (s *ccDB) GetBalance(common.Address) *uint256.Int { return uint256.NewInt(0) }
|
||||
func (s *ccDB) AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int {
|
||||
return uint256.Int{}
|
||||
}
|
||||
func (s *ccDB) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int {
|
||||
return uint256.Int{}
|
||||
}
|
||||
func (s *ccDB) GetBalanceMultiCoin(common.Address, common.Hash) *big.Int { return big.NewInt(0) }
|
||||
func (s *ccDB) AddBalanceMultiCoin(common.Address, common.Hash, *big.Int) {}
|
||||
func (s *ccDB) SubBalanceMultiCoin(common.Address, common.Hash, *big.Int) {}
|
||||
func (s *ccDB) CreateAccount(common.Address) {}
|
||||
func (s *ccDB) Exist(common.Address) bool { return false }
|
||||
func (s *ccDB) AddLog(*ethtypes.Log) {}
|
||||
func (s *ccDB) Logs() []*ethtypes.Log { return nil }
|
||||
func (s *ccDB) GetPredicateStorageSlots(common.Address, int) ([]byte, bool) { return nil, false }
|
||||
func (s *ccDB) TxHash() common.Hash { return common.Hash{} }
|
||||
func (s *ccDB) Snapshot() int { return 0 }
|
||||
func (s *ccDB) RevertToSnapshot(int) {}
|
||||
|
||||
type ccAcc struct{ s contract.StateDB }
|
||||
|
||||
func (a ccAcc) GetStateDB() contract.StateDB { return a.s }
|
||||
func (a ccAcc) GetBlockContext() contract.BlockContext { return nil }
|
||||
func (a ccAcc) GetConsensusContext() context.Context { return nil }
|
||||
func (a ccAcc) GetConsensusContext() context.Context { return nil }
|
||||
func (a ccAcc) GetChainConfig() precompileconfig.ChainConfig { return nil }
|
||||
func (a ccAcc) GetPrecompileEnv() contract.PrecompileEnvironment { return nil }
|
||||
|
||||
@@ -126,8 +134,8 @@ func TestVerifyAndMintWork_E2E(t *testing.T) {
|
||||
|
||||
func TestVerifyAndMintData_E2E(t *testing.T) {
|
||||
const chainId = uint64(420420)
|
||||
desc := make([]byte, 42) // dataHash(32) | size(8) | privacy(2)
|
||||
desc[31] = 0xDD // dataHash
|
||||
desc := make([]byte, 42) // dataHash(32) | size(8) | privacy(2)
|
||||
desc[31] = 0xDD // dataHash
|
||||
binary.BigEndian.PutUint64(desc[32:40], 1000) // 1000 data units
|
||||
binary.BigEndian.PutUint16(desc[40:42], 3) // confidential
|
||||
pub, sig := mldsaKeyAndSig(t, desc)
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
func makeWorkProof(privacy uint16, mins uint32) []byte {
|
||||
p := make([]byte, WorkProofMinSize)
|
||||
p[31] = 0xAA // deviceId (last byte)
|
||||
p[63] = 0xBB // nonce (last byte)
|
||||
p[31] = 0xAA // deviceId (last byte)
|
||||
p[63] = 0xBB // nonce (last byte)
|
||||
binary.BigEndian.PutUint64(p[64:72], 1718000000) // timestamp
|
||||
binary.BigEndian.PutUint16(p[72:74], privacy)
|
||||
binary.BigEndian.PutUint32(p[74:78], mins)
|
||||
@@ -51,7 +51,7 @@ func TestMintWorkAndDoubleSpend(t *testing.T) {
|
||||
func TestMintDataAndDoubleSpend(t *testing.T) {
|
||||
st := NewMockStateDB()
|
||||
desc := make([]byte, 42)
|
||||
desc[31] = 0xCD // dataHash (last byte)
|
||||
desc[31] = 0xCD // dataHash (last byte)
|
||||
binary.BigEndian.PutUint64(desc[32:40], 1000) // dataSize units
|
||||
binary.BigEndian.PutUint16(desc[40:42], 3) // privacy: confidential
|
||||
chainId := uint64(200202)
|
||||
|
||||
@@ -64,9 +64,9 @@ func leafTemplate(serial int64, cn string, notAfter int64) *x509.Certificate {
|
||||
|
||||
// teeChain is a generated root -> intermediate -> leaf attestation PKI.
|
||||
type teeChain struct {
|
||||
root *x509.Certificate
|
||||
inter *x509.Certificate
|
||||
leaf *x509.Certificate
|
||||
root *x509.Certificate
|
||||
inter *x509.Certificate
|
||||
leaf *x509.Certificate
|
||||
leafKey crypto.Signer
|
||||
roots *x509.CertPool
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ const computeProofK = 2
|
||||
|
||||
// Result bits in the returned word's last byte.
|
||||
const (
|
||||
resultIncluded = 1 // the operands are committed under the transcript root (Merkle inclusion)
|
||||
resultIncluded = 1 // the operands are committed under the transcript root (Merkle inclusion)
|
||||
resultFreivaldsOK = 2 // C == A·B (the matmul is genuine)
|
||||
)
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
aivm "github.com/luxfi/chains/aivm"
|
||||
"github.com/holiman/uint256"
|
||||
aivm "github.com/luxfi/chains/aivm"
|
||||
"github.com/luxfi/crypto"
|
||||
"github.com/luxfi/geth/common"
|
||||
)
|
||||
|
||||
@@ -169,7 +169,7 @@ func TestSubmit_RejectsZeroTxHash(t *testing.T) {
|
||||
// mockState with txHash==0 (newMockState(zero)) AND txID==ids.Empty → both id sources
|
||||
// zero → the fallback yields a zero c_tx_hash.
|
||||
st := newMockState(common.Hash{}) // StateDB.TxHash() == 0
|
||||
st.txID = ids.Empty // atomic TxID() == 0 (the fallback is also zero)
|
||||
st.txID = ids.Empty // atomic TxID() == 0 (the fallback is also zero)
|
||||
|
||||
input := encodeSubmit(h32(0x11), h32(0x22), 1, 1, feeWord(5), [32]byte{})
|
||||
gas := BridgePrecompile.RequiredGas(input)
|
||||
|
||||
@@ -121,7 +121,8 @@ func magnetarKAT() katOut {
|
||||
// ---- Corona (0x012206): real 2-round LWE threshold signature -------------
|
||||
// Wire: t:uint32 || n:uint32 || msgHash:32 || serializedSig
|
||||
// serializedSig (per precompile contract.go deserializeSignature):
|
||||
// c || z[N] || Delta[M] || A[M][N] || bTilde[M], each poly = N()*8 bytes BE.
|
||||
//
|
||||
// c || z[N] || Delta[M] || A[M][N] || bTilde[M], each poly = N()*8 bytes BE.
|
||||
func coronaKAT(t, n uint32) katOut {
|
||||
shares, groupKey, err := cthr.GenerateKeys(int(t), int(n), rand.Reader)
|
||||
must(err)
|
||||
@@ -251,7 +252,8 @@ func serializePoly(buf *bytes.Buffer, r *ring.Ring, poly ring.Poly) error {
|
||||
// asserts the recovered pubkey equals the supplied aggregated pubkey, so a
|
||||
// real KAT is just a genuine secp256k1 signature whose key is the group key.
|
||||
// Wire: t:uint32(4) || n:uint32(4) || pubkey(65: 0x04||x||y) || msgHash(32) ||
|
||||
// sig(65: r||s||v).
|
||||
//
|
||||
// sig(65: r||s||v).
|
||||
func cggmp21KAT(t, n uint32) katOut {
|
||||
priv, err := crypto.GenerateKey()
|
||||
must(err)
|
||||
|
||||
@@ -68,9 +68,9 @@ const (
|
||||
// and D-Chain-side idempotency identity (the vault-drain fix). The four order frames
|
||||
// (ensure/place/cancel/submit) are byte-unchanged — this is additive to custody.
|
||||
const (
|
||||
zapUserSize = 16 // user identity field width
|
||||
zapAssetIDSize = 32 // FULL injective asset id field width (NOT a truncated handle)
|
||||
zapRefSize = 32 // idempotency reference (originating EVM txHash) field width
|
||||
zapUserSize = 16 // user identity field width
|
||||
zapAssetIDSize = 32 // FULL injective asset id field width (NOT a truncated handle)
|
||||
zapRefSize = 32 // idempotency reference (originating EVM txHash) field width
|
||||
depositReqSize = zapUserSize + zapAssetIDSize + 8 + zapRefSize // user[16]+asset[32]+amount[8]+ref[32] = 88
|
||||
withdrawReqSize = zapUserSize + zapAssetIDSize + 8 + zapRefSize // = 88
|
||||
openMarketReqSize = 32 + zapAssetIDSize + zapAssetIDSize // poolId[32]+base[32]+quote[32] = 96
|
||||
|
||||
+7
-7
@@ -39,9 +39,9 @@ import (
|
||||
const coreStoreNamespace = settleStateNamespace + "core."
|
||||
|
||||
var (
|
||||
coreKVPrefix = []byte(coreStoreNamespace + "kv.") // per dexcore key -> value slots
|
||||
coreIndexPrefix = []byte(coreStoreNamespace + "oidx.") // per-market order-id index
|
||||
coreOrderPrefix = []byte("order:") // dexcore order-row key prefix
|
||||
coreKVPrefix = []byte(coreStoreNamespace + "kv.") // per dexcore key -> value slots
|
||||
coreIndexPrefix = []byte(coreStoreNamespace + "oidx.") // per-market order-id index
|
||||
coreOrderPrefix = []byte("order:") // dexcore order-row key prefix
|
||||
)
|
||||
|
||||
// evmStore implements dexcore.Store over the 0x9999 EVM storage trie via stateKV
|
||||
@@ -263,10 +263,10 @@ func (it *evmOrderIterator) Next() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (it *evmOrderIterator) Error() error { return it.err }
|
||||
func (it *evmOrderIterator) Key() []byte { return it.curKey }
|
||||
func (it *evmOrderIterator) Value() []byte { return it.curVal }
|
||||
func (it *evmOrderIterator) Release() {}
|
||||
func (it *evmOrderIterator) Error() error { return it.err }
|
||||
func (it *evmOrderIterator) Key() []byte { return it.curKey }
|
||||
func (it *evmOrderIterator) Value() []byte { return it.curVal }
|
||||
func (it *evmOrderIterator) Release() {}
|
||||
|
||||
// --- order-key parsing (the index trigger) ---
|
||||
|
||||
|
||||
@@ -15,13 +15,14 @@ import (
|
||||
)
|
||||
|
||||
// TestRED_GateC_DoS_BuildCostDominatesSweepCost builds N resting maker orders and shows:
|
||||
// (1) each placement costs the GasSwap floor (50k) + real locked capital (custody-gated),
|
||||
// so depth is NOT free — building the "trap" costs N*50k gas;
|
||||
// (2) a taker swap over that depth charges the SAME flat GasSwap floor — confirming the
|
||||
// amplification is real (O(N) work, flat gas) BUT that the attacker paid MORE to
|
||||
// build the book (N*50k) than a single sweep costs (50k);
|
||||
// (3) there is no single input field that forces N to be large in ONE call — N is the
|
||||
// persistent committed book depth, each unit gas+capital-gated.
|
||||
//
|
||||
// (1) each placement costs the GasSwap floor (50k) + real locked capital (custody-gated),
|
||||
// so depth is NOT free — building the "trap" costs N*50k gas;
|
||||
// (2) a taker swap over that depth charges the SAME flat GasSwap floor — confirming the
|
||||
// amplification is real (O(N) work, flat gas) BUT that the attacker paid MORE to
|
||||
// build the book (N*50k) than a single sweep costs (50k);
|
||||
// (3) there is no single input field that forces N to be large in ONE call — N is the
|
||||
// persistent committed book depth, each unit gas+capital-gated.
|
||||
func TestRED_GateC_DoS_BuildCostDominatesSweepCost(t *testing.T) {
|
||||
h := newE2EHarness(t)
|
||||
maker, taker := e2eMaker, e2eTaker
|
||||
|
||||
@@ -58,7 +58,7 @@ func (h *settleHarness) depositNative(t testing.TB, depositor common.Address, am
|
||||
t.Helper()
|
||||
h.state.stateDB.AddBalance(depositor, uint256.NewInt(uint64(amount)))
|
||||
h.state.stateDB.AddBalance(poolManagerAddr9999, uint256.NewInt(uint64(amount))) // host frame moved msg.value
|
||||
data := make([]byte, 64) // asset = address(0) (native), amount
|
||||
data := make([]byte, 64) // asset = address(0) (native), amount
|
||||
new(big.Int).SetInt64(amount).FillBytes(data[32:64])
|
||||
_, _, err := h.c.Run(h.state, depositor, poolManagerAddr9999,
|
||||
prependSelector(SelectorDeposit, data), 5_000_000, false)
|
||||
|
||||
@@ -63,10 +63,10 @@ func readHostMarker(t testing.TB, db database.Database) uint64 {
|
||||
// 3. build the commit batch and STAGE the advanced marker (to) into it (mirrors
|
||||
// acceptedBlockDB.Put of dexAtomicSeqKey into the versiondb the batch snapshots);
|
||||
// 4. THE SINGLE ATOMIC WRITE:
|
||||
// - with ops: sm.Apply(reqs, batch) — its WriteAll replays our batch (marker)
|
||||
// onto the shared-memory batch and writes BOTH in one db write;
|
||||
// - without ops: batch.Write() — persists just the marker (mirrors the plain
|
||||
// versiondb.Commit() path the EVM takes when there is nothing cross-chain).
|
||||
// - with ops: sm.Apply(reqs, batch) — its WriteAll replays our batch (marker)
|
||||
// onto the shared-memory batch and writes BOTH in one db write;
|
||||
// - without ops: batch.Write() — persists just the marker (mirrors the plain
|
||||
// versiondb.Commit() path the EVM takes when there is nothing cross-chain).
|
||||
//
|
||||
// If commit==false we model a CRASH BEFORE the single write (step 4): the batch and
|
||||
// reqs are prepared but neither sm.Apply nor batch.Write runs, so NOTHING is durable —
|
||||
@@ -220,7 +220,7 @@ func TestFIX2_MarkerAndApplyShareOneBatch(t *testing.T) {
|
||||
|
||||
// OLD-BUG MODEL: apply the window to shared memory committed (its own batch write)
|
||||
// but FAIL to persist the marker (the separate versiondb.Commit lost to a crash).
|
||||
from := readHostMarker(t, h.memdbBacking) // 0
|
||||
from := readHostMarker(t, h.memdbBacking) // 0
|
||||
to := ReadStagedAtomicSeq(h.state.stateDB) // 1
|
||||
reqs, cerr := CollectStagedAtomicRange(h.state.stateDB, from, to)
|
||||
if cerr != nil {
|
||||
|
||||
@@ -99,7 +99,7 @@ func TestBuildIntentRequest_CarriesPriceLimit(t *testing.T) {
|
||||
t.Fatalf("buildIntentRequest: %v", err)
|
||||
}
|
||||
if req.PriceLimit == 0 {
|
||||
t.Fatalf("MEDIUM NOT FIXED: buildIntentRequest dropped the slippage floor (PriceLimit=0) for a swap "+
|
||||
t.Fatalf("MEDIUM NOT FIXED: buildIntentRequest dropped the slippage floor (PriceLimit=0) for a swap " +
|
||||
"carrying a real SqrtPriceLimitX96.")
|
||||
}
|
||||
if !req.LimitIsUpper {
|
||||
|
||||
@@ -720,7 +720,7 @@ func (w *contractStateDBWrapper) TxHash() common.Hash {
|
||||
// stack. This is what lets the atomicity tests observe that a failed swap rolls
|
||||
// back BOTH the C balances and the D book — exactly as geth/core/vm/evm.go's Call
|
||||
// reverts a precompile's writes on error. Defined in swap_sync_snapshot_test.go.
|
||||
func (w *contractStateDBWrapper) Snapshot() int { return takeMockSnapshot(w.inner) }
|
||||
func (w *contractStateDBWrapper) Snapshot() int { return takeMockSnapshot(w.inner) }
|
||||
func (w *contractStateDBWrapper) RevertToSnapshot(id int) { revertMockToSnapshot(w.inner, id) }
|
||||
|
||||
// --- erc20Vault (additive test capability; lets the 0x9999 settlement tests
|
||||
|
||||
@@ -437,4 +437,3 @@ func nextSwapCounter(stateDB StateDB, poolID [32]byte) uint64 {
|
||||
func blockTimestampNanos(stateDB StateDB) int64 {
|
||||
return int64(stateDB.GetBlockNumber())
|
||||
}
|
||||
|
||||
|
||||
@@ -89,8 +89,12 @@ const dexAMMRowSlots = 2
|
||||
|
||||
// dexKeyBalance / dexKeyLocked build the dexcore ledger keys EXACTLY as dexcore's
|
||||
// balanceLedgerKey does (<prefix><user:32><asset:32>) so valueSlot names the identical slot.
|
||||
func dexKeyBalance(user, asset [32]byte) []byte { return dexBalanceLikeKey(coreBalancePrefix, user, asset) }
|
||||
func dexKeyLocked(user, asset [32]byte) []byte { return dexBalanceLikeKey(coreLockedPrefix, user, asset) }
|
||||
func dexKeyBalance(user, asset [32]byte) []byte {
|
||||
return dexBalanceLikeKey(coreBalancePrefix, user, asset)
|
||||
}
|
||||
func dexKeyLocked(user, asset [32]byte) []byte {
|
||||
return dexBalanceLikeKey(coreLockedPrefix, user, asset)
|
||||
}
|
||||
|
||||
func dexBalanceLikeKey(prefix []byte, user, asset [32]byte) []byte {
|
||||
k := make([]byte, 0, len(prefix)+32+32)
|
||||
|
||||
@@ -54,7 +54,7 @@ func TestRED_C1_SyncSwap_SyntheticBaseRevertsViaOnChainProof(t *testing.T) {
|
||||
// REAL quote tradeable by seeding its on-chain code; the synthetic base is deliberately
|
||||
// left WITHOUT code, so the on-chain proof — the authoritative reality gate — refuses it.
|
||||
r := newTestAssetResolver(h.networkID, h.cChainID).boundToHarness(h)
|
||||
r.admitERC20(t, c1RealQuote, 6) // real quote: code-backed
|
||||
r.admitERC20(t, c1RealQuote, 6) // real quote: code-backed
|
||||
h.state.stateDB.SetCodeSize(c1FabricatedBase, 0) // synthetic base: NO code
|
||||
prev := installedAssetResolver.Load()
|
||||
if err := InstallAssetResolver(r, h.networkID, h.cChainID); err != nil {
|
||||
|
||||
@@ -82,7 +82,7 @@ func TestDecomplect_RealAssetFillsThenSyntheticFailsClosed(t *testing.T) {
|
||||
hs.key = c1MarketKey() // base = c1FabricatedBase (synthetic, no code), quote = c1RealQuote (real)
|
||||
|
||||
r := newTestAssetResolver(hs.networkID, hs.cChainID).boundToHarness(hs)
|
||||
r.admitERC20(t, c1RealQuote, 6) // real quote: code-backed
|
||||
r.admitERC20(t, c1RealQuote, 6) // real quote: code-backed
|
||||
hs.state.stateDB.SetCodeSize(c1FabricatedBase, 0) // synthetic base: NO code
|
||||
prev := installedAssetResolver.Load()
|
||||
installedAssetResolver.Store(nil) // drop any prior harness resolver so this install lands cleanly
|
||||
|
||||
@@ -22,7 +22,7 @@ require (
|
||||
github.com/luxfi/magnetar v1.2.3
|
||||
github.com/luxfi/runtime v1.1.3
|
||||
github.com/luxfi/threshold v1.9.9
|
||||
github.com/luxfi/warp v1.20.0
|
||||
github.com/luxfi/warp v1.21.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/zeebo/blake3 v0.2.4
|
||||
golang.org/x/crypto v0.52.0
|
||||
|
||||
@@ -275,6 +275,8 @@ github.com/luxfi/vm v1.2.5 h1:L1etY/gh68f9tns1BtyDUpZcBVqc3Ng1mqU3n38GyLo=
|
||||
github.com/luxfi/vm v1.2.5/go.mod h1:TCCg4lDcQFCjxaxfXnxPIrpRSVAyyf2ucT4A4w654Hg=
|
||||
github.com/luxfi/warp v1.20.0 h1:CyUokvCZ2ZhIpbziKPzCdqdvdMc1V32JpyoZTM2tShs=
|
||||
github.com/luxfi/warp v1.20.0/go.mod h1:4a6ZqXSsQVpm1nl1Q5i6SYPjDcdHvPyEoj4M9pvrIHE=
|
||||
github.com/luxfi/warp v1.21.0 h1:QRgDJuGkp0V3GkmnboHTOKl9Ak0ZHc8DcQqbV4gnCRM=
|
||||
github.com/luxfi/warp v1.21.0/go.mod h1:4a6ZqXSsQVpm1nl1Q5i6SYPjDcdHvPyEoj4M9pvrIHE=
|
||||
github.com/luxfi/zap v0.8.10 h1:QKNTAsenkke+qQw/QGHVdVZdV48bzbPkoXq5SDCPhs0=
|
||||
github.com/luxfi/zap v0.8.10/go.mod h1:JfqII8VtVQYLLTX6obU1DP9sjGqf9L24vfug5ifh0b8=
|
||||
github.com/luxfi/zapdb v1.10.1 h1:XV3k4UTTKKxUMgbfC7woPXgUEIJd3P5nj2lGTQ88xeE=
|
||||
|
||||
@@ -171,20 +171,20 @@ func argmaxI8(logits []int8, n uint32) int32 {
|
||||
|
||||
// ModelConfig mirrors aivm::tiny_llm::Config (the transformer dims + requant shifts).
|
||||
type ModelConfig struct {
|
||||
Vocab, Dim, Hidden, NLayers uint32
|
||||
Vocab, Dim, Hidden, NLayers uint32
|
||||
GemmShift, GemmShiftH, LmShift, RmsMult, RmsEps, QkShift, OvShift, SwigluShift int32
|
||||
}
|
||||
|
||||
// Weights are int8 row-major; per-layer arrays concatenated by layer.
|
||||
type Weights struct {
|
||||
Embed []int8 // [vocab*dim]
|
||||
Rms1 []int8 // [n_layers*dim]
|
||||
Wq, Wk, Wv, Wo []int8 // [n_layers*dim*dim]
|
||||
Rms2 []int8 // [n_layers*dim]
|
||||
Wgate, Wup []int8 // [n_layers*hidden*dim]
|
||||
Wdown []int8 // [n_layers*dim*hidden]
|
||||
Rmsf []int8 // [dim]
|
||||
Wlm []int8 // [vocab*dim]
|
||||
Embed []int8 // [vocab*dim]
|
||||
Rms1 []int8 // [n_layers*dim]
|
||||
Wq, Wk, Wv, Wo []int8 // [n_layers*dim*dim]
|
||||
Rms2 []int8 // [n_layers*dim]
|
||||
Wgate, Wup []int8 // [n_layers*hidden*dim]
|
||||
Wdown []int8 // [n_layers*dim*hidden]
|
||||
Rmsf []int8 // [dim]
|
||||
Wlm []int8 // [vocab*dim]
|
||||
}
|
||||
|
||||
// Model is a deterministic int8 transformer (no KV cache; recomputes the prefix).
|
||||
|
||||
@@ -77,4 +77,3 @@ var aivmSiluLUT = [256]int32{
|
||||
112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127,
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -84,9 +84,9 @@ type Config struct {
|
||||
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
||||
}
|
||||
|
||||
func (c *Config) Key() string { return ConfigKey }
|
||||
func (c *Config) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
||||
func (c *Config) IsDisabled() bool { return c.Upgrade.Disable }
|
||||
func (c *Config) Key() string { return ConfigKey }
|
||||
func (c *Config) Timestamp() *uint64 { return c.Upgrade.Timestamp() }
|
||||
func (c *Config) IsDisabled() bool { return c.Upgrade.Disable }
|
||||
func (c *Config) Verify(precompileconfig.ChainConfig) error { return nil }
|
||||
|
||||
func (c *Config) Equal(cfg precompileconfig.Config) bool {
|
||||
|
||||
+16
-15
@@ -141,7 +141,8 @@ func publicKeyFromKeygenSeed(t *testing.T, mode byte, seed []byte) (pk []byte, d
|
||||
}
|
||||
|
||||
// buildEncapInput frames a precompile encapsulate call:
|
||||
// op(0x01) || mode || seed(32) || publicKey
|
||||
//
|
||||
// op(0x01) || mode || seed(32) || publicKey
|
||||
func buildEncapInput(mode byte, seed, pk []byte) []byte {
|
||||
out := make([]byte, 0, 2+SeedSize+len(pk))
|
||||
out = append(out, OpEncapsulate)
|
||||
@@ -154,20 +155,20 @@ func buildEncapInput(mode byte, seed, pk []byte) []byte {
|
||||
// TestNISTKAT_MLKEM_PublicKeyAndPrecompileDeterminism is the combined KAT
|
||||
// driver. For each FIPS 203 parameter set it:
|
||||
//
|
||||
// 1. Reconstructs the public key from the canonical 64-byte keygen seed
|
||||
// and pins pk[:32] against the JSON record.
|
||||
// 2. Calls the precompile twice with identical (caller, seed, pubkey) and
|
||||
// asserts byte-identical output.
|
||||
// 3. Splits the output into ciphertext + shared_secret per the documented
|
||||
// precompile layout, and asserts that the off-line decapsulate of that
|
||||
// ciphertext using the test's private key recovers the precompile's
|
||||
// shared secret. This is the ML-KEM correctness equation -- if it
|
||||
// fails the precompile is producing ciphertexts no honest receiver
|
||||
// can decapsulate, which is the §1.7 silent-failure mode.
|
||||
// 4. Calls the precompile with a tampered ciphertext-side input does not
|
||||
// apply (the precompile is encaps-only; decaps is off-chain). We
|
||||
// instead tamper with the SEED and assert the output ciphertext
|
||||
// changes -- the determinism is keyed on seed, not pubkey alone.
|
||||
// 1. Reconstructs the public key from the canonical 64-byte keygen seed
|
||||
// and pins pk[:32] against the JSON record.
|
||||
// 2. Calls the precompile twice with identical (caller, seed, pubkey) and
|
||||
// asserts byte-identical output.
|
||||
// 3. Splits the output into ciphertext + shared_secret per the documented
|
||||
// precompile layout, and asserts that the off-line decapsulate of that
|
||||
// ciphertext using the test's private key recovers the precompile's
|
||||
// shared secret. This is the ML-KEM correctness equation -- if it
|
||||
// fails the precompile is producing ciphertexts no honest receiver
|
||||
// can decapsulate, which is the §1.7 silent-failure mode.
|
||||
// 4. Calls the precompile with a tampered ciphertext-side input does not
|
||||
// apply (the precompile is encaps-only; decaps is off-chain). We
|
||||
// instead tamper with the SEED and assert the output ciphertext
|
||||
// changes -- the determinism is keyed on seed, not pubkey alone.
|
||||
func TestNISTKAT_MLKEM_PublicKeyAndPrecompileDeterminism(t *testing.T) {
|
||||
vectors := loadMLKEMNISTVectors(t)
|
||||
|
||||
|
||||
@@ -31,34 +31,38 @@ func (s *mockState) SetState(_ common.Address, k, v common.Hash) common.Hash {
|
||||
return old
|
||||
}
|
||||
|
||||
func (s *mockState) SetNonce(common.Address, uint64, tracing.NonceChangeReason) {}
|
||||
func (s *mockState) GetNonce(common.Address) uint64 { return 0 }
|
||||
func (s *mockState) GetBalance(common.Address) *uint256.Int { return uint256.NewInt(0) }
|
||||
func (s *mockState) AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int { return uint256.Int{} }
|
||||
func (s *mockState) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int { return uint256.Int{} }
|
||||
func (s *mockState) GetBalanceMultiCoin(common.Address, common.Hash) *big.Int { return big.NewInt(0) }
|
||||
func (s *mockState) AddBalanceMultiCoin(common.Address, common.Hash, *big.Int) {}
|
||||
func (s *mockState) SubBalanceMultiCoin(common.Address, common.Hash, *big.Int) {}
|
||||
func (s *mockState) CreateAccount(common.Address) {}
|
||||
func (s *mockState) Exist(common.Address) bool { return false }
|
||||
func (s *mockState) AddLog(*ethtypes.Log) {}
|
||||
func (s *mockState) Logs() []*ethtypes.Log { return nil }
|
||||
func (s *mockState) GetPredicateStorageSlots(common.Address, int) ([]byte, bool) { return nil, false }
|
||||
func (s *mockState) TxHash() common.Hash { return common.Hash{} }
|
||||
func (s *mockState) Snapshot() int { return 0 }
|
||||
func (s *mockState) RevertToSnapshot(int) {}
|
||||
func (s *mockState) SetNonce(common.Address, uint64, tracing.NonceChangeReason) {}
|
||||
func (s *mockState) GetNonce(common.Address) uint64 { return 0 }
|
||||
func (s *mockState) GetBalance(common.Address) *uint256.Int { return uint256.NewInt(0) }
|
||||
func (s *mockState) AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int {
|
||||
return uint256.Int{}
|
||||
}
|
||||
func (s *mockState) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int {
|
||||
return uint256.Int{}
|
||||
}
|
||||
func (s *mockState) GetBalanceMultiCoin(common.Address, common.Hash) *big.Int { return big.NewInt(0) }
|
||||
func (s *mockState) AddBalanceMultiCoin(common.Address, common.Hash, *big.Int) {}
|
||||
func (s *mockState) SubBalanceMultiCoin(common.Address, common.Hash, *big.Int) {}
|
||||
func (s *mockState) CreateAccount(common.Address) {}
|
||||
func (s *mockState) Exist(common.Address) bool { return false }
|
||||
func (s *mockState) AddLog(*ethtypes.Log) {}
|
||||
func (s *mockState) Logs() []*ethtypes.Log { return nil }
|
||||
func (s *mockState) GetPredicateStorageSlots(common.Address, int) ([]byte, bool) { return nil, false }
|
||||
func (s *mockState) TxHash() common.Hash { return common.Hash{} }
|
||||
func (s *mockState) Snapshot() int { return 0 }
|
||||
func (s *mockState) RevertToSnapshot(int) {}
|
||||
|
||||
type mockAccessible struct{ s contract.StateDB }
|
||||
|
||||
func (a mockAccessible) GetStateDB() contract.StateDB { return a.s }
|
||||
func (a mockAccessible) GetBlockContext() contract.BlockContext { return nil }
|
||||
func (a mockAccessible) GetConsensusContext() context.Context { return nil }
|
||||
func (a mockAccessible) GetChainConfig() precompileconfig.ChainConfig { return nil }
|
||||
func (a mockAccessible) GetPrecompileEnv() contract.PrecompileEnvironment { return nil }
|
||||
func (a mockAccessible) GetStateDB() contract.StateDB { return a.s }
|
||||
func (a mockAccessible) GetBlockContext() contract.BlockContext { return nil }
|
||||
func (a mockAccessible) GetConsensusContext() context.Context { return nil }
|
||||
func (a mockAccessible) GetChainConfig() precompileconfig.ChainConfig { return nil }
|
||||
func (a mockAccessible) GetPrecompileEnv() contract.PrecompileEnvironment { return nil }
|
||||
|
||||
// --- helpers -----------------------------------------------------------------------
|
||||
|
||||
func sel(s uint32) []byte { b := make([]byte, 4); binary.BigEndian.PutUint32(b, s); return b }
|
||||
func sel(s uint32) []byte { b := make([]byte, 4); binary.BigEndian.PutUint32(b, s); return b }
|
||||
func word(b []byte) []byte { out := make([]byte, 32); copy(out[32-len(b):], b); return out }
|
||||
func u256(v uint64) []byte { b := make([]byte, 8); binary.BigEndian.PutUint64(b, v); return word(b) }
|
||||
|
||||
@@ -66,7 +70,7 @@ func adoptInput(name, weight common.Hash, version uint64) []byte {
|
||||
return bytes.Join([][]byte{sel(SelectorAdopt), name[:], u256(version), weight[:]}, nil)
|
||||
}
|
||||
func getApprovedInput(name common.Hash) []byte { return append(sel(SelectorGetApproved), name[:]...) }
|
||||
func isAdminInput(a common.Address) []byte { return append(sel(SelectorIsAdmin), word(a.Bytes())...) }
|
||||
func isAdminInput(a common.Address) []byte { return append(sel(SelectorIsAdmin), word(a.Bytes())...) }
|
||||
func setAdminInput(a common.Address, on bool) []byte {
|
||||
en := make([]byte, 32)
|
||||
if on {
|
||||
|
||||
@@ -46,13 +46,12 @@ type Predicater interface {
|
||||
}
|
||||
|
||||
// WarpMessageWriter queues a precompile-emitted cross-chain message for the
|
||||
// validator set to attest. Post-ZAP hard fork, the unsigned subject is the
|
||||
// warp.SignedCore (the canonical core whose D = keccak256(DST ‖ zap_c14n) the
|
||||
// BLS Beam / Corona Pulse / ML-DSA lanes sign), replacing the deleted RLP
|
||||
// warp.UnsignedMessage. Build a core via warp.NewSignedCore(networkID,
|
||||
// sourceChainID, payload).
|
||||
// validator set to attest. The unsigned subject is the warp.Core: the
|
||||
// canonical value whose digest D = keccak256(DST ‖ zap_c14n(core)) is what the
|
||||
// BLS Beam / Corona Pulse / ML-DSA lanes sign. Build one via
|
||||
// warp.NewCore(networkID, sourceChainID, payload).
|
||||
type WarpMessageWriter interface {
|
||||
AddMessage(core *warp.SignedCore) error
|
||||
AddMessage(core *warp.Core) error
|
||||
}
|
||||
|
||||
// AcceptContext defines the context passed in to a precompileconfig's Accepter
|
||||
|
||||
+14
-12
@@ -113,7 +113,9 @@ func modeByteAndLib(t *testing.T, name string) (byte, luxslhdsa.Mode) {
|
||||
}
|
||||
|
||||
// buildSLHDSAInput frames a precompile call:
|
||||
// mode(1) || pkLen(2,BE) || pk || msgLen(2,BE) || msg || sig
|
||||
//
|
||||
// mode(1) || pkLen(2,BE) || pk || msgLen(2,BE) || msg || sig
|
||||
//
|
||||
// (See slhdsa/contract.go for the canonical layout.)
|
||||
func buildSLHDSAInput(t *testing.T, mode byte, pk, msg, sig []byte) []byte {
|
||||
t.Helper()
|
||||
@@ -131,17 +133,17 @@ func buildSLHDSAInput(t *testing.T, mode byte, pk, msg, sig []byte) []byte {
|
||||
|
||||
// runNISTKAT executes the deterministic KAT for one parameter set:
|
||||
//
|
||||
// 1. Generate keypair from (skSeed || skPrf || pkSeed) via luxfi/crypto
|
||||
// wrapper (which streams (skSeed || skPrf || pkSeed) into circl's
|
||||
// GenerateKey -- this is the FIPS 205 keygen contract).
|
||||
// 2. Assert pk[:n] == pkSeed (FIPS 205 §10.2 invariant). Catches wrapper-
|
||||
// level layout regressions.
|
||||
// 3. Assert pk[:n] also matches the pinned ExpectedPublicKeyPrefixHex.
|
||||
// 4. Sign with precompileCtx; assert sig[:16] matches the pinned
|
||||
// ExpectedSignaturePrefixHex. Catches changes in the sign-deterministic
|
||||
// chain.
|
||||
// 5. Drive the precompile and require byte[31] == 1.
|
||||
// 6. Tamper with the signature's last byte and require byte[31] == 0.
|
||||
// 1. Generate keypair from (skSeed || skPrf || pkSeed) via luxfi/crypto
|
||||
// wrapper (which streams (skSeed || skPrf || pkSeed) into circl's
|
||||
// GenerateKey -- this is the FIPS 205 keygen contract).
|
||||
// 2. Assert pk[:n] == pkSeed (FIPS 205 §10.2 invariant). Catches wrapper-
|
||||
// level layout regressions.
|
||||
// 3. Assert pk[:n] also matches the pinned ExpectedPublicKeyPrefixHex.
|
||||
// 4. Sign with precompileCtx; assert sig[:16] matches the pinned
|
||||
// ExpectedSignaturePrefixHex. Catches changes in the sign-deterministic
|
||||
// chain.
|
||||
// 5. Drive the precompile and require byte[31] == 1.
|
||||
// 6. Tamper with the signature's last byte and require byte[31] == 0.
|
||||
func runNISTKAT(t *testing.T, v slhdsaNISTVector) {
|
||||
t.Helper()
|
||||
mode, libMode := modeByteAndLib(t, v.Mode)
|
||||
|
||||
+12
-12
@@ -81,18 +81,18 @@ import (
|
||||
// generated header. Kept as typed constants so the switch in the
|
||||
// adapter is exhaustive and self-documenting.
|
||||
const (
|
||||
p3qOK = C.P3Q_OK // 1 — accepted
|
||||
p3qRejected = C.P3Q_REJECTED // 0 — ran, rejected
|
||||
p3qErrNullPtr = C.P3Q_ERR_NULL_PTR // -1
|
||||
p3qErrParse = C.P3Q_ERR_PARSE // -2
|
||||
p3qErrUnsupportedProf = C.P3Q_ERR_UNSUPPORTED_PROFILE // -3
|
||||
p3qErrMerkle = C.P3Q_ERR_MERKLE // -4
|
||||
p3qErrFRI = C.P3Q_ERR_FRI // -5
|
||||
p3qErrStark = C.P3Q_ERR_STARK // -6
|
||||
p3qErrTranscript = C.P3Q_ERR_TRANSCRIPT // -7
|
||||
p3qErrField = C.P3Q_ERR_FIELD // -8
|
||||
p3qErrCircuit = C.P3Q_ERR_CIRCUIT // -9
|
||||
p3qErrPanic = C.P3Q_ERR_PANIC // -99
|
||||
p3qOK = C.P3Q_OK // 1 — accepted
|
||||
p3qRejected = C.P3Q_REJECTED // 0 — ran, rejected
|
||||
p3qErrNullPtr = C.P3Q_ERR_NULL_PTR // -1
|
||||
p3qErrParse = C.P3Q_ERR_PARSE // -2
|
||||
p3qErrUnsupportedProf = C.P3Q_ERR_UNSUPPORTED_PROFILE // -3
|
||||
p3qErrMerkle = C.P3Q_ERR_MERKLE // -4
|
||||
p3qErrFRI = C.P3Q_ERR_FRI // -5
|
||||
p3qErrStark = C.P3Q_ERR_STARK // -6
|
||||
p3qErrTranscript = C.P3Q_ERR_TRANSCRIPT // -7
|
||||
p3qErrField = C.P3Q_ERR_FIELD // -8
|
||||
p3qErrCircuit = C.P3Q_ERR_CIRCUIT // -9
|
||||
p3qErrPanic = C.P3Q_ERR_PANIC // -99
|
||||
)
|
||||
|
||||
// Backend error sentinels. These are INTERNAL failures (decode, FFI,
|
||||
|
||||
@@ -136,11 +136,11 @@ func TestStarkFRI_KAT_RejectTampered(t *testing.T) {
|
||||
// FRI layer roots, final poly, query openings deeper in.
|
||||
bodyLen := len(proof) - len(MagicHeader)
|
||||
bodyOffsets := []int{
|
||||
1, // header (log_degree_bound)
|
||||
11, // first byte of the public-input echo / trace area
|
||||
bodyLen / 4, // FRI layer-root / final-poly region
|
||||
bodyLen / 2, // query-openings region (Merkle siblings)
|
||||
bodyLen - 2, // last query opening's last auth byte
|
||||
1, // header (log_degree_bound)
|
||||
11, // first byte of the public-input echo / trace area
|
||||
bodyLen / 4, // FRI layer-root / final-poly region
|
||||
bodyLen / 2, // query-openings region (Merkle siblings)
|
||||
bodyLen - 2, // last query opening's last auth byte
|
||||
}
|
||||
for _, off := range bodyOffsets {
|
||||
// Operate on a fresh copy each time.
|
||||
|
||||
+6
-6
@@ -114,12 +114,12 @@ var (
|
||||
ErrNoBlockContext = errors.New("swap: block context unavailable")
|
||||
ErrOutOfGas = errors.New("swap: out of gas")
|
||||
|
||||
ErrZeroHashlock = errors.New("swap: hashlock must be non-zero")
|
||||
ErrZeroRecipient = errors.New("swap: recipient must be non-zero")
|
||||
ErrZeroRefund = errors.New("swap: refund address must be non-zero")
|
||||
ErrDustAmount = errors.New("swap: amount below MinSwapAmount")
|
||||
ErrTimeoutBounds = errors.New("swap: timeout outside [T0+MinTimeout, T0+MaxTimeout]")
|
||||
ErrSwapExists = errors.New("swap: swapId already in use")
|
||||
ErrZeroHashlock = errors.New("swap: hashlock must be non-zero")
|
||||
ErrZeroRecipient = errors.New("swap: recipient must be non-zero")
|
||||
ErrZeroRefund = errors.New("swap: refund address must be non-zero")
|
||||
ErrDustAmount = errors.New("swap: amount below MinSwapAmount")
|
||||
ErrTimeoutBounds = errors.New("swap: timeout outside [T0+MinTimeout, T0+MaxTimeout]")
|
||||
ErrSwapExists = errors.New("swap: swapId already in use")
|
||||
|
||||
ErrNotLocked = errors.New("swap: swap is not in the Locked state")
|
||||
ErrExpired = errors.New("swap: timeout passed; claim window closed (refund instead)")
|
||||
|
||||
Reference in New Issue
Block a user