Commit Graph
597 Commits
Author SHA1 Message Date
zeekayandHanzo Dev 5a2035adb5 Merge feat/lp023-native-tx-codec: FULL codec kill — P-chain/warp/proposervm/components struct-is-wire
The LP-023 native-ZAP migration, complete except xvm (next patch):
- P-Chain: tx + block + state + genesis are the zap buffer (struct=wire, no
  codec, no serialize tags, no versions). Executor fold: CreateNetworkTx/
  ConvertNetworkTx with security.Mode (RestakeParent × own-set Admission/
  Manager) — one definition shared by wire/executor/state; CreateChainTx is
  the sole chain constructor (block-atomic L1 spawn per LP-018).
- warp: registration-order codec (hard-fork footgun) → explicit wkind/mkind/
  pkind discriminator bytes; ChainToL1ConversionID = sha256(Marshal()) same-
  encoder invariant; native wire baselines pinned.
- proposervm block/state/summary, components/{lux,message,keystore,index},
  evm/{predicate,lp176}, example/xsvm: native ZAP; pcodecs consumers reduced
  to xvm only.
- consensus v1.36.1 + node-side view-change plumbing ripped (merged with
  main's parallel rip; main's Nova tombstones kept).
- /ext/ endpoint prefix retired: /v1/ is THE endpoint.
- All codec-era tests restored/converted to struct-is-wire (0 parked); staker
  dispatch-safety guard added.
- Deps: published pins only (consensus v1.36.1, zap v1.2.0, utxo v0.3.7,
  crypto v1.20.0); no local replaces.

Merged-tree gate: go build ./... EXIT 0; go test ./... = 155 ok / 0 FAIL.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 22:36:04 -07:00
zeekayandHanzo Dev b4992860f6 deps: publishable pins — zap v1.2.0, drop local replaces
Node builds + full test sweep green (155 ok / 0 FAIL) against PUBLISHED
modules only: consensus v1.36.1, zap v1.2.0, utxo v0.3.7. The local zap/utxo
replaces are gone; the upstream nftfx/propertyfx wire (utxo e790d39) ships as
v0.3.8 with the xvm struct-is-wire patch, which is the only remaining pcodecs
consumer and lands in the next release.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 22:32:00 -07:00
zeekayandHanzo Dev 0ba5d05bd8 Retire /ext/ endpoint prefix: /v1/ is THE endpoint
Route registration, client URL builders, and log lines all move to /v1/
(wallet primary api, chains/rpc handler_manager+chain_integration, xvm
client+wallet_client, xsvm api client, multi-network example, manager logs).
Zero /ext/ literals remain. One endpoint namespace, no transition alias.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 19:14:51 -07:00
zeekayandHanzo Dev 926ddaafa4 go.mod: replace luxfi/utxo -> local (nftfx/propertyfx wire envelopes)
Consumes the upstream fx-wire addition (utxo commit e790d39: TypeKindNFT/
Property + 6 shapes + NextEnvelope) needed for the xvm struct-is-wire
migration. Local replace like zap; publish as utxo v0.3.8 with the node
release.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 17:55:48 -07:00
zeekayandHanzo Dev eda299d30d node v1.36.2: consensus v1.36.1 finality fix on the known-good v1.36.0 base
v1.36.1 bundled staged-but-runtime-untested ZAP work (api v1.0.15->v1.0.16,
vm v1.2.5->v1.2.7, EVM v1.104.7->v1.104.8, platformvm sole-codec cutover,
rpcchainvm Quasar-export plugin-boundary wiring). That bump breaks VM
initialization on EVERY chain at boot:
  failed to initialize VM: zap decode initialize response: unexpected EOF
— a node<->plugin ZAP handshake mismatch (the plugins were not synced to the
new api/vm ZAP wire). Mainnet would not boot on v1.36.1.

v1.36.2 drops that unfinished ZAP transition and ships ONLY the orthogonal
consensus finality fix (v1.36.1 — close the intermediate-ancestor load-livelock,
RED-SHIP 0 crit/high/med) on the known-good v1.36.0 dependency set (api v1.0.15,
vm v1.2.5, EVM v1.104.7). Boots clean AND carries the finality fix. luxd builds
green (-mod=mod). The ZAP Quasar-export / codec cutover ships separately once the
plugins are synced to the api/vm bump and it is runtime-validated.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 17:45:11 -07:00
zeekayandHanzo Dev 6a766516b1 warp -> native ZAP struct-is-wire: kill the registration-order codec (hard-fork footgun)
All 3 warp codec registries deleted (codec.go, message/codec.go,
payload/codec.go). Every dispatched type now carries an EXPLICIT 1-byte
discriminator at object offset 0 — the invariant is DATA, not registration
order:

  warp wkind:    0x00 BitSetSignature, 0x01 CoronaSignature,
                 0x02 EncryptedWarpPayload, 0x03 HybridBLSCoronaSignature,
                 0x04 TeleportMessage, 0x05 TeleportTransferPayload,
                 0x06 TeleportAttestPayload   (ids = old registration order)
  message mkind: 0 ChainToL1Conversion, 1 RegisterL1Validator,
                 2 L1ValidatorRegistration, 3 L1ValidatorWeight
  payload pkind: 0 Hash, 1 AddressedCall

CONSENSUS-CRITICAL invariant made structural: ChainToL1ConversionID =
sha256(ChainToL1ConversionData.Marshal()) — the ID calls the SAME encoder, so
ID/Marshal skew (the bug in the reverted agent attempt) is impossible. The
native hash preimage is pinned as a golden with field-offset assertions
(verified by the L1 staking contract => consensus surface).

Message = {unsigned bytes, wkind-tagged sig bytes} container object;
UnsignedMessage = {networkID u32, sourceChainID 32B, payload} @44B header.
wire_baseline_test.go rewritten: pins the native hex golden for all 7 wkinds
+ structural discriminator checks + signature dispatch round-trips. Old-codec
sentinels -> zap errors. Whole node builds; warp+platformvm+proposervm green.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 17:44:13 -07:00
zeekayandHanzo Dev 2d227dd3aa Full-codec-kill wave 2: proposervm + xsvm + components + evm + platformvm-residual → native ZAP
Kills pcodecs from 3 complete subsystems (verified go test ./... = 155 ok / 0 FAIL):
- proposervm: block/state/summary struct-is-wire (blockwire.go + statewire.go;
  deleted block/state/summary codec.go). blockKind bytes: reserved=0 signed=1
  option=2. Epoch inlined in unsigned object. proposer/windower chainSource seed
  = binary.LittleEndian (byte-identical to old wrappers.Packer.UnpackLong).
- example/xsvm: tx/block/genesis native Marshal (deleted 3 codec.go); create-chain
  example uses genesis.Marshal().
- components: message.Tx native (deleted codec.go); keystore codec shell removed;
  index pcodecs.LongLen → local const.
- evm/{predicate,lp176}: off pcodecs.
- platformvm residual: state metadata + genesis + metrics + signer + stakeable
  native, vestigial serialize tags removed.

REMAINING (careful solo, agents weekly-capped): warp (reverted — agent left an
ID≠Marshal consensus inconsistency in ChainToL1Conversion; needs proper review,
not a golden-regen) + xvm (reverted — barely started). pcodecs package stays
until those 2 land. /ext/→/v1/ endpoint change also pending.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 17:19:20 -07:00
zeekayandHanzo Dev 7123b7399e Restore+convert remaining txs tests to struct-is-wire + dispatch-safety guard
Converts the per-type P-chain tx tests to native New*Tx + accessor methods +
roundTrip/SyntacticVerify (agents, verified): add_validator, add_chain_validator,
create_blockchain, disable/increase/register/set_weight/remove_chain/
transfer_ownership L1, add_permissionless_delegator, transform_chain. Every
error-path sentinel preserved by driving the bad value THROUGH the constructor
(pure byte-writer). Mock-based cases (fxmock/luxmock/verifymock, impossible on
an immutable zap buffer) reproduced with REAL unspendable owners / unsorted
inputs → real sentinels (ErrOutputUnspendable, ErrInputIndicesNotSortedUnique).
Only the un-reproducible 'already verified' cached-flag case dropped per file.

NEW staker_dispatch_guard_test.go pins the interface-satisfaction invariant the
staker type-switches depend on: struct-is-wire made *AddValidatorTx satisfy both
ValidatorTx+DelegatorTx (safe — ValidatorTx checked first everywhere), but
*AddDelegatorTx must NOT satisfy ValidatorTx (verified: lacks
ValidationRewardsOwner/Shares) or delegators would mis-route. Guard fails loudly
if a future edit breaks either property.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 05:46:10 -07:00
zeekayandHanzo Dev 43cbbac511 Restore+convert genesis/state/network tests to struct-is-wire (4 files, zero coverage dropped)
- genesis: field->method on *txs.AddValidatorTx (.Validator().NodeID/.End/
  .StakeOuts()); 3 error-path builders preserved (errUTXOHasNoValue,
  errValidatorHasZeroWeight, errValidatorAlreadyExited).
- state/staker: generateStakerTx via NewAddPermissionlessValidatorTx; the
  mutable-Signer-mock trick (impossible on immutable zap buffer) ->
  NewMockScheduledStaker.PublicKey()=errCustom, errCustom preserved exactly.
- network/gossip+network: nil-buffer &txs.BaseTx{} -> newBaseTx helper (avoids
  InputIDs() panic); SetBytes 2-arg->1-arg; all expectedErr preserved
  (ErrDuplicateTx, ErrTxTooLarge, ErrConflictsWithOtherTx, ErrMempoolFull...).
go test ./genesis/ ./state/ ./network/ = all ok.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 05:45:21 -07:00
zeekayandHanzo Dev 7ea0c0383f Restore+convert fee/mempool/txheap tests to struct-is-wire (6 files, green)
- fee/complexity: kept all 5 component tests + error paths; dropped codec
  byte-cross-check + dead pre-LP-023 BE-hex fixtures, REPLACED with native
  TestTxComplexity (visitor single-path + batch-additivity + ErrUnsupportedTx).
  Removed TestConvertNetworkToL1ValidatorComplexity (fn deleted; per-validator
  convert complexity now inline in complexityVisitor.ConvertNetworkTx).
- fee/static + dynamic_calculator: skipped hex-loops -> native (TxFee/
  CreateChainTxFee/positive-priced supported, ErrUnsupportedTx unsupported).
- mempool/{auth,mempool}: native New*Tx + Initialize(); strict-PQ credential
  gate (ErrLegacyCredentialUnderStrictPQ) + Add/Get/Peek/Remove/DropExpired.
- txheap/by_end_time: NewAddValidatorTx + heap-ordering assertions.
go test ./txs/fee/ ./txs/mempool/ ./txs/txheap/ = ok (17 tests, no skips).

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-11 05:40:20 -07:00
hanzo-dev 6b599d29e1 ci: run linux jobs on lux-build-amd64 ARC scale set (no GitHub-hosted builders) 2026-07-11 00:14:50 -07:00
zeekayandHanzo Dev c5e999487c Green the 8 post-bump test failures (real fixes, no delete-to-hide)
- spending.go: harden spendingTx.Bytes() against nil msg (uninitialized tx no
  longer panics the spend-verification path; production always sets msg).
- config/genesis-builder tests: codec-era Codec.Marshal -> native g.Bytes();
  AddValidator field access -> methods (Weight()/Validator()/StakeOuts());
  drop unused pchaintxs imports.
- config test: consensus params K=30 alpha 16->20/25 to satisfy v1.36's tighter
  BFT bound (2*alpha-K >= floor((K-1)/3)+1); assertions updated.
- version/compatibility.json: register Current v1.32.11 under RPCChainVM proto 42
  (pre-existing registration gap).
- cevm e2e: genesis fixture completed with gasLimit+difficulty (strict geth
  genesis validation in the installed CEvm plugin; pre-existing fixture drift).

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 21:20:17 -07:00
zeekayandHanzo Dev 9626ca6c2f Bump consensus v1.35.37 -> v1.36.1 + rip node-side view-change plumbing
v1.36 upstreamed round-scoped view-change INTO the engine (internal prevote/POL
in attestation/reconcile/cert), dropping the external hooks config.Parameters.
ViewChange + Runtime.HandleIncomingPrevote. Ripped the node's now-redundant
external plumbing: the ViewChange enable block (LUX_CONSENSUS_VIEW_CHANGE gate),
the quorumKindPrevote gossip routing + HandleIncomingPrevote call, the dead
BroadcastPrevote gossiper method, and the quorumKindPrevote envelope kind. The
engine owns view-change natively now (fail-secure halt on 2a-n>f unchanged).

Whole node builds EXIT 0 on v1.36.1; luxd binary compiles (55M).

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 21:07:38 -07:00
zeekayandHanzo Dev 87a57925f3 components/lux UTXO value tree -> native ZAP (Wave-A Substrate)
The shared UTXO value tree (UTXO/TransferableOutput/TransferableInput/Asset/
UTXOID/BaseTx/Metadata + OutputOwners path) gets native struct-is-wire
Marshal/Unmarshal (new marshal.go), replacing every pcodecs.Manager. Codec
param dropped from utxo_state / atomic_utxos / transferables (Sort* sorts on
inner fx wire Bytes()); flow_checker pcodecs.Errs -> errors.Join.

Node consensus persistence uses luxfi/utxo (unchanged); components/lux is the
tx-builder/#58 surface — encoding-only change, type tree NOT collapsed (#58
respected). Both P and X share the encoding => internally consistent, re-genesis
safe. Whole node builds EXIT 0; 8 components/lux round-trips + P-chain txs/block
tests green.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 21:01:11 -07:00
zeekayandHanzo Dev 3b4d16bbc5 indexer p-chain example: block.Parse(b) codec-free — WHOLE NODE builds
Last P-chain codec consumer. go build ./... = EXIT 0. The platformvm codec
(pcodecs/txs.Codec/serialize tags) is fully dead; P-chain tx + block + state are
native ZAP struct-is-wire end to end. Remaining codec surface is X-chain +
proposervm + warp (Wave A), which still carry their own (intact) codecs.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 14:35:18 -07:00
zeekayandHanzo Dev 511a804016 Decomplect: CreateChainTx is the sole chain constructor (kill genesis-chains stub)
CreateNetworkTx no longer carries genesis chains — the executor never created
them, so tx.Chains() was a latent stub (declared, verified, silently dropped).
Model A resolves it by decomplection, not by implementing a second chain path:

  - CreateNetworkTx = ∅→Network birth (owner + security.Mode + own validator set).
  - CreateChainTx = the ONE chain constructor. An L1 spawn is a BLOCK of
    CreateNetworkTx + N CreateChainTx (block-atomic, not tx-atomic).
  - Removed NetworkChain, its wire (writeNetworkChains/readNetworkChains/
    ncStride/sliceIDs), the chain error set, MaxNetworkChains, the chains param.
  - managerChainIdx (index into genesis chains) -> managerChainID (direct
    ids.ID), now SYMMETRIC with ConvertNetworkTx's manager ref. ids.Empty =>
    P-Chain-governed; a set chainID => Contract-governed staking-contract host.

Net: less code (write as little as possible), one-and-one-way chain creation,
no stub. platformvm build+vet PASS; SovereignL1/InheritedL2/HybridL2/Convert
round-trips PASS.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 14:33:13 -07:00
zeekayandHanzo Dev c44cc2289f platformvm builds GREEN off the codec: executor fold + full consumer flip
vms/platformvm/... build + vet PASS with pcodecs/txs.Codec gone from the VM.

Executor semantics (standard_tx_executor):
- registerOwnSet(): shared primitive — per-validator state.L1Validator with
  native owner blobs (txs.MarshalOwner/UnmarshalOwner, no codec), active-set
  capacity check, EndAccumulatedFee=balance+accruedFees, SetNetToL1Conversion
  manager-authority recording (byte-for-byte legacy tail).
- ConvertNetworkTx: promote endomorphism (owner-authorized, folds old
  ConvertNetworkToL1Tx), gated by security.Mode.Manager.
- CreateNetworkTx: base (AddNet/SetNetOwner) + sovereign path registers own set.
- Deleted CreateSovereignL1Tx + ConvertNetworkToL1Tx.
- txs.UnmarshalOwner added: canonical owner marshal/unmarshal pair, no codec.

All ~13 txs.Visitor impls carry ConvertNetworkTx; gossip/block Parse(b) codec-free;
wallet/network/primary off txs.Codec.

KNOWN GAP (pending design decision, NOT silently green): CreateNetworkTx reads
tx.Chains() only to derive managerChainID — it does NOT create the genesis
chains (no AddChain). Atomic-spawn-with-chains vs decomplect-to-CreateChainTx is
the open call. 17 codec-era _test.go parked as .bak for follow-up rewrite.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 14:25:08 -07:00
zeekayandHanzo Dev c73eba739f Flip 4 platformvm consumers off txs.Codec (MarshalOwner + New*Tx + native genesis Bytes)
- txs.MarshalOwner(any): ONE canonical owner encoding (same layout as embedded
  tx owner), lifted to a standalone buffer for lock-owner hash keys in utxo
  handler+verifier. Replaces txs.Codec.Marshal(owner). Re-genesis-safe (ownerID
  only matched within a tx's own consumed/produced sets).
- validators/manager: chain.ChainID -> chain.ChainID() (field->method).
- api/static_service: genesis txs via NewAddValidatorTx / NewAddPermissionless
  ValidatorTx / NewCreateChainTx + codec-free Initialize(); genesis blob via
  native g.Bytes(). Mid-flip: executor + remaining visitors still pending.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 13:40:18 -07:00
zeekayandHanzo Dev f1a3e85b8e Rename LuxAddress -> UTXOAddr (decomplect place-from-value)
LuxAddress in airdrop.AirdropClaim + bridgevmroot.SignerLeaf is the NATIVE
20-byte Lux address (ids.ShortID / [20]byte), held beside the EVM common.Address
it disambiguates. 'Lux' prefix is banned place-in-value naming; the canonical
pair is EVMAddr / UTXOAddr. Named by address KIND, not brand.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 13:30:17 -07:00
zeekayandHanzo Dev d008eba286 security.Mode: decomplect network security into its own package
Pull the network security model out of the tx wire into a small orthogonal
package (vms/platformvm/security): pure values, stdlib-only, no zap/tx/state
deps. One definition — security.Mode{RestakeParent, Admission, Threshold,
Manager} + Sovereign() + Valid() — composed by tx wire, executor, and state
(Rich Hickey: values not places; Rob Pike: no stutter, small orthogonal pkg).

Two orthogonal axes replace the flat Inherited/Sovereign byte:
  - RestakeParent: lean on parent's validator set
  - own set: Admission(NoOwnSet|Open|Gated) + Manager(PChain|Contract)
Their product spans every mode incl. HYBRID L2 (restake AND additive own set),
which the flat byte could not express. Invariant RestakeParent || own-set on
Mode.Valid(); Sovereign derived, never flagged.

CreateNetworkTx + ConvertNetworkTx carry security.Mode on the wire via shared
setSecurity/readSecurity. Round-trip green incl. new HybridL2 case + Convert
target-mode. Wallet builders pass the explicit restaked-L2 Mode.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 12:59:29 -07:00
zeekay b6143b5d53 Block codec → native ZAP (struct-is-wire): builds + round-trips green
Blocks are now the zap buffer: kind + parentID@1 + height@33 + time@41 +
tx-length-list@49 + tx-blob@57 (+ proposal-tx@65). commonZapBlock embedded base
mirrors spendingTx. Parse = zap.Parse + kind dispatch (no codec, no version).
Deleted block/codec.go + block/v0 + lift_v0. Round-trip green for abort/commit/
proposal/standard incl real signed txs. go build + go test ./block/ = green.

FINDING: block.GenesisCodec was double-duty — also serialized NON-block STATE
values (feeState, owners, L1Validator, metadata, chains). That's a THIRD codec
surface (state DB serialization) still to migrate for the full kill.
2026-07-10 12:43:20 -07:00
zeekay 20d36b36aa Restore ConvertNetworkTx as the promote endomorphism (Create ≠ Convert)
Create and Convert are orthogonal arrows: CreateNetworkTx = ∅→Network (birth,
sovereign-or-inherited); ConvertNetworkTx = Network→Network (promote an
existing network: inherited→sovereign, re-anchor parent — L2→L1, L3→L1, with
owner auth). Only CreateSovereignL1 stays folded (it was birth+sovereign, not
a distinct op). Both reuse the NetworkValidator component. Round-trip green
incl L2→L1 promote.
2026-07-10 12:13:15 -07:00
zeekay 4610978bcc Decomplect network creation: one CreateNetworkTx folds Convert+CreateSovereign
CreateNetworkTx{parent, owner, security, validators, chains, manager} creates a
network at ANY level in one tx — parent is the level axis (Primary⇒L1, L1⇒L2,
recurse; level=depth, never stored). security is a coproduct: SecuritySovereign
(own validators+manager) | SecurityInherited (restaked from parent). manager
lives on the Network so an inherited L2 holds local admin. NetworkValidator +
NetworkChain are shared value components (reused by CreateChainTx). Deleted
ConvertNetworkToL1Tx + CreateSovereignL1Tx (folded / migration artifacts).

Round-trip green: sovereign L1 (own validators+chains+manager) AND inherited L2
(parent recorded, no own validators, local manager) both survive. One and one
way to make a network at any depth.
2026-07-10 11:39:12 -07:00
zeekay e869b7bcd1 Consumer flip: fee + wallet field->method accessors + codec-free signing
fee/complexity + static_calculator + wallet/chain/p signer/backend visitors
moved off removed struct fields onto method accessors (tx.Ins->tx.Inputs()
etc). sign() rewritten to the codec-free unsigned‖creds model (tx.Unsigned.
Bytes() + tx.Initialize()). txs/fee + wallet/chain/p/signer build clean.
2026-07-10 11:11:42 -07:00
zeekay bbba24bad6 txs pure-zap wire PROVEN: round-trip green (fix AddBytes element-count bug)
zap.ListBuilder.AddBytes counts BYTES not elements; fixed-stride lists were
storing byte-inflated counts -> stride clamp rejected them. Fixed every write
helper to store the real element count (len(entries)). Round-trip test now
GREEN across the hardest cases: multisig+stakeable outputs/inputs, the nested
ConvertNetworkToL1Validator (NodeID+BLS PoP+2 owners), SovereignL1Chain
manifest, and signed unsigned‖creds. go build ./vms/platformvm/txs = exit 0.

The P-chain tx wire is now struct-IS-wire, codec-free, and verified correct.
2026-07-10 10:57:47 -07:00
zeekay 34cb5c1684 txs package GREEN: pure zap struct-is-wire compiles (Convert + CreateSovereign done)
All 21 real P-chain tx types are now the zap buffer — no codec, no marshal/
unmarshal, no Manager, no version, decompounded, on luxfi/zap. ConvertNetworkToL1Tx
+ CreateSovereignL1Tx hand-written with a shared ConvertNetworkToL1Validator
nested encoder (fixed-stride records + shared NodeID/addr pools) and a
SovereignL1Chain encoder. go build ./vms/platformvm/txs/ = exit 0.

Next: round-trip correctness test, then the external consumer flip.
2026-07-10 10:53:14 -07:00
zeekay e288b67008 Decomplect P-chain tx set: rip Slash + P-chain CreateAsset/Operation, restore staker ifaces
- SlashValidatorTx ripped (unwired stub; Avalanche has no slashing; consensus
  only detects, never enforces). Type+executor+tests+Visitor surface removed.
- CreateAssetTx + OperationTx ripped from P-CHAIN (X-chain/AVM types; LP-0130:
  asset creation + fx ops are X-chain money-rail, not P staking-rail; no P
  producer). xvm/avm untouched.
- Staker interfaces (StakerTx/ValidatorTx/DelegatorTx/ScheduledStaker) restored
  on the 5 validator types via pure accessors + FxID-on-stake preserved.
- Remaining real complex types: ConvertNetworkToL1Tx + CreateSovereignL1Tx.
2026-07-10 10:36:35 -07:00
zeekay f0a00167e9 node v1.36.0 — Nova/Quasar export-frontier bridge; consensus v1.36.0
Wires the consensus EXPORT (Quasar, two-thirds-stake) frontier into the C-Chain VM so
the EVM finalized/safe tags and the warp cross-chain gate resolve to the Quasar tip.
Consensus v1.35.38 -> v1.36.0.
2026-07-10 09:44:14 -07:00
zeekay 33e005c869 fix register_l1 verifyBaseTx (return-form) 2026-07-10 09:18:19 -07:00
zeekay 949210730d Pure zap tx: 18 type files converted (parallel) + verifyBaseTx reconciled
Batches 1-3 (proposal + spending + validator-family) landed pure: struct is
the buffer, New*Tx builds, accessors read, SyntacticVerify via verifyBaseTx.
Remaining package-internal: 5 complex types (Convert/CreateSovereign/CreateAsset/
Operation/Slash) + staker interface methods + consumer flip.
2026-07-10 09:17:15 -07:00
zeekay 8d2fb750b6 Remove stale codec tests (codec deleted) 2026-07-10 09:08:31 -07:00
zeekay 1bc07cb1ca Pure zap tx: pure Tx (Parse=wrap+split, Sign=build) + delete reflection codec
tx.go: Tx holds Unsigned (zap-backed) + Creds; Parse wraps signed bytes and
splits unsigned/creds at the self-delimiting boundary; Sign builds unsigned‖creds;
no codec.Manager param anywhere. Deleted codec.go (V0/V1/V2 reflection Manager)
and codec_activation.go. WIP: consumer sites that passed txs.Codec / called the
old Parse(codec, bytes) flip next.
2026-07-10 09:08:15 -07:00
zeekay 1dede2e3d2 Pure zap tx: Parse kind-dispatch + native credential wire (no codec)
Parse wraps the buffer zero-copy and dispatches on the 1-byte kind. Signed =
unsigned ‖ creds (both self-delimiting), so unsigned is a byte-prefix of
signed. writeCredsBuf/parseCredsBuf encode credentials natively (shared 65B
sig-blob array). No Marshal/Unmarshal/Manager. WIP: references the 24 pure
type constructors (5 hand-written + 18 in parallel conversion + 1 template).
2026-07-10 09:07:13 -07:00
zeekay 636944a63a Pure zap tx: spendingTx embedded base (envelope surface for all types) 2026-07-10 09:02:58 -07:00
zeekayandHanzo Dev 9c2468671e chains: bridge the consensus EXPORT (Quasar) frontier into the VM; drop dead view-change braid (v1.36)
Wire the two-tier consensus export boundary through the node so the EVM `finalized`/`safe` tags and
the warp export gate track the ⅔-stake Quasar tip, never the reorgable Nova/accept tip:

- Set NetworkConfig.QuasarObserver to push each EXPORT (Quasar) frontier advance into the raw inner
  VM (SetLastQuasarFinalized) — the eth/warp backends live there, not on the proposervm wrapper.
  Interface-gated: only a VM exposing the export sink (the C-Chain EVM) participates.
- On boot, re-seed the consensus export frontier from the VM's DURABLE Quasar height
  (SyncQuasarFrontier) so GetQuasarTip/QuasarHeight do not regress on restart.

Also remove the node's dead references to the v1.36-deleted Tendermint braid (the consensus engine
dropped it in 174af3c31), which no longer compile against the v1.36 engine:
- the LUX_CONSENSUS_VIEW_CHANGE opt-in (params.ViewChange is gone — Nova is the sole decider),
- the quorumKindPrevote gossip kind + BroadcastPrevote + HandleIncomingPrevote routing (no prevotes;
  the ⅔ Quasar attestation rides the ordinary accept-vote gossip). Keep the braid dead.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 04:59:06 -07:00
zeekay 7750ca1829 gofmt spending.go 2026-07-10 01:43:56 -07:00
zeekayandHanzo Dev c526c0aaa4 Pure zap tx: reusable delta encoders (owner/auth/validator/signer/idlist)
Shared delta-field encoders every non-proposal tx composes on the spending
envelope: owner (fx.Owner), auth (*secp256k1fx.Input), inline Validator (44B)
+ Signer (145B: kind+BLS pubkey+PoP), id lists, extra spending lists. Built on
luxfi/zap. With spending.go, the full reusable foundation — type files are now
pure compositions.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 01:42:43 -07:00
zeekayandHanzo Dev 7354ce84b9 Pure zap tx: shared spending wire (envelope + Output/Input/owner/creds)
The envelope (NetworkID/BlockchainID/Outs/Ins/Memo) + multisig/stakeable
Output/Input entries + shared owner-address/sig-index arrays, built on
luxfi/zap generic primitives — no codec, no zap_native package. writeSpending/
setEnvelope build inside New*Tx; readEnvelope reads lazily. Polymorphism
(TransferOutput/LockOut, TransferInput/LockIn) handled in explode/assemble.
Foundation every non-proposal tx composes.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 01:40:27 -07:00
zeekayandHanzo Dev 8e7253a3c5 Pure zap tx: kind dispatch + AdvanceTimeTx template (struct IS the wire)
kind.go: 1-byte discriminator @ object offset 0 = the whole dispatch. No
codec, no version, no slot map. AdvanceTimeTx converted to the pure model:
holds *zap.Message, Time() is an offset read, NewAdvanceTimeTx builds once,
Bytes() returns the buffer. No marshal/unmarshal anywhere.

Template for the remaining 21 types. Package migrates atomically (codec.go +
all types + Parse/Sign together), so it compiles green again only when the
whole set + concentrated consumers (executor/builder/fee/api, ~63 New sites)
are converted. WIP.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 01:24:10 -07:00
zeekayandHanzo Dev 67ec31a344 Rip the marshal/unmarshal bridge — it was a codec by another name
ZAP has no serialization step. The bridge copied fields between plain txs.*
structs and the buffer, which is exactly the codec ZAP deletes. Removed.
The right way: tx type IS the zap buffer (accessors, Parse=wrap, Bytes=buffer),
no codec / manager / compat / version. Wire primitives stay in luxfi/zap.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 01:13:02 -07:00
zeekayandHanzo Dev 77389092c2 LP-023: bridge 5 more tx types (extra-list/bytes/idlist deltas)
Shared extra-out/in list helpers (Import/Export second spending set), id-list
+ BLS-PoP encoders. Bridges TransferChainOwnership, RegisterL1Validator,
Import, Export, CreateChain. Round-trip green (13/22 P-tx types native).

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 01:03:37 -07:00
zeekayandHanzo Dev 13cca30a71 LP-023: bridge 5 delta tx types (owner/auth/scalar deltas)
Shared delta-encoders (owner=fx.Owner->OutputOwners, auth=verify.Verifiable->
secp256k1fx.Input, fixed-id helpers). Bridges IncreaseL1ValidatorBalance,
SetL1ValidatorWeight, DisableL1Validator, RemoveChainValidator, CreateNetwork
= spending envelope + fixed-offset delta fields. Round-trip green (8/22 P-tx
types now native: proposal x2 + BaseTx + these 5).

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-10 01:00:42 -07:00
zeekayandHanzo Dev a93e5cdd9d chains: size-chunk GetContext responses so a behind validator resyncs under heavy load (1/3)
Benchmark-proven live mainnet bug (250-trader DEX load): a validator that falls behind cannot
resync the C-Chain. GetContext (the catch-up "context response", wire = Ancestors) bounded the
response ONLY by block COUNT (maxContextBlocks=256). Under heavy DEX load 256 blocks summed to
3.4-5.7 MB, exceeding the 2 MB peer message cap (the zstd compressor refuses uncompressed input
above constants.DefaultMaxMessageSize to prevent a decompression bomb), so msgCreator.Ancestors
FAILED to build and the behind validator received NOTHING — permanently stuck while the tip
advanced (luxd-3 stuck at 256 while tip went 293→300, looping empty-block builds).

Fix (piece 1/3 of the layered design — defense in depth): GetContext now ALSO bounds the
response by serialized SIZE. It stops adding blocks before the accumulated payload would exceed
byteBudget (cap − 128 KiB envelope margin), but ALWAYS includes at least one block so a behind
node makes progress every round; the requester re-requests the remaining gap (context fetch is
already a multi-round oldest-first fill). A single block that alone exceeds the budget is still
served (best-effort) so the walk never deadlocks — the forthcoming trust-tiered validator cap
(pieces 2/3) gives such a block the send headroom; a stranger's tight cap correctly rejects it.

Tests (chains/context_chunk_test.go): TestGetContext_ChunksBySize_FitsUnderCap (100×150 KiB
chain → 12 blocks / 1.84 MB, under budget, vs ~15 MB packed by count — fail-on-old);
TestGetContext_SingleOversizeBlock_StillServed (one oversize block still served, no deadlock).

Pieces 2/3 to follow: trust-tiered message cap (validator peers get headroom, strangers keep
2 MB) + confirm the inbound throttler/benchlist penalizes oversized-message senders.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-09 23:30:40 -07:00
zeekayandHanzo Dev ae3e3a45f5 LP-023: native spending envelope + full component converters
Shared spending envelope (NetworkID/BlockchainID/Outs/Ins/Memo) + polymorphic
converters bridging the txs struct graph to proto/zap_native primitives with
zero reflection: TransferOutput/stakeable.LockOut, TransferInput/stakeable.LockIn,
secp256k1fx.Credential. BaseTx (TxKindBaseFull) bridged; creds travel in the
separate creds buffer of the unsigned‖creds envelope.

Round-trip GREEN: 2-of-3 multisig + owner-locktime output, stakeable.LockOut,
stakeable.LockIn input, memo, AND signed secp256k1 credentials all survive
Marshal->Unmarshal with exact field equality; unsigned stays a byte-prefix of
signed. Every embedding tx type now composes this envelope + its delta fields.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-09 21:39:14 -07:00
zeekayandHanzo Dev 83c1a83765 v1.34.29: consensus v1.35.37 -> v1.35.38 (behind-node self-heal via cert-triggered ancestor catch-up)
Fixes the 'restart-recovery exhausted' mainnet killer: a slipped validator
logged 'cert REFUSED (behind; fetch and retry)' but NEVER fetched, because
HandleIncomingCert only triggered a catchup when the cert's OWN block was
untracked — never for a missing INTERMEDIATE ancestor. v1.35.38 (3c09ecb94)
surfaces the specific missing ancestor as a typed error and the cert handler
fires exactly one requestCatchup for it. The node-layer fetch machinery
(networkCatchup.RequestAncestors -> requestContext -> GetAncestors ->
AcceptCatchupBlock) was already fully wired — it was just never called on this
path. With --skip-bootstrap=true (which disables the beacon-quorum frontier
backstop) this cert-trigger was the ONLY self-heal path, so its absence was
fatal: a behind node couldn't rejoin -> effective 4/5 -> any flap -> stall.

Consensus-side only, no node code change. -race: launch-gate invariant PASS
(rejoin 2.75s, no fork); self-heal + typed-error tests PASS, no data races.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-09 21:28:06 -07:00
zeekayandHanzo Dev be18fce176 LP-023 keystone: native-ZAP tx Manager (drop-in, zero reflection)
Adds nativeManager implementing pcodecs.Manager by bridging txs structs to
proto/zap_native buffers — no reflection, no serialize-tag walk, no version
dispatch. Signed wire = unsigned_zap_buffer ‖ creds_zap_buffer (ZAP buffers
are self-delimiting), preserving tx.go's unsigned-is-prefix-of-signed
invariant with no tx.go change. AdvanceTimeTx + RewardValidatorTx bridged
and round-trip green (build->Marshal->Unmarshal field equality, byte-stable,
prefix invariant, non-ZAP reject). Added alongside the reflection Codec;
flip + reflection deletion lands once all registered types are bridged.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-09 16:53:16 -07:00
zeekayandHanzo Dev 74be89840c v1.34.28: consensus v1.35.36 -> v1.35.37 (F1 stale-alias prevote-lock rebase)
Third-layer mainnet finality fix. v1.34.27 (consensus v1.35.36) proved the
dynamic committee (alpha=4 n=5) and topology.go cert-receive canonical resolve
work live — consensus climbed past 1085755 to round-height 1085761 — but hit the
next layer: a stale-alias prevote-lock. viewForLocked seeds lockBlock from a
pre-canonical-fix durable committedSlot (an OUTER proposervm-wrapper id); a
round-0 lock on an outer alias makes prevoteTarget compare the stale outer id
against the inner-canonical winner by raw id, mismatch forever, no POL, freeze.

v1.35.37 (742696baf): stepViewChange rebases a stale-alias lock onto the inner
canonical winner IFF it resolves (via the same vmCanonicalResolver the cert
rebase uses) to exactly winnerCanon — a genuinely different inner (real fork) or
unresolvable lock is left fail-closed frozen, never merged. lockRound preserved,
2a-n>f untouched, alpha inner-precommits were always inner (CanonicalVoteMessage
binds inner, excludes outer). Full engine/chain green (356s, 0 fail); -race
clean; RED safety gate proves divergent inners still refused.

Roll note: luxd-4 first releases its lock (log 'vc stale-alias lock REBASED');
finality past 1085755 needs >=4 nodes on this build, so height climbs as 3->2->
1->0 come up. EVM stays v1.104.7 (head-pin).

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-09 12:05:51 -07:00
zeekayandHanzo Dev 9a0800065f v1.34.27: consensus v1.35.33 -> v1.35.36 (EVM-accept unstick + dynamic committee + snowman purge)
Unsticks mainnet C-Chain finality. Root cause (consensus-layer, proven): under
pChainHeight=0 anyone-can-propose, each validator wraps the same inner block in
its own outer proposervm envelope; votes are canonical-keyed so an α-of-K cert
forms network-wide, but HandleIncomingCert did a strict envelope-id lookup — a
node holding a different alias of the same inner block missed it and requested
catchup instead of finalizing the local wrapper it held, so VM.Accept was never
called and the EVM head froze at 1085755 while consensus logged 'finalized
voters=4'. v1.35.34 (66438a23b) resolves the local wrapper by canonical id and
rebases the verified cert (outer ids unsigned; α votes verify unchanged), no
fork (per-height gate keys on canonical id, idempotent).

Also: dynamic committee 1→N proven (v1.35.35, effectiveCommittee sizes cert +
view-change from live validator count; n=1→1/1,2→2/2,3→3/3,4→3/4,5→4/5 — the
BFT-safe ⌊2n/3⌋+1); view-change safety gate realigned to the effective
committee (RED#2); snowman comment-purge (Quasar/Nova); dynamic committee logs.
Node commits: 4e71814e58 (proposervm→EVM Accept-cascade test, RED#1),
c13681108f (purge), a02611413e (logs). EVM stays v1.104.7 (head-pin). Full
engine/chain suite green under -race (369s, 0 fail/0 race); RED adversarial
suite proves scale-invariance 1→1M + RLP seam byte-exact on real mainnet state.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-09 11:11:58 -07:00
zeekayandHanzo Dev 4e71814e58 vms/proposervm: prove proposervm-finalize → inner-EVM Accept propagation (RED #1, choke #4)
The mainnet 1085755 freeze had consensus finalizing an outer proposervm block while the
inner EVM lastAccepted stayed frozen. The consensus engine's ledger advancing on VM.Accept
is proven in engine/chain; this proves the OTHER half at the NODE layer — that VM.Accept on
a proposervm wrapper cascades to the inner block's Accept:

  postForkBlock.Accept → acceptOuterBlk → acceptInnerBlk → Tree.Accept(innerBlk) →
  innerBlk.Accept  ⇒ inner VM lastAccepted advances

- TestAcceptCascade_InnerHeadAdvances_AtScale: 1000 heights through the REAL Accept path;
  the inner EVM head + proposervm head advance in lock-step at every height.
- TestAcceptCascade_SiblingStorm_WinnerAdvancesInnerOnce: five distinct outer envelopes wrap
  ONE inner block (the anyone-can-propose alias set); accepting the finalized wrapper advances
  the shared inner exactly once.

Confirms the propagation was sound, not a node-layer bug — the freeze was the consensus-layer
storm-alias resolution gap (fixed in consensus v1.35.34). The real luxfi/evm RLP-import→produce
→tip byte-exactness is proven separately in evm/core rlp_seam_red_test.go; composed, they cover
the full engine→proposervm→EVM Accept path.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-09 10:57:31 -07:00
zeekayandHanzo Dev c13681108f node: purge 'snowman' comment references — Quasar/Nova terminology (comment-only, no behavior change)
Removes the forbidden Avalanche term from code comments in chains/manager.go,
chains/quorum.go, and vms/proposervm/proposer/windower_determinism_test.go. Reworded to
preserve exact meaning; comments only, no identifier/behavior change.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-09 10:50:27 -07:00