One toolchain across the estate. The tree carried 1.26.0, .1, .3, .4 and .5
at once, so which compiler built a binary depended on which repo it came
from.
Co-authored-by: Hanzo Dev <[email protected]>
The id is declared twice — here beside the Factory and in luxfi/constants,
which is the one genesis writes into the CreateChainTx — and nothing made them
agree. If this repo's literal moved, a node would look for a plugin under one
name while genesis named the other, and the chain would never appear: a plugin
that is absent and a plugin nobody asked for look identical to a directory
scan.
The second test records the property that decides how a plugin gets pinned. The
id is an ASCII name padded to 32 bytes, not a digest of the binary, and it must
not become one: genesis references it from a transaction already signed and
already in the chain, so an id derived from the build would change on every
rebuild and stop resolving the chain it created. Identity is stable across
versions by construction.
Which leaves integrity as a separate value. Nothing states which build of dexd
is the right one, and the registry runs whatever sits at the filename. What
CB58 does buy is that a mistyped filename fails its checksum instead of
resolving to nothing.
My previous commit here raised this module's go directive from 1.26.4 to 1.26.5.
That was not intended and not needed: `go mod tidy` writes the local toolchain's
version, and a go directive is the MAXIMUM of the module's own and every
dependency's — so hanzos3/go v1.0.1 and zapdb v1.10.4, both of which had picked
up 1.26.5 the same way, dragged this one up with them.
Both are fixed upstream (v1.0.2 back to 1.26.1, v1.10.6 back to 1.26.4), so this
declares 1.26.4 again, which is what it asked for before I touched it. Still zero
minio; build passes.
The S3 client moves from hanzos3/go-sdk to hanzos3/go, and zapdb comes up to
v1.10.4.
go-sdk pointed at our checksum forks with `replace`. Go ignores `replace` in a
non-main module, so that redirect applied when you built go-sdk and to none of
its consumers — this repo resolved the real minio packages regardless of how the
arrows were drawn. hanzos3/go requires the forks by name, which does travel, and
zapdb v1.10.4 is the release that stops pulling go-sdk back in on every tidy.
go.mod names zero minio modules. build passes.
The dexvm runs as a ZAP plugin, so the Runtime rebuilt on its side had
SharedMemory nil. That silently disabled the autonomous seam drive
(autoDriveSeam requires a non-nil handle), so the D-Chain never imported a
C->D intent, never matched one, and never exported a fill — the far half of
why no swap has ever settled.
vm v1.3.6 dials the node's per-chain atomic server at Initialize and
installs the handle, including Indexed, which enumerateSeamPending needs to
discover intents at all.
Co-authored-by: Hanzo Dev <[email protected]>
api.lux.network is returning 503 right now. The node reports one failing check:
D: failed to create chain on net 1111…LpoYY: failed to initialize VM:
zap decode initialize response: unexpected EOF
bootstrapped: chains not bootstrapped
healthy: false
Everything else — bls, database, diskspace, network, router — is ok. One chain
cannot start, and that alone takes the node unhealthy.
It is a wire-version mismatch, not a bug in either side.
zapwire.InitializeResponse gained a SIXTH field, `Capabilities uint64`, appended
last, in luxfi/api v1.0.16:
api v1.0.4, v1.0.12, v1.0.13, v1.0.15 no Capabilities (5 fields)
api v1.0.16, v1.1.1 Capabilities (6 fields)
luxfi/vm f39ce26 then made the plugin server actually SET it ("the generic ZAP VM
server never set InitializeResponse.Capabilities … handleInitialize now sets
Capabilities").
luxd pins api v1.1.1, so it decodes six fields. This repo — which builds the
D-Chain plugin, via internal/plugin → luxfi/vm/rpc → luxfi/api/zap — pinned
v1.0.15 and writes five. The client reads past the end of the response, and that
is the "unexpected EOF" verbatim.
Bumped to what luxd already runs: api v1.0.15 → v1.1.1, vm v1.2.5 → v1.3.5
(v1.3.5 also carries the NewZAPHandler export luxfi/node's rpcchainvm tests
build against). utils, validators, warp and zap move with them.
go build ./internal/plugin/ OK
go build ./... OK
go test ./... 23 packages ok, 0 failed
⚠️ This does not fix production by itself — the D-Chain plugin has to be REBUILT
from this commit and redeployed before the running node can complete the
handshake.
Co-authored-by: Hanzo Dev <[email protected]>
Panic-driven denial of service in the AWS SDK for Go v2 EventStream decoder:
eventstream -> v1.7.8, service/s3 -> v1.97.3 (minimum patched versions, so the
change carries the fix and nothing else).
Verified against a measured baseline: go build ./... exit 0, and go test ./...
is 22 ok / 0 fail BOTH with and without this change — identical, so any failures are
pre-existing and none is a regression from this commit.
Only go.mod/go.sum staged; other working-tree changes in this repo are left
untouched.
Port the atomic import/export into the native dexvm matcher so the in-luxd
D-Chain PRODUCES and CONSUMES the same primary-network shared-memory objects
the 0x9999 precompile speaks — the owner's chosen model (D matches under its
own consensus; C-Chain 0x9999 settles by consuming a node-local atomic object
D produces; no BLS receipt, no external venue).
- atomic.go: the seam. encodeSeamObject/decodeSeamObject reproduce the
precompile's 69-byte wire (rail|owner|asset|amount|spent) BYTE-FOR-BYTE, and
DeriveIntentID its id derivation — ONE wire across precompile/proxy/native.
executeImport consumes a C->D object (Get under the C chain + shared-memory
Remove) and funds the taker's native D account; executeExport debits the
matched proceeds and writes a D->C object keyed exactly as ImportSettlement
reads it, bound to the per-intent escrow (owner/asset/remaining) so Phase B's
owner/asset/amount + per-taker-cap checks pass. commitSeamAtomic applies the
removes/puts atomically with the block overlay (the platformvm acceptor
pattern). No root change needed: the in-consensus matcher makes the atomic
ops a pure function of the already-rooted txs (unlike the proxy's live venue).
- vm.go: capture init.Runtime -> shared-memory handle + C-Chain id.
- tx.go: TxImport (intentID) / TxExport (intentID|asset|amount|spent), both
authorized by the cross-chain object, not a signature.
- block.go: execute drives the seam in the account-scoped lane; Accept commits
via commitSeamAtomic.
- atomic_seam_e2e_test.go: two-phase e2e over REAL shared memory — Phase A intent
-> native D import + a real crossing under D consensus -> native D export ->
Phase B (the exact 0x9999 ImportSettlement consume) credits once; replay
rejected; over-export beyond the locked principal rejected; conservation holds.
Plus a golden-wire test pinning encodeSeamObject to the SAME cross-repo golden
the precompile pins ImportSettlement against (native == precompile == proxy).
go.sum: re-record re-tagged luxfi/[email protected] (stale hash blocked the build).
go.mod: luxfi/runtime indirect -> direct (atomic.go uses it).
The single place a Lux cross-chain atomic swap is constructed across all
three legs, composed from one shared primitive:
- secret.go — Secret [32]byte, Hashlock() = sha256(secret), constant-time
VerifyPreimage. THE source of the SHA-256 hashlock every leg shares (one
32-byte preimage unlocks BTC, the LP-90A0 swap precompile, and the EVM
LXSwapHTLC.sol); keccak is explicitly excluded.
- bitcoin.go — the fixed P2WSH HTLC script (OP_IF SHA256/EQUALVERIFY/CHECKSIG
// OP_ELSE CLTV/DROP/CHECKSIG), P2WSHAddress, and claim/refund witnesses
signed with real BIP143 segwit-v0 sighash via btcd txscript (no hand-rolled
sighash; low-S RFC6979 sigs).
- evm.go — lock/claim/refund calldata; selectors DERIVED from the canonical
ABI signatures and asserted equal to the precompile's 0x4da2c728 /
0x84cc9dfb / 0x7249fbb6.
Tests (-race) include real txscript.Engine execution proofs: claim spends
with the correct preimage and fails with a wrong one; refund spends at/after
locktime and fails before / with CLTV disabled. btcd pinned v0.24.2 (v0.26.0
split chaincfg/wire/txscript into /v2 modules and breaks the build).
Aligns the dex leaf onto the canonical crypto/consensus go-live tags. dexcore
(permissionless AssetResolver) + dchain (dex_get_* read RPC, pure block.ChainVM)
tests green (GOWORK=off). No source change — dep alignment.
database v1.20.4 fixes prefixdb NewIteratorWithStartAndPrefix synthesizing a
pre-prefix start for a nil-start prefix scan, which returned ZERO rows over a
prefixdb-wrapped store (every plugin VM's chain DB via vm/rpc) when sub-prefix
keys sorted before the target. This stranded the native D-Chain: rebuildBookFromDB
iterates order:<pool> alongside asset:/balance:/locked:/meta: rows, folded an
EMPTY book, and every taker cross produced 0 fills despite durably-committed
asks. With the bump the order book refolds correctly and crosses settle.
The D-Chain (dexvm) is its own chain: trading is its consensus-driven state
transition (matcher-at-Verify in pkg/dchain). There is no off-chain keeper
driving 0x9999 — 0x9999 is only the C<->D settlement adapter. Remove the
keeper and its footprint:
- cmd/dexkeeper/ (the off-chain relayer)
- Dockerfile.dexkeeper
- .github/workflows/docker-dexkeeper.yml + docker.yml reference
- k8s/devnet-keeper/ (never deployed)
- go.mod: drop luxfi/chains dep (was pinned at v1.3.16 ONLY for the keeper;
nothing else in dex imports chains — go mod tidy removes it)
Native dchain VM + matcher build pure-Go (CGO_ENABLED=0) and the full
pkg/dchain suite passes (consensus match->Verify->Accept, conservation,
LUX/LUSD + LUX/LETH venue e2e, ownership red-team).
cmd/dexkeeper watches the C-Chain for IntentSubmitted (Phase-A intent: a maker
swap to 0x9999 with DI01 hookData), submits the ImportTx (consume the staged
C->D atomic object, fund the D order) + the settling RelayOrderTx (clob_submit,
collateral-bound) to the dexvm dex.submitTx RPC, then drives the Phase-B
settlement swap (DS01 hookData) that consumes the D->C proceeds object and emits
DEXFill. The keeper holds NO custody authority: value is locked in shared memory
by C before it acts, and the D->C object pays its recorded owner regardless.
- maker.go: BIP44 m/44'/9000'/0'/0/i maker-key derivation, pinned byte-for-byte
against genesis.LoadBIP44WalletKeysFromMnemonic. Uses the STANDARD EVM address
(keccak256(X||Y)[12:]) everywhere — NOT secp256k1.PrivateKey.EVMAddress(),
which hashes the compressed pubkey and yields a non-standard address.
- calldata.go: Phase-A/B 0x9999 calldata via zap/dexsession, intent-id
derivation mirroring precompile/dex DeriveIntentID, IntentSubmitted + DEXFill
decoders (fail-closed at the boundary).
- venue.go: ZAP maker-liquidity seeding, modeled on cmd/fourpath-live.
- keeper.go: watch loop + import/relay orchestration. Settling relay is sent
UNSIGNED with From = escrow owner (the architecturally-correct build).
- Modes: seed | phase-a | watch. Maker key from LUX_MNEMONIC.
Unit tests (10, all passing) cover the pure logic: maker derivation vs the
genesis authority + a known vector, Phase-A/B calldata byte-identity + DI01/DS01
shape, intent-id determinism/injectivity, and synthetic event decode (+ negative
cases). Builds CGO_ENABLED=0 for linux/amd64 (static ELF).
Known gap (documented stub): getExportedOutput — the D->C export discovery needs
a dexvm settlement-coordinate query (dex.getSettlement) or a C-Chain importable-
UTXO view; neither is exposed today. Phase-A path is fully wired.
bootVenue opened the on-disk chainstate via badgerdb.New; use zapdb.New
(same signature, same on-disk format). Bump luxfi/vm v1.2.3→v1.2.4 to pick
up the matching rpc/zap zapdb harness. Transitive api v1.0.12→v1.0.15,
warp v1.18.6→v1.19.2 (v1.x). go build+vet ./pkg/dchain/ clean.
pkg/dchain: store original outcome under seen:<txID> and return it verbatim on replay so a
deduped clob_place is distinguishable from a genuine reject (was returning StatusRejected →
reverted the EVM tx that re-executes ~5x). BookDepth read accessor. cmd/dvenue = the dial-able
venue D-Chain ZAP listener (badgerdb + vm.Initialize + rpc.Listen + RegisterCLOB + production
sealer) the 0x9010 precompile + dexvm proxy point at; cmd/dclient = native-ZAP e2e driver.
zapdb v1.10.0→v1.10.1 (cloud-free, cgo blocker resolved on the v1 lineage). Tests green.
NEW pkg/zapwire: pure-Go leaf holding the frozen CLOB ZAP frame (Submit=66/Place=65/
Cancel=40/EnsureMarket=32/Ack=24, FillWireSize=17, float64 codec) so the public precompile
imports the wire format without the cgo/GPU engine. SubmitMarketable (IOC taker): removed
time.Now()+atomic.AddUint64 from the consensus path; trade ts derives from block-derived
order ts; fills carry maker+taker identity. zap_server.go docstring demoted authority->
gateway. nocgo: verifyOrdersCPU returns nil for empty. Verified pkg/zapwire 6/6, full ./... green.
AMM unification (one Go entry point, per-platform impls):
- amm_gpu.go (cgo) — BatchEvalConstantProduct dispatcher with
LUX_GPU_DISABLE kill switch + fallback metrics
- amm_gpu_metal.go (cgo && darwin) — Metal driver via lux-dex-amm-metal
- amm_gpu_cuda.go (cgo && linux) — CUDA driver via lux-dex-amm-cuda
- amm_gpu_stub.go (cgo && other) — errAMMGPUUnsupported sentinel
- amm_nogpu.go (!cgo) — pure CPU path
CLOB CUDA wire (the LP-108 missing piece — Backend enum can come back):
- orderbook_cuda_types.go — Go mirrors of DEXOrder (64B), DEXTrade (80B),
DEXPrice; assertDEXABI() in init() panics
on any size/offset drift vs the C header
- orderbook_match_cpu.go — MatchOrderCPU canonical Go oracle
- orderbook_cuda.go (cgo && linux) — gpuMatchOrder via
lux-dex-clob-cuda → libdex_clob_cuda.a →
luxcpp/cuda/kernels/gpu/dex_swap.cu
- orderbook_cuda_stub.go (other) — errCLOBGPUUnsupported sentinel
- orderbook_gpu.go — MatchOrderGPU dispatcher with strict fallback
policy + backend.RecordFallback observability
- orderbook_cuda_parity_test.go — 8 randomized parity subtests using
DEXTrade.EqualFields / DEXOrder.EqualFields
(NOT struct ==) so padding bytes can't
cause false negatives
Padding normalization: _ blank pads renamed to _pad (addressable);
ClearPadding() methods on DEXOrder/DEXTrade; CPU oracle + CUDA host
driver both zero pad bytes for deterministic structural comparison.
Branding: all `Lux*`/`LUX_*` types in the C ABI mirror dropped (DEXOrder,
DEXTrade, DEXPrice, AMMReservePair, DEX_SIDE_BID, etc.).
Temporary replace github.com/luxfi/crypto => ../../lux/crypto pending
publication of crypto with backend.GPUDisabled / RecordFallback /
FallbackReason. Remove the replace once crypto is tagged.
Drop pkg/lx/security_profile.go entirely (local SecurityProfile,
ProfileClassical/StrictPQ constants, ProfileFromPQFlag,
IsPostQuantum). The strict-PQ Mode vocabulary lives in
github.com/luxfi/pq as the single source of truth — warp, dex,
fhe, evm, zap all dispatch through pq.ValidateMode against the
pq.PQEvidencer interface and share pq.ErrClassicalAuthForbidden.
SignedOrderPQ now implements pq.PQEvidencer:
func (o *SignedOrderPQ) HasPQEvidence() bool {
return o != nil && len(o.PubKey) > 0 && len(o.Sig) > 0
}
VerifyOrderForProfile (local enum) → VerifyOrderForMode (pq.Mode):
classical *SignedOrder under pq.ModeStrictPQ refuses with
pq.ErrClassicalAuthForbidden via the canonical gate;
*SignedOrderPQ accepted under any mode (verified with ML-DSA-65).
errors.Is(err, pq.ErrClassicalAuthForbidden) now works across the
EVM, DEX, FHE, Warp, and ZAP refusal sites with a single import.
VerifyOrderPQ, BatchVerifyOrdersPQ, AddressFromMLDSAPubKey
unchanged — only the dispatch surface migrated.
Tests: pq.ModeStrictPQ + pq.Verify closures; same coverage of
happy path, address-mismatch attack, wrong pubkey size, and the
canonical refusal sentinel.
pkg/api/zap_server_test.go calls rpc.Dial which only exists in
luxfi/rpc v1.0.2+. Bump go.mod to track.
pkg/price's CChainSource* tests dial localhost:9650 (mainnet C-Chain)
and report failure when no luxd is running. Add a requireLuxd helper
that t.Skip's the test cleanly when the port is unreachable, so CI
machines without a node don't false-fail.
Net effect: full ./... test surface is green without environment.
- Add missing OrderBook interface implementations
- Fix go vet warnings (unreachable code, redundant newline)
- Add build tags for long-running tests
- Create proper Go and C++ orderbook implementations
- Fix clearinghouse test skipping properly
- Format all Go code with gofmt
- Ensure all packages build successfully
- All tests pass with -short flag
- Update all GitHub Actions workflows to use Go 1.24.5
- Update Dockerfile to use golang:1.24.5-alpine base image
- Maintain go.mod with go 1.24.5 and toolchain go1.24.6
- Fix CI/CD pipeline compatibility issues
- Ensure all workflows use consistent Go version
- Remove luxfi package imports that don't exist
- Clean up go.mod to only include available dependencies
- Remove cmd files with unavailable dependencies
- Fix GitHub Actions workflows