build(deps-dev): bump postcss from 8.5.6 to 8.5.10 in /docs in the npm_and_yarn group across 1 directory#134
Closed
dependabot[bot] wants to merge 270 commits into
Closed
Conversation
added 30 commits
May 6, 2026 15:32
Introduces ZWingDialer + ZWingListener which wrap any underlying
net.Conn (TCP, hostname, RNS mesh link, Unix socket, in-memory pipe)
with the canonical Lux PQ secure channel:
IETF X-Wing KEM (X25519 + ML-KEM-768)
Hybrid Ed25519 + ML-DSA-65 identity, signed transcript
ChaCha20-Poly1305 with sequence-numbered nonces
Z-Wing's contract is "any net.Conn" — the same secure channel rides
unchanged on TCP today and on the existing RNS transport tomorrow
without a per-transport rewrite. The legacy LP-9701 in-RNS-link crypto
(rns_link.go) stays in place during the transition; new p2p paths
should layer ZWingDialer over the EndpointDialer instead of relying on
LP-9701's inline encryption.
Adds:
network/dialer/zwing_dialer.go ZWingDialer + ZWingListener
network/dialer/zwing_dialer_test.go 5 e2e tests covering:
- missing-identity rejection (dialer + listener)
- real TCP listener + Z-Wing handshake + payload round trip
- Wrap() over an arbitrary net.Conn (net.Pipe stand-in for RNS)
- identity mismatch (MitM defence)
- DialEndpoint over an Endpoint (works for IP, hostname, future RNS)
Bumps:
github.com/luxfi/zwing v0.5.2 (full FIPS 204 PQ stack, cross-language
wire-byte interop with Rust/Py/TS)
github.com/luxfi/api v1.0.10 (NewListener seam used by zwing.ListenZAP)
luxd-side wiring (node.go construction with a loaded LocalIdentity) is
the next follow-up; this commit lands the seam without behavioural
changes to the existing dialer interface.
Pulls in:
* luxfi/constants v1.5.2 — LocalID/CustomID semantic split, IsCustom()
* luxfi/genesis v1.9.2 — same split mirrored at the configs layer
* luxfi/zwing v0.5.2 — full PQ secure channel (X-Wing + ML-DSA-65 +
ChaCha20-Poly1305) with cross-language
wire-byte interop verified against Rust /
Python / TypeScript ports
* luxfi/api v1.0.10 — zap.NewListener seam (used by zwing.ListenZAP)
* luxfi/netrunner v1.18.1 — PQ-mandatory zapwire control RPC + same
LocalID rename
* luxfi/geth v1.16.87 — verkle.Fr type fix (drop bandersnatch import)
* luxfi/consensus v1.23.1 — banderwagon path move tracked
Source-side rename in this repo: every constants.CustomID call was
"the local 1337 dev network", so they all become constants.LocalID
(both the upgrade-config validation switch and the test fixtures).
The old constants.CustomID literal is now 0 — used as the explicit
"this is a user-defined custom network" sentinel, separate from the
LocalID dev network.
Plus a clarifying comment on the upgrade-config switch noting which
network IDs are permitted to override their upgrade schedule (any
non-well-known ID, including DevnetID/UnitTestID and any genuinely
custom user-defined network ID).
Z-Wing dialer + tests still green; all network/dialer, config,
config/node, config/spec, and genesis/builder tests pass.
* consensus v1.23.2 — pulls threshold v1.6.7 with the LSS-Pulsar
adapter (PulsarConfig, DynamicResharePulsar) needed by the epoch
manager's resharing path.
* New proto/zap/rpcdb package — pure-Go wire types for the database
RPC, no protobuf. Mirrors the proto/zap/{vm,p2p,sync,platformvm}
pattern.
* New proto/rpcdb/rpcdb_zap.go (build tag !grpc) — full ZAP-native
DatabaseClient + DatabaseServer + Register hook, implements
database.Database against any Transport. The host's underlying DB
is luxfi/database (zapdb in production); the protocol shape is
identical regardless of which engine the host runs.
* Renamed the existing rpcdb.go to rpcdb_grpc.go so the two
variants are mutually exclusive: build with no tag (ZAP default)
or with `-tags=grpc` (protobuf path), never both.
examples/multi-network/multi-network-poc.go: drop duplicate-key map
entry where Q-Chain was illustrated as a separate network — Q-Chain
shares the primary network ID per LP-134, see comments on
MainnetID entry.
Net effect: full default build is ZAP-only PQ-secure-channel-aware,
RPC over a Z-Wing-encrypted ZAP transport, no gRPC/protobuf in the
critical path.
Two compatibility seams that downstream consumers need post-Z-Wing restructure: 1. proto/pb/* stubs (build tag grpc) — every grpc-tagged file under proto/<name>/<name>_grpc.go (and the legacy proto/rpcdb/rpcdb_grpc.go) imports proto/pb/<name>. Those dirs were empty (git ignores empty dirs), so consumers' `go mod tidy` walked the imports under the grpc tag and failed to resolve the package. Default builds use ZAP and never enter these stubs; the grpc-tag path now compiles cleanly even though the protobuf types themselves still need regeneration when someone actually wants the gRPC transport. 2. vms/dexvm/dexvm.go — re-export shim for the canonical chains/dexvm package. The DEX VM moved out of node/vms/dexvm into github.com/luxfi/chains/dexvm; existing callers (~/work/liquidity/ node, etc.) keep building unchanged. Default build clean; grpc-tagged build also resolves. No on-the-wire behaviour change in the ZAP default path.
* vms/components/lux: restore the X-Chain UTXO type tree from v1.24.29. External consumers (~/work/liquidity/network-bootstrap, PlatformVM tx builders, AVM tx builders) import this exact type tree to interop with the X→P export path. Documented in CLAUDE.md as a known anomaly pending #58 consolidation; until that lands the package must be present. * vms/thresholdvm/thresholdvm.go: re-export shim mirroring vms/dexvm. The Threshold (FHE / MPC) VM moved out of node/vms/thresholdvm into github.com/luxfi/chains/thresholdvm. Callers (liquidity/fhe plugin etc) keep building unchanged. No on-the-wire behaviour change.
Anchor /lux + /luxd binary patterns at repo root so the gitignore rule doesn't accidentally match every directory called "lux" deep in the tree (which was excluding vms/components/lux that the previous commit tried to land). Add the actual UTXO type tree files so v1.26.5 ships with the package contents external consumers (liquidity/network-bootstrap etc) need.
X-Chain genesis at builder.go:603-613 references 9 FxIDs (secp256k1fx, nftfx, propertyfx, mldsafx, slhdsafx, ed25519fx, secp256r1fx, schnorrfx, bls12381fx) but chains/manager.go only registered the first 3. Chain init failed with "fx qC5JEjDhfXD66cGuhtiL3Lkka2SgZyht74nHVQFmYFyDiLqXe not found" — that ID encodes 'mldsafx' which the genesis builder added when post-quantum support landed but wasn't paired with a manager-side registration. Add all 6 missing factories so any FxID emitted by the genesis builder loads at chain create time. The fxs map is now structurally identical to the X-Chain FxIDs slice — drift between the two will become a review-time diff in chains/manager.go vs. genesis/builder/builder.go.
The field has always semantically been the X-Chain asset ID — the JSON tag is already `xAssetID`. The Go name `LuxAssetID` was a holdover from when "LUX" was the only asset name on the chain, which created confusion when readers expected `XAssetID` to mirror `XChainID` / `CChainID` / `DChainID` (all of which already used the chain-letter naming). Renamed across config, node, vms/platformvm, vms/rpcchainvm/zap and the static_service API request types. JSON tag and protobuf wire fields are unchanged, so on-disk configs and inter-process plugin RPC are backwards-compatible — only Go callers see the new name.
The struct `zapwire.InitializeRequest.LuxAssetID` is generated from a .proto in luxfi/api — renaming it requires regenerating the wire bindings, bumping luxfi/api, then bumping luxfi/node to that. Out of scope for this rename pass; revert the one Go-side assignment so the build resolves against the existing wire type. The local variable already reads from `Context().XAssetID` so the data path is consistent; only the on-the-wire field name lags.
Picks up the localnet genesis regen from LIGHT_MNEMONIC. lux/node's default genesis for network-id=1337 now funds the same 100 P/X wallets the lux/node + liquidityio/node toolchains derive against, so local dev no longer has to set --genesis-file or hand-edit allocations.
Match the OPT-IN comment at genesis/builder/builder.go:617. The initChainManager path was hard-erroring when the platform genesis had no constants.EVMID chain — that contradicted the documented opt-in behaviour and forced consumers (Liquidity Network) to bake a placeholder EVM into the primary genesis just to satisfy the node init. With this change, networks that register their own EVM as a dedicated chain via platform.createChainTx (the canonical L2-on-Lux or sovereign-chain flow) leave the platform genesis EVM-less and cChainID stays ids.Empty. Chain manager + aliasing already accept the empty ID — no further changes needed.
…_CCHAIN_GENESIS_PATH The automine path embeds the C-Chain genesis bytes into the primary- network genesis at boot. Until now that genesis was a hardcoded constant (chainId 31337) — fine for stock lqd local dev, but downstream networks (Liquidity at chainId 8675312, etc.) had no way to override without patching the binary. The chain-config-dir scan happens AFTER the EVM plugin has already initialised from the embedded bytes, so dropping a genesis.json into configs/chains/C/ is silently ignored. Adds LUX_AUTOMINE_CCHAIN_GENESIS_PATH: when set, lqd reads the JSON at that path and embeds it as the C-Chain genesis. Unset → unchanged behaviour (chainId 31337 default). The saved AutomineNetworkConfig also mirrors the resolved value so the on-disk record is true to what was embedded.
Picks up luxfi/genesis@2b16f454 — adds operator-overridable C-Chain genesis at the embedded-loader layer. Pairs with d0a248f (this repo's LUX_AUTOMINE_CCHAIN_GENESIS_PATH for the automine single-node path). With both env vars wired, downstream networks can reuse stock lqd without forking configs/network/cchain.json or patching this binary.
The wire protocol uses two flags on responses: MsgResponseFlag (0x80) — set on EVERY response (success or error) MsgErrorFlag (0x40) — set ONLY on error responses The transport's readLoop already converts MsgErrorFlag responses into a non-nil err out of Conn.Call, so by the time the client checks respType the response is guaranteed successful. Treating MsgResponseFlag as the "is this an error?" predicate fired on every successful Initialize and rendered the binary InitializeResponse payload (LastAcceptedID, parent, height, bytes, timestamp) as if it were an error string, producing "vm error: <unprintable bytes>" and crashing chain creation despite the plugin reporting "VM initialized successfully". Symptom in the field: lqd repeatedly logged failed to create chain on net 11111111111111111111111111111111LpoYY: failed to initialize VM: zap initialize: vm error: \x00\x00\x00 ... while the plugin's own log read "ZAP VM initialized successfully" and "Chain initialized successfully". Health check C reported permanent failure, eth_getBalance returned 404, no blocks were ever produced. Fix: drop the spurious MsgResponseFlag check and strip both flags before comparing the message type so that any well-formed response is accepted. Regression test in client_initialize_test.go pins both halves of the contract: a success response is decoded (lastAcceptedID round-trips), and a server-side error is surfaced through err with the original message intact.
createCChainIfNeeded is the one-time recovery path for the historical mainnet migration where post-merge geth state was imported under a fixed blockchainID (no CreateChainTx). On every other launch the function either silently no-ops on the missing data dir or — worse — risks touching the filesystem before the data dir exists during a fresh genesis. Gating it behind LUX_MIGRATE_CCHAIN=1 keeps the migration path exactly where it belongs: opt-in, run once, never again.
Adds platform.getChains alongside platform.getNets — same wire shape
(IDs in, list of {ID, ControlKeys, Threshold} out), names that match
the user-facing concept ("chain") instead of the internal "net" /
"subnet" jargon. APIChain replaces APINet, ClientChain (alias for
ClientNet) keeps drop-in source compatibility.
Why now: GetNets was already marked deprecated via the "deprecated
API called" log line, but no canonical replacement existed — callers
had to keep calling the deprecated method. This commit lands the
replacement so the bootstrap binary's chain idempotency check
(EnsureChainNetwork → list chains, match owner set) can target the
canonical name.
GetNets stays available indefinitely for wire-protocol compatibility.
GetChains delegates to GetNets internally so the two methods can
never diverge — bug-fix one, both fix.
Test pinned in service_test.go alongside GetNets test (existing file
has //go:build skip but the test is documentation for the contract).
Two related fixes that make chain tracking explicit per-validator:
1. config/config.go: drop the silent default
`if TrackedChains == nil { TrackAllChains = true }`. That made any
node without an explicit --track-chains list try to spin up every
chain in P-chain state, including ones whose VM plugin wasn't
loaded. The setting was a footgun. Empty TrackedChains now means
"track only P/X (built-in)". TrackAllChains stays as an explicit
opt-in escape hatch.
2. chains/manager.go: when buildChain returns ErrNotFound (VM plugin
not registered for this chain's vmID), treat it as the validator's
"I don't validate this one" signal — log info, mark the slot
bootstrapped, and return WITHOUT registering a per-chain failing
health check. The chain stays in pending state for hot-load.
Previously this registered a permanent 503 on /ext/health for the
chain-alias, which made kubelet liveness probes kill any pod that
didn't ship plugins for every chain in the primary genesis. Now
validators participate per-plugin: load liquid-evm/dex/fhe → those
chains validate; don't load Lux's upstream EVM plugin → C-Chain
stays in pending without crashing the node.
Real failures (e.g. genesis decode error, db corruption) still register
the failing health check — those are operator misconfigurations, not
deliberate opt-outs.
Future: a Lux-signed featured-chains.json + --track-featured (default
true) would make this opt-in safer at scale — limits the DDoS surface
of unbounded chain creation while still letting validators earn yield
on the curated set out of the box.
…lt-in Only P-Chain (chain manager startup) and X-Chain (UTXO infra) are required primary-network chains. C-Chain (EVM), D-Chain (DEX), B-Chain (Bridge), T-Chain (Threshold) — and any subnet blockchain — must be explicitly tracked via --track-chains. A validator gets exactly the topology its operator asks for, nothing more. Pre-fix: every primary-network blockchain in genesis was created unconditionally because `constants.PrimaryNetworkID != tx.ChainID` short-circuited the TrackedChains gate. Liquidity validators (no C-Chain plugin shipped) ran into "failed to initialize VM: parsing genesis: unexpected end of JSON input" on every health check. Replace the primary-network bypass with a per-VM check: only tx.VMID == constants.XVMID skips the gate. Everything else (including C-Chain on primary network) goes through TrackedChains.
Replaces classical X25519/ECDH peer handshake with ML-KEM-768 (default) and ML-KEM-1024 (high-value validator/DKG channels). Node identity is signed with ML-DSA-65 over a TupleHash256-bound transcript. cSHAKE256 derives the AEAD session key with customization "LUX_NODE_AEAD_V1", binding profile_id, chain_id, both nodes' ML-DSA public keys, and the shared KEM secret. DKG channels in pulsar/pulsar-m force ML-KEM-1024. Strict-PQ profile refuses peers offering X25519Unsafe KEM. Patch-bump.
NodeIDScheme enum (MLDSA65=0x42 canonical, Secp256k1=0x90 classical-
compat-unsafe only). NodeID derivation now domain-separated via
SHAKE256-384("LUX_NODE_ID_V1" || chain_id || scheme || pubkey).
Wire encoding includes a leading scheme byte so the receiver can
verify without trusting the profile alone.
Strict-PQ profile rejects secp256k1 NodeIDs.
Classical-compat profile accepts both (transition path).
Migration: hardfork activation switches strict-PQ chains from
mixed-scheme to ML-DSA-only at a configured activation block.
network/peer/scheme_gate.go is the single primitive consumers funnel
inbound NodeIDs through: SchemeGate.Classify(nodeID, scheme, height,
site) returns a TypedNodeID once the chain policy admits the pair.
The ActivationHeight field implements the hardfork transition window;
ClassicalCompatUnsafe mirrors the operator opt-in flag (refused under
strict-PQ regardless, honoured on permissive).
Existing 20-byte ids.NodeID array stays byte-identical for storage /
map keys / codec; the scheme byte travels alongside it on the wire
via ids.TypedNodeID. Consumers of the 20-byte form (peer/upgrader,
proposervm block proposer, platformvm validator registry, mempool
sender) continue to work unchanged at the storage layer; the
SchemeGate boundary is what stamps the scheme byte and runs the
cross-axis check.
Bumps luxfi/ids v1.2.9 -> v1.2.10 (NodeIDScheme, TypedNodeID,
DeriveMLDSA, FullDigest, error surface) and luxfi/consensus
v1.23.2 -> v1.23.3 (ValidatorSchemeID accessor, AcceptsValidatorScheme,
ErrValidatorSchemeMismatch).
Tests:
- TestSchemeGate_NewSchemeGate_RejectsNilProfile
- TestSchemeGate_StrictPQ_AcceptsMatchedScheme
- TestSchemeGate_StrictPQ_PostActivation_RejectsClassical
- TestSchemeGate_StrictPQ_PreActivation_AcceptsBothSchemes
- TestSchemeGate_StrictPQ_PreActivation_RejectsClassicalAfterCutover
- TestSchemeGate_Permissive_AcceptsClassicalUnderUnsafeFlag
- TestSchemeGate_RejectsUnknownSchemeByte
- TestSchemeGate_PinsProfileScheme
- TestSchemeGate_SiteTagIncludedInError
Patch-bump: v1.26.9 -> v1.26.10.
The prior commit referenced luxfi/consensus v1.23.3, but that tag was already in use on the remote. Retagged the new ChainSecurityProfile ValidatorSchemeID work as v1.23.4 and update node's go.mod/go.sum to match. luxfi/ids v1.2.10 is unaffected.
Re-exports the canonical ML-DSA-65 (FIPS 204) UTXO feature extension
from github.com/luxfi/utxo/mldsafx so platformvm and xvm callers depend
on a single import path:
github.com/luxfi/node/vms/mldsafx
One feature extension, one import path. The wire types (Credential,
TransferInput/Output, MintOutput, MintOperation, OutputOwners, Input,
Fx, Factory) and the security-level constants are type aliases against
the upstream package — adding mldsafx as a node-side bridge introduces
zero runtime code.
This is the foundation the P-chain and X-chain mempool admission gates
(vms/txs/auth) and the strict-PQ tx variants build against.
Adds the canonical credential-policy gate that the P-chain and X-chain
mempools use to enforce a strict-PQ ChainSecurityProfile at admission
time. One package, one entry point (EnforceCredentialPolicy), one
error (ErrLegacyCredentialUnderStrictPQ).
- ClassicalCompatRegistry: read-only allow-list interface. Names a
bounded set of legacy operator addresses that may still post
classical secp256k1 credentials on a chain that otherwise pins
RequireTypedTxAuth=true. The chain's governance pathway is the
only writer; the mempool only reads.
- NewStaticClassicalCompatRegistry: frozen registry constructed from
a fixed []ids.ShortID slice. Useful for tests and for genesis-
pinned allow-lists before the governance path is online.
- EnforceCredentialPolicy: idempotent gate, branches on
profile.RequireTypedTxAuth:
false → admit unconditionally (classical-compat profile)
true → walk creds; if any is *secp256k1fx.Credential and the
originator is not in the registry, return
ErrLegacyCredentialUnderStrictPQ.
10 tests cover: nil profile (ErrNilProfile, programmer error), classical
profile admits, strict-PQ admits PQ-only creds, strict-PQ refuses
classical without registry, strict-PQ refuses originator not in
registry, strict-PQ admits allow-listed originator, mixed creds with
one classical refuses, empty creds always admits (syntactic verifier's
job to require ≥1), nil-safe staticRegistry, distinguishes addresses.
Wiring into platformvm/txs/mempool and xvm/txs/mempool lands in the
follow-up commits.
Wires the canonical credential-policy gate (vms/txs/auth) into the P-chain mempool. Adds an opt-in setter so existing callers that have not migrated their construction path observe no behavioural change — without SetAuthPolicy, the gate is bypassed and every tx the legacy path accepted is still accepted. Once a chain pins a non-nil *config.ChainSecurityProfile via SetAuthPolicy, every Add path runs through auth.EnforceCredentialPolicy before the underlying mempool sees the tx. A classical secp256k1fx.Credential under RequireTypedTxAuth=true returns auth.ErrLegacyCredentialUnderStrictPQ. The originator is left at ids.ShortEmpty here because P-chain txs do not bind a single canonical "from" address (the input owners can name many keys). Chain builders that supply a ClassicalCompatRegistry whose IsAllowed depends on tx-level context layer that resolver on top of this gate. Three integration tests cover: strict-PQ + no registry refuses classical, no policy (legacy default) admits classical, classical- compat profile admits classical. The full P-chain mempool suite (TestBlockBuilderMaxMempoolSizeHandling et al.) is unchanged.
Mirrors the P-chain gate (vms/platformvm/txs/mempool) onto the X-chain (xvm) mempool. The X-chain wraps every credential in fxs.FxCredential, so the gate unwraps the inner verify.Verifiable before handing the slice to auth.EnforceCredentialPolicy — the policy package only sees the canonical *secp256k1fx.Credential type. Same opt-in shape as the P-chain wiring: SetAuthPolicy installs the ChainSecurityProfile + ClassicalCompatRegistry; without a profile the gate is bypassed. Three integration tests cover: strict-PQ + no registry refuses classical, no policy admits classical, strict-PQ + empty registry refuses classical (the all-allow-listed contract is that the registry names the allowed addresses; an empty registry admits nothing).
Adds Node.SecurityProfile() getter and Node.initSecurityProfile() boot
step. New() now calls initSecurityProfile() right after
initBootstrappers() and before tracer/metrics/networking/chain init —
every downstream consumer (signer factory, peer handshake gate,
mempool, validator registry, bridge oracle) sees the resolved
*consensus/config.ChainSecurityProfile (or its absence) via the
getter at construction time.
The pin lives in genesis.Config.SecurityProfile (luxfi/genesis@v1.9.6,
which pins luxfi/consensus@v1.23.5). Resolution:
1. genesiscfg.GetConfig(networkID) — load JSON-form genesis
2. cfg.SecurityProfile.Resolve() — refuse mismatched pin
3. stamp result onto n.securityProfile
4. emit startup banner with hash, post-quantum, NIST-friendly,
classical-SNARK, and BLS-fallback posture
A forked binary that swaps in a different canonical profile content
fails Resolve() because the live ComputeHash diverges from the
genesis-pinned hex — closes the F102 attack chain end-to-end.
Adds 5 regression tests for the load + reject paths under StrictPQ
and FIPS profiles, plus nil-pin / wrong-hash / unknown-ID rejection.
Bumps luxfi/consensus v1.23.4 → v1.23.5, luxfi/genesis pseudo →
v1.9.6, luxfi/crypto v1.18.3 → v1.18.4.
The reusable hanzoai/.github/docker-build.yml requires cross-org callers
to override runner labels — hanzoai org scale-sets aren't visible from
luxfi org. All v1.26.x CI runs have failed with startup_failure since
the upstream workflow added this requirement (~2026-05).
Per the reusable workflow's docstring:
Cross-org callers (luxfi/*, zooai/*, liquidityio/*) MUST override
these with their own org's ARC scale-set labels.
Switch to lux-build-linux-{amd64,arm64} labels which exist on the
luxfi ARC scale-set.
…ValidatorsList + bench refresh
Phase C — Multi-chain CreateSovereignL1 ChainsList primitive (chains_list.go,
chains_list_test.go):
* 64-byte fixed-stride ChainEntry per chain: (NameRel/Len uint32, VMID 32B,
FxIDsRel/Len uint32, GenesisDataRel/Len uint32, Reserved 8B).
* Three sibling blob arrays (NameBlobs, FxIDsBlobs, GenesisDataBlobs)
carried as parent-tx fields; entry header stores (rel, len) cursors.
* Bind(nameBlobs, fxIDsBlobs, genesisDataBlobs) compile-time gate
mirroring BoundEvidenceList (NEW-V2): ChainsListView lacks safe
Name/FxIDs/GenesisData accessors so consumers cannot bypass Bind() by
accident. Only BoundChainEntry exposes the safe accessors.
* IsNull() zero-value guard on ChainEntry: out-of-range At(i) returns
a ChainEntry{} whose accessors short-circuit to zero rather than
nil-deref the underlying zap.Object's msg. Defense-in-depth atop the
defensive At(i) clamp.
* Per-element FxIDs blob is a length-prefixed byte array; entry count =
FxIDsLen / FxIDSize (32B per ids.ID). Non-multiple lengths clamp to nil.
* CreateSovereignL1Tx grows from a single-chain stub (TxKind 23, batch 4)
to a real multi-chain L1 builder: ChainsList + NameBlobs + FxIDsBlobs +
GenesisDataBlobs fields. Size 193 bytes (was 121).
Phase D — ValidatorsList encoding (validators_list.go,
validators_list_test.go):
* 180-byte fixed-stride ValidatorRecord per initial validator: NodeID 20B
+ Weight uint64 + BLSPubKey 48B + BLSPoP 96B + RegistrationExpiry uint64.
* Uses zap.Object.ListStride from v0.7.2 — per-element clamp against
poisoned wire length fields (R4V9).
* No sibling arrays needed — every field is fixed-size.
* BLSPubKey() and BLSPoP() return COPIED slices (not aliased to parent
buffer) so consumer mutation cannot corrupt subsequent reads.
* IsNull() zero-value guard mirroring ChainEntry.
* ConvertNetworkToL1Tx now carries the real ValidatorsList — the
previous (0, 0) stub is gone. Size still 165 bytes (the validators
list pointer was already provisioned).
* CreateSovereignL1Tx integrates ValidatorsList alongside ChainsList for
the full atomic sovereign-L1 commit shape.
Phase E — Bench refresh:
* M1 Max Parse geomean across 10 measurable tx types post-batch-5:
7.44× at -benchtime=2s -count=3 (medians).
* Restricted to the original 9 tx types from the v0.7.2 baseline:
7.74×, within noise of the 7.71× pre-batch-5 number.
* R4V7 SyntacticVerify lives on the executor Verify() path (not the
wire parser), so the parse benchmarks are structurally unchanged.
* ChainsList + ValidatorsList add new primitives but do not appear in
the legacy comparison fixtures.
Test coverage:
* chains_list_test.go: RoundTrip (3 chains incl. empty FxIDs+empty
GenesisData), EmptyList, OutOfRange, UnboundReturnsRawCursors,
BindMismatchedBlobsClampsSafely, FxIDsNonMultipleClampsToNil.
* validators_list_test.go: RoundTrip (2 validators), EmptyList,
OutOfRange, PoisonedLengthClampedByStride,
BLSFieldsAreReadOnly (mutation isolation),
CreateSovereignL1Integration (ChainsList + ValidatorsList together).
* batch4_tx_test.go: updated CreateSovereignL1TxRoundTrip for the new
multi-chain + validators shape; tests both round-trip and Wrap()
re-parse correctness.
All zap_native tests pass under go test -race.
Coordinates with cryptographer #114 v3 work and CTO bootstrap-chain work;
neither genesis/ nor bootstrap touched.
LP-023 batch 5 Phase C+D+E.
…ActivationUnix=0 (always-on) ZAP wire is now mandatory from genesis. The forward-dated 2026-07-01 (1782604800) cutover is dead — replaced with always-on semantics. New deployments, fresh syncs, and all production binaries from v1.28.19 onward are ZAP-only by construction. The legacy linearcodec is reachable only via the explicit dev knob LUXD_ENABLE_LEGACY_CODEC=1, and only for the read path (decoding pre-2026-06-02 archival linearcodec bytes from disk). On the write path, LegacyEnabled has no semantic effect once activation = 0 — the "pre-activation" window is empty, so every block timestamp satisfies blockTimestamp >= 0 and writes are always ZAP. Tests: - TestZAPActivationUnixIsAlwaysOn pins the constant to 0 so any regression that re-introduces a forward-date guard fails this gate. - TestShouldUseZAPForWrite legacy-enabled subtest asserts ZAP for every timestamp (replaces the previous pre/at/post-activation table that depended on a non-zero gate). - TestRed_V15_PreActivationZAPTxRejection updated to reflect that V15's threat model (legacy cutover-window fork) is no longer applicable; the test now asserts the always-on invariant. Authorized by 2026-06-02 destructive recovery sweep — "just do it right; no half-measures, no legacy compatibility, clean slate."
…nL1Tx zero-validator/zero-chain CRITICAL) + R6V8 (TransferChainOwnershipTx HIGH) + R6V3 (BLS PoP verification HIGH) + R6V5 (FxIDs malformed length MEDIUM) R6V4 (CRITICAL): CreateSovereignL1Tx.Verify now rejects zero-validator and zero-chain wire buffers (both halt consensus at activation). Per-validator Weight > 0 walk also fires here. RegistrationExpiry remains an executor clock concern (deferred to staking handler, documented). R6V8 (HIGH): TransferChainOwnershipTx had no Verify() despite carrying Owner fields. Wired in: reconstructs OwnerStub from the (threshold, locktime, address) tuple and calls SyntacticVerify. Tx count with SyntacticVerify wired into 8 tx types (was 7). R6V3 (HIGH): BLS PoP now verified at the SyntacticVerify boundary for every initial validator. Wire-layer opaque 48B BLSPubKey + 96B BLSPoP now pairing-checked via bls.VerifyProofOfPossession with new ErrBadBLSPoP. Closes the zero-downstream-consumer gap Red grep found. R6V5 (MEDIUM): ChainsListView.Verify walks entries and rejects any FxIDsLen that is not a multiple of FxIDSize. Replaces the silent-nil return path in BoundChainEntry.FxIDs with a typed error. Wired into CreateSovereignL1Tx.Verify via ChainsListView.Verify(). Tests (all under go test -race): TestCreateSovereignL1Tx_Verify_RejectsZeroValidators TestCreateSovereignL1Tx_Verify_RejectsZeroChains TestCreateSovereignL1Tx_Verify_RejectsZeroWeight TestCreateSovereignL1Tx_Verify_RejectsBadBLSPoP TestCreateSovereignL1Tx_Verify_RejectsBadBLSPoP_MismatchedPubKey TestCreateSovereignL1Tx_Verify_AdversarialWireBuffer_ValidatorWeight TestChainsList_Verify_RejectsBadFxIDsLen (adversarial wire buffer) TestChainsListView_Verify_StandaloneEntries TestTransferChainOwnershipTx_Verify_RejectsZeroThreshold TestTransferChainOwnershipTx_Verify_RejectsThresholdAboveOne TestTransferChainOwnershipTx_Verify_AdversarialWireBuffer TestBLSSurfaceReachable Updates TestVerify_AcceptsWellFormed/CreateSovereignL1 to supply a properly-constructed validator (real BLS PoP) and a chain entry so the new gates fire green on the legitimate path. Adds TestVerify_AcceptsWellFormed/TransferChainOwnership subtest for R6V8. New typed errors: ErrZeroValidators, ErrZeroChains, ErrValidatorWeightZero, ErrBadBLSPoP, ErrMalformedFxIDsLen. Bench unchanged (Verify is on executor path, parse benches structurally untouched). Full zap_native suite green under -race. LP-023 batch 5 v3 closes Red round 6 V3/V4/V5/V8.
…List CI audit gate (R6-6) + cross-blob aliasing documented contract (R6-2 design decision)
R6-4 (RESERVED zero-gate)
- ChainEntry RESERVED bytes [56..64) gated by ChainsListView.Verify.
- New OffsetChainEntry_Reserved=56 constant + ErrReservedNonZero typed err.
- Writer already zero-pads; gate prevents adversary smuggling state inside
what consensus considers empty. Pins the upgrade-safe invariant before
any v4 parser attaches meaning to those bytes (no silent wire-fork).
- Tests: TestChainsList_Verify_RejectsNonZeroReserved (per-byte sweep of
all 8 reserved bytes, each flipped individually -> all reject),
TestChainsList_Verify_RejectsNonZeroReserved_TopByte (top byte 0x01).
R6-6 (AddressList.At CI audit gate)
- .github/workflows/zap-audit.yml: grep-based gate on PR + push to
main/dev. Fails if any new production caller of AddressList.At()
appears outside the allowlist (_test.go, tx_verify.go, owner.go,
audit_test.go).
- vms/platformvm/txs/zap_native/audit_test.go: local mirror so
`go test ./vms/platformvm/txs/zap_native/` reproduces CI behavior.
Verified locally: clean -> PASS; injected violator -> trips correctly.
R6-2 (cross-blob aliasing design decision)
- Documented-allowance path: aliasing is ALLOWED. Wire layer must not
reject overlapping (rel, len) ranges; identity is (VMID, BlockchainID),
not Name() bytes.
- Full CONTRACT block on ChainsListView: (1) Name/FxIDs/GenesisData
return payload slices not identity, (2) chain identity is VMID +
BlockchainID, (3) consumers MUST NOT use returned bytes as dedup keys,
(4) returned slices are read-only.
- Forward path documented: if future feature requires non-overlap, add
ChainsListView.VerifyNonOverlappingRanges() and wire it from tx.Verify.
- Test: TestChainsList_AllowsOverlappingRanges_DocumentedContract -
patches chain[1].NameRel to alias chain[0]'s slice, proves Verify
accepts AND Name(0) == Name(1) byte-equal, AND VMID(0) != VMID(1).
go test -race ./vms/platformvm/txs/zap_native/...: ok 1.4s
Builds on top of v3 commit 15b25a2.
…e (Path A) + R7V7 Verify() for RegisterL1ValidatorTx + ConvertNetworkToL1Tx (HIGH) + R7V8 MustVerify rename + CI gate (MEDIUM)
Red round 7 closes the activation gap so Neo's ZAPActivationUnix=0 image can
land without zombie txs from not-yet-implemented zap_native executors.
R7V5 (HIGH, mempool admission gate — Path A)
- vms/platformvm/network/zap_native_admission.go: new file. Wraps
TxVerifier with NewZapNativeAdmissionGate; refuses
*txs.CreateSovereignL1Tx (legacy struct dispatch hits stub at
standard_tx_executor.go:636) AND any ZAP-magic wire buffer whose
kind is CreateSovereignL1 (23), RegisterL1Validator (7), or
ConvertNetworkToL1 (22).
- vms/platformvm/network/network.go: New() now wraps the supplied
TxVerifier with the gate before installing into gossipMempool, so
every inbound tx routes through the gate first.
- Typed error ErrZapNativeNotYetExecutable for errors.Is matching.
- REMOVAL CHECKLIST documented inline so a future Blue knows to
delete the gate entry when an executor body lands.
- Tests in zap_native_admission_test.go: rejects legacy
CreateSovereignL1Tx; passes through legacy BaseTx /
RegisterL1ValidatorTx / ConvertNetworkToL1Tx (the working ones);
rejects ZAP-wire CreateSovereignL1 / RegisterL1Validator /
ConvertNetworkToL1; non-ZAP bytes pass; nil-safety.
R7V7 (HIGH, Verify() for two missing tx types)
- RegisterL1ValidatorTx.Verify(): BLS PoP pairing + zero-Expiry gate
(ErrZeroExpiry). RemainingBalanceOwnerID treated as optional v3
placeholder.
- ConvertNetworkToL1Tx.Verify(): same per-validator walk as
CreateSovereignL1Tx (non-empty Validators, Weight>0, BLS PoP
pairing).
- Tests in r7v7_register_convert_verify_test.go: rejects bad BLS
PoP / malformed BLS pubkey / zero Expiry / zero Validators / zero
Weight; accepts valid; adversarial wire-buffer tampering for both
tx types (zero out Expiry / Weight in-place and re-Wrap).
R7V8 (MEDIUM, MustVerify rename + CI gate)
- chains_list.go: ChainsListView.Verify renamed to MustVerify so
the per-list gate is grep-able from CI. The previous Verify()
name collided with the tx-level Verify() convention.
- tx_verify.go: CreateSovereignL1Tx.Verify call site updated.
- r6_verify_test.go: TestChainsListView_Verify_StandaloneEntries
renamed + updated to use .MustVerify().
- audit_test.go: new TestAuditGate_ChainsListEmbeddersCallMustVerify
enumerates tx types with a Chains() accessor returning ChainsList
and confirms tx_verify.go has a corresponding Verify() body that
calls .MustVerify().
- .github/workflows/zap-audit.yml: new chainslist-verify-gate job
mirroring the local audit_test.go invariant.
Test results (GOWORK=off, race enabled):
./vms/platformvm/network/... PASS (8 new + all existing)
./vms/platformvm/txs/zap_native/ PASS (8 new + all existing)
./vms/platformvm/txs/executor/ PASS
./vms/platformvm/txs/ PASS
./vms/platformvm/block/... PASS
…rflow ZAPActivationUnix is now 0 (LP-023 cutover, 2026-06-02). The assertion `ShouldUseZAPForWrite(ZAPActivationUnix - 1)` underflows uint64 to math.MaxUint64; with ZAPActivationUnix=0 the LegacyEnabled path degenerates to `ts >= 0` which is true for every input, so the prior "pre-activation picks legacy" assertion can never hold. Rewrite runEnableLegacyChild to mirror zap_native.security_test.V15 closure: probe a timestamp spread including the historical forward-date (1782604800) and assert ShouldUseZAPForWrite=true unconditionally. Pins the always-on invariant on the bench surface too. No production code change.
…t on mainnet Adds an opt-in escape hatch that pins the fee-payment asset to a specific 32-byte asset ID, bypassing platform.getStakingAssetID. Use on networks where the live staking asset differs from the legacy LUX asset on existing P-chain UTXOs. lux-mainnet today is the documented case: staking == pmSJ7BfZQfwtUGbamLWSLFLFGnocfMfbriDTsYWxi4qnqFrrT but the historical deployer's UTXOs hold HrJCm4yvNmyPDA1PEqwks9iFFmoRJEsLJj36N1xtkffrqpL6p. Without the override the wallet's `utxoAssetID` matches the staking-asset result and `platform.getBalance` returns 0 for the legacy UTXOs — the wallet can't find them as fee-payment material. NOTE: this addresses the wallet-side identification only. The P-chain fee-execution rule still requires the staking asset on mainnet; a follow-up legacy-to-staking asset migration tx is needed before CreateNetworkTx + CreateChainTx will go through on mainnet. Tracked as the 2026-06-03 mainnet brand L2 re-fire blocker. Empty / unset is a no-op. Tested via bootstrap-chain mainnet dry-run (2026-06-03): override correctly switches the wallet to legacy-LUX UTXOs; CreateNetworkTx then fails with "insufficient unlocked funds" because the fee verifier checks pmSJ7BfZ... balance — which is the expected second-half blocker.
…+ ChainsList N≤16 cap + ValidatorsList MustVerify (5 floor invariants) + R4V3 re-audit
Blue batch 5 v3.7 closes the 5 target gaps from Red round 5 follow-up:
1. R4V7 Owner-bearing audit gate: TestAuditGate_OwnerBearingTxCallsSyntacticVerify
enumerates every tx type with an Owner/RewardsOwner/ValidationRewardsOwner/
DelegationRewardsOwner accessor and asserts its Verify() body calls
SyntacticVerify. CI mirror: owner-bearing-syntacticverify-gate job
in .github/workflows/zap-audit.yml. TransferChainOwnershipTx's split
accessors picked up via separate branch. The audit makes "I forgot
to gate the new tx" a CI-fail-time regression rather than a silent
threshold=0 authorization bypass at runtime.
2. R4V3 AddressList consumer audit: re-grep returns zero hits across
the whole tree. Documented inline at tx_verify.go header with the
reproducer grep. No regressions since batch 5 v3.5.
3. ChainsList MaxChainsPerL1 = 16: hard cap enforced in
ChainsListView.MustVerify. New ErrTooManyChains typed error.
Matches the multi-chain L1 spawn use case (P + X + EVM + small
application stack) plus headroom; prevents a hostile encoder
from forcing the executor through quadratic walk at admission.
Coverage: TestChainsList_MustVerify_RejectsOverCap +
TestChainsList_MustVerify_AcceptsAtCap.
4. ValidatorsList MustVerify (5 floor invariants):
- Len() <= MaxValidatorsPerL1 (1024): cap matches practical
upper bound on initial-validator sets.
- Weight > 0: lifts the per-validator gate from tx_verify.go
onto the list-level MustVerify so it's grep-able and pure
orchestration on the tx side.
- BLSPubKey not all-zero: structural floor before R6V3 pairing.
- BLSPoP not all-zero: structural floor before R6V3 pairing.
- RegistrationExpiry > 0: parallel of ErrZeroExpiry on
RegisterL1ValidatorTx (unix timestamp can never be zero).
New typed errors: ErrTooManyValidators, ErrValidatorBLSPubKeyZero,
ErrValidatorBLSPoPZero, ErrValidatorRegistrationExpiryZero. Wired
into CreateSovereignL1Tx.Verify and ConvertNetworkToL1Tx.Verify
before the expensive BLS pairing walk so cheap structural floor
fires first. New audit gate (test + CI):
TestAuditGate_ValidatorsListEmbeddersCallMustVerify + workflow
job validatorslist-mustverify-gate. Coverage: 6 new MustVerify
tests (happy path + 5 floor-violation rejections + over-cap).
5. Bench refresh -benchtime=2s (M1 Max):
- Parse geomean (n=9): 7.50× vs v3.6 7.74× — within 4% noise.
- Build geomean (n=9): 1.03× vs v3.6 1.12× — within 9% noise.
- Allocs/op unchanged: Parse 1/24, Build 2 (down from 4-7).
- No regression > 5%. v3.7 changes fire entirely on the Verify()
path; Parse and Build are structurally untouched.
Full numbers in vms/platformvm/txs/bench_results/RESULTS.md.
All 4 audit gates pass locally:
- TestAuditGate_AddressListNoProductionConsumers
- TestAuditGate_ChainsListEmbeddersCallMustVerify
- TestAuditGate_ValidatorsListEmbeddersCallMustVerify (NEW)
- TestAuditGate_OwnerBearingTxCallsSyntacticVerify (NEW)
Full zap_native test suite: 0.715s, all green.
…d) (#132) * Dockerfile: bump EVM plugin v0.18.18 → v0.19.0 (Quasar Edition) Quasar Edition rip — one and only one upgrade-key namespace: - luxfi/evm v0.19.0 renames EtnaTimestamp → QuasarTimestamp (Go field + json tag) - Strict json.Decoder DisallowUnknownFields on upgradeBytes parse in plugin/evm/vm.go — any stale etnaTimestamp in a deployed upgrade.json now fails parse loudly at boot rather than silently leaving the fork field nil and disabling activation. Pairs with: luxfi/genesis kill-etna sweep (configs/*/upgrade.json and brand L1 EVM genesis.json scrubbed). * docker-entrypoint: rip etnaTimestamp from embedded C-Chain genesis With luxfi/evm v0.19.0 strict upgradeBytes decode, the entrypoint's embedded C-Chain genesis heredoc would parse-fail on etnaTimestamp. One name. quasarTimestamp.
…Key() fix)
v0.19.1 bundles luxfi/precompile v0.5.27 → v0.5.35 (commit 794912f).
Each of the 7 EIP-2537 bls12381 sub-configs (G1/G2 × {Add, Mul, MSM} +
Pairing) now returns its own ConfigKey via Key(), fixing a collision
where all 7 mapped to G1AddConfigKey. Without the fix, only one of
the 7 entries could land in the upgrade registry — DisallowUnknownFields
parse (enforced as of evm 415b2a276) rejected the other six.
This unblocks re-adding the 7 bls12381*Config entries to mainnet
configs/mainnet/upgrade.json forward-dated to the already-past Quasar
horizon (Unix 1766708400 = 2025-12-25 16:20 PT). Testnet + devnet
upgrade.json already carry these entries (testnet at 1766708400,
devnet at 0).
…tivated rip) v0.19.2 bumps luxfi/vm v1.1.5 -> v1.1.6 which drops the obsolete GetNetworkUpgrades() method on the VMContext interface. Required by the v0.19.0 Etna->Quasar rename: vm v1.1.5 still expected upgrade.Config to implement runtime.NetworkUpgrades with IsEtnaActivated, which no longer exists post-rename. v1.28.22 and v1.28.23 Docker builds failed on this signature mismatch; v0.19.2 closes the cascade.
v0.19.3 pulls vm v1.1.7 + runtime v1.1.0. runtime v1.1.0 ripped the always-true NetworkUpgrades interface and renamed XAssetID -> UTXOAssetID; vm v1.1.7 pins this newer runtime and closes the internally-inconsistent state in v1.1.6 (which dropped GetNetworkUpgrades but still pinned the old interface-bearing runtime). Builds cleanly now.
Final Ringtail-residue sweep in vms/platformvm/warp:
- HybridBLSRTSignature → HybridBLSCoronaSignature (the lingering "RT"
suffix in the Go type for the deprecated BLS+lattice hybrid).
- ErrInvalidRTSignature → ErrInvalidCoronaSignature.
- ErrMissingRTPublicKey → ErrMissingCoronaPublicKey.
- String() format, comments, doc references updated to Corona.
Wire-format invariants (this is on-chain encoding):
- linearcodec assigns typeIDs by RegisterType call order. The order
in codec.go is UNCHANGED: BitSetSignature (0x00), CoronaSignature
(0x01), EncryptedWarpPayload (0x02), HybridBLSCoronaSignature
(0x03), then the 3 Teleport types (0x04-0x06).
- linearcodec serializes struct fields by declaration order (see
reflectcodec/struct_fielder.go). Field declaration order is
UNCHANGED for every type in this PR.
- Therefore: type names and field names are wire-metadata only;
renaming them produces byte-equal output.
Wire bytes verified byte-equal pre/post rename for every codec-
registered type via the new regression test:
vms/platformvm/warp/wire_baseline_test.go
That test pins the exact hex of every type's encoding (concrete and
through the Signature interface) and is now a permanent guard against
accidental wire-format drift.
Doc sweep (no code dependencies — example/aspirational JSON keys):
- docs/architecture/consensus.mdx: Ringtail Privacy Layer section
rewritten as Corona Threshold Layer, matching the actual
luxfi/corona implementation. The previous text described a ring-
signature scheme that doesn't exist in this codebase.
- docs/architecture/overview.mdx: Q-Chain diagram + cryptographic
primitives table.
- docs/configuration/node-config.mdx + docs/getting-started/running.mdx:
example Q-Chain config keys (ringtail-* → corona-*).
- docker/Dockerfile.multichain: vestigial -tags ringtail build tag
(no Go files actually consume it) renamed to -tags corona.
Verification:
go build ./... exit 0
go vet ./vms/platformvm/warp/... clean
go test ./vms/platformvm/warp/... all packages PASS (warp,
message, payload, zwarp)
Phase 6 of the LP-023 ZAP migration. luxfi/utxo v0.3.5 (commit 559e482)
drops codec.Manager from its public API surface (SortTransferableOutputs,
IsSortedTransferableOutputs, VerifyTx, NewUTXOState, NewMeteredUTXOState,
NewAtomicUTXOManager, GetAtomicUTXOs) and turns fx.Initialize into a
no-op. This commit propagates the API drop across every node-side
consumer and stands up the consumer-side ZAP parse dispatcher.
Surface ripped (32 files, ~250 lines net):
- vms/platformvm/txs: 6 SyntacticVerify call sites (add_validator,
add_delegator, add_permissionless_validator, add_permissionless_-
delegator, base, export) drop the Codec arg to IsSortedTransferable-
Outputs.
- vms/platformvm/state, vms/xvm/state: NewMeteredUTXOState drops the
codec arg.
- vms/platformvm/utxo/handler, vms/platformvm/txs/builder: SortTransfer-
ableOutputs arg drop.
- vms/xvm/txs/executor/syntactic_verifier: 5 lux.VerifyTx call sites
drop v.Codec.
- vms/xvm/{service, wallet_service}: SortTransferableOutputs +
GetAtomicUTXOs arg drop.
- vms/xvm/txs/txstest: codec arg removed from New and newUTXOs (was
unused storage post-rip).
- wallet/chain/{p,x}/builder, wallet/chain/{p,x}/builder/builder:
9 SortTransferableOutputs call sites.
- Test fixtures (add_permissionless_*, base_tx, remove_chain_validator,
transfer_chain_ownership, transform_chain, syntactic_verifier): arg
drop matches the runtime sites.
New: vms/components/lux/utxo_parser.go — the luxd-side ZAP wire
dispatcher. utxo.ParseUTXO is consumer-registered via
utxo.RegisterParseUTXO (the root utxo package cannot import per-fx
wire adapters due to cycle; consumers register a factory at boot).
The dispatcher routes on (wire.TypeKind, wire.ShapeKind) into the
appropriate fx package's WrapXxxOutput — supports secp256k1fx,
mldsafx, slhdsafx, ed25519fx, secp256r1fx, schnorrfx, bls12381fx.
vms/xvm/txs/parser.go: utxo v0.3.5 secp256k1fx.Fx.Initialize is a
no-op (no codec RegisterType chain). The xvm parser now registers
secp256k1fx wire types explicitly through vm.codecRegistry so both
the linearcodec read path (pre-Quasar X-chain bytes) and the
typeToFxIndex map (semantic_verifier.getFx) stay populated.
vms/{xvm,platformvm}/state/state.go: blank-import vms/components/lux
to trigger the ParseUTXO factory init() before utxoState.GetUTXO
deserializes off disk.
Activation: ZAPActivationUnix=0 preserved (always-on, per LP-023).
Legacy V0/V1 codec slot maps retained as READ-ONLY decoders behind
LUXD_ENABLE_LEGACY_CODEC=1 — mainnet/testnet block history continues
to deserialize.
Build/test status:
- go build ./... clean.
- go vet ./... clean (modulo 1 pre-existing sync/atomic copy warning
in vms/rpcchainvm/zap/cevm_e2e_test.go unrelated to this rip).
- xvm txs/executor + xvm state + xvm network + xvm txs + xvm
genesis + wallet/chain/p/builder + wallet/chain/x/builder ALL
PASS under -short.
- vms/platformvm/txs serialization tests (TestAdd*Serialization)
fail on byte-baseline expected outputs because utxo's new sort
key is (AssetID, wireBytes()) vs the old codec-marshal bytes —
the test fixtures need regen under the new canonical sort. Same
story for xvm/state_test.go TestFundingAddresses / TestVerifyFxUsage
using utxo.TestState whose Out type doesn't satisfy
wireSerializable. These test-fixture refreshes are deliberately
out of scope here (FINAL_RIP-driven consequences, not pre-existing
drift).
go.mod: luxfi/utxo v0.3.2 -> v0.3.5, luxfi/api transitive v1.0.11
-> v1.0.12. luxfi/codec v1.1.4 stays direct (network/peer, warp
internal, indexer, keystore et al. still use codec.Manager for
non-UTXO concerns; those packages are out of UTXO-rip scope).
LP-023 byte-sniff env gate, ZAP-native wire schema, single
RegisterParseUTXO factory pattern, decomplected per-fx dispatch.
PR #132 (kill-etna) squash-merge regressed luxfi/ids v1.2.14 -> v1.2.13. v1.2.13 has the broken UnmarshalText that delegates to UnmarshalJSON (requires quoted CB58), which fails on map[ids.ID][]string keys passed unquoted via TextUnmarshaler contract. v1.2.14 (commit 305dbda on ids repo) split the methods cleanly. Without this, v1.28.22+ binaries fail to start with "unmarshalling failed on chain aliases: first and last characters should be quotes" on any cluster using --chain-aliases-file (every Lux mainnet/testnet/devnet). Root cause: the quasar/evm-v0.19.0 branch was created from an older node main that pre-dated the ids v1.2.13 -> v1.2.14 bump. Squash-merge preserved the stale go.mod. Reapplied v1.2.14 explicitly.
genesis: add I/O/R chains to primary network registry
…ed-payload-admit vms/txs/mempool: add AdmissionVerifier hook for encrypted-payload txs (#115)
…rage test(errors): cover Wrap/Multi/Join/Is* and category inference (100%)
…-docs docs: align Go version in README and CONTRIBUTING with go.mod (1.26.3)
Bumps the npm_and_yarn group with 1 update in the /docs directory: [next](https://github.com/vercel/next.js). Updates `next` from 16.1.5 to 16.2.6 - [Release notes](https://github.com/vercel/next.js/releases) - [Changelog](https://github.com/vercel/next.js/blob/canary/release.js) - [Commits](vercel/next.js@v16.1.5...v16.2.6) --- updated-dependencies: - dependency-name: next dependency-version: 16.2.6 dependency-type: direct:production dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <support@github.com>
…nd_yarn-152f59e559 build(deps): bump next from 16.1.5 to 16.2.6 in /docs in the npm_and_yarn group across 1 directory
P-Chain syncGenesis on mainnet/testnet was failing with `UTXO.Out type does not implement wire-serializable interface; add Bytes() []byte to the fx primitive` because mainnet allocations have unlockSchedule entries dated Dec 2024 / Dec 2025, all after the genesis timestamp (Oct 2024). genesis.go wraps such allocs as *stakeable.LockOut, which lacked Bytes(). LockOut.Bytes() now encodes (Locktime, inner.Bytes()) via wire.NewLockedOutput (added in luxfi/utxo v0.3.6, ShapeKind=0x0F). Bumps luxfi/utxo v0.3.5 -> v0.3.6. Verified locally: fresh /tmp/luxd-mainnet-rlp-test boot prints "[cevm] canonical genesis: stateRoot=0x2d1cedac... hash=0x3f4fa2a0..." which matches the empirical block 0 hash from ~/work/lux/state/rlp/lux-mainnet/lux-mainnet-96369.rlp.
Root cause of mainnet/testnet/devnet `platform.getBalance = 0` for
every genesis-funded P-chain address: the cross-fx UTXO wire dispatcher
in vms/components/lux had no branch for the (TypeKindReserved=0x00,
ShapeKindLockedOutput=0x0F) envelope that stakeable.LockOut.Bytes()
produces. Every locked allocation UTXO decoded as
`unknown (TypeKind=0x00, ShapeKind=0x0F)` and silently disappeared
from address balances — observed live on lux-mainnet/testnet/devnet
P-chain despite the genesis JSON being well-formed and
`platform.getCurrentSupply` correctly tallying the sum of allocations
(13.27B LUX).
Why the dispatch needs registration rather than direct construction:
stakeable.LockOut embeds lux.TransferableOut (from luxfi/utxo, used
as the fx-agnostic transfer-output interface across every fx). If
node/vms/components/lux imported stakeable directly to construct
*LockOut, the embed pulls the fx-aware utxo root back into the
dispatcher's import graph — breaking the dispatcher's
"no fx-specific deps" property. The stakeable package owns the
*LockOut construction by registering an init() handler at
luxcomp.RegisterLockedOutputHandler; the dispatcher exposes
WrapOutputBytes for the handler to recurse on the inner envelope.
Surface added:
- vms/components/lux/utxo_parser.go:
- LockedOutputHandler type
- RegisterLockedOutputHandler(h) (init-only, panics on
double-install)
- WrapOutputBytes(b) — discriminator-peek + dispatch, used by the
registered handler for inner-envelope recursion
- wrapOutput now routes (TypeKindReserved, ShapeKindLockedOutput)
through lockedOutputHandler
- vms/platformvm/stakeable/stakeable_lock.go:
- init() registers a handler that wire.WrapLockedOutput → recurse
via luxcomp.WrapOutputBytes → cast inner to lux.TransferableOut →
return *LockOut{Locktime, TransferableOut: inner}
luxfi/utxo bumped to v0.3.7 to pick up the public wire.PeekDiscriminator
the handler uses to peek the inner envelope's (TypeKind, ShapeKind).
Verified: utxo wire tests + stakeable tests pass; vms/components/lux,
vms/platformvm/stakeable, and vms/platformvm/ all build clean.
Bumps the npm_and_yarn group with 1 update in the /docs directory: [postcss](https://github.com/postcss/postcss). Updates `postcss` from 8.5.6 to 8.5.10 - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](postcss/postcss@8.5.6...8.5.10) --- updated-dependencies: - dependency-name: postcss dependency-version: 8.5.10 dependency-type: direct:development dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <support@github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps the npm_and_yarn group with 1 update in the /docs directory: postcss.
Updates
postcssfrom 8.5.6 to 8.5.10Release notes
Sourced from postcss's releases.
Changelog
Sourced from postcss's changelog.
Commits
33b9790Release 8.5.10 version536c79eEscape </style> in CSS output (#2074)afa96b2Update dependencies (#2073)effe88bTypo (#2072)3ee79a2Thread model (#2071)2e0683dCreate incident response docs (#2070)fe88ac2Release 8.5.9 versionc551632Avoid RegExp when we can use simple JS89a6b74Move SECURITY.txt for docs folder to keep GitHub page cleaner6ceb8a4Create SECURITY.mdDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore <dependency name> major versionwill close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)@dependabot ignore <dependency name> minor versionwill close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)@dependabot ignore <dependency name>will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)@dependabot unignore <dependency name>will remove all of the ignore conditions of the specified dependency@dependabot unignore <dependency name> <ignore condition>will remove the ignore condition of the specified dependency and ignore conditionsYou can disable automated security fix PRs for this repo from the Security Alerts page.