Commit Graph
9 Commits
Author SHA1 Message Date
zeekayandHanzo Dev a63a18bf71 node v1.32.11: C-Chain restart/recovery serving hardening (isBootstrapped truth + wipe-path ancestry)
Two node/bootstrap-layer fixes for a clean rolling validator upgrade. Consensus
engine untouched (v1.35.5 boot-seed from v1.32.10 carried forward).

[HIGH — correctness] info.isBootstrapped(C) tracks REAL state, not premature true.
  manager.IsBootstrapped(id) returned true the instant a chain merely EXISTED in
  m.chains (set right after createChain launched the async, possibly-stalling
  bootstrap goroutine) — so a C-Chain stalled at genesis (head 0x0) reported
  info.isBootstrapped(C)=true, masking the stall from any wait-for-healthy gate.
  Now keys on the SAME sb.Bootstrapped signal the readiness health check uses
  (m.Nets.IsChainBootstrapped), set only after runInitialSync reaches the named
  frontier and the VM goes to normal operation (head advanced, eth-RPC live).
  GetChains().Bootstrapped fixed identically. New per-chain query on nets.Net +
  chains.Nets (nil-safe). Regression test TestIsBootstrappedTracksRealConvergence.

[MEDIUM — robustness] WIPE-path GetAncestors fetch hardened for ≥2 peers at genesis.
  Applying the proven avalanchego contract (studied in snowman/bootstrap +
  getter): (a) Ancestors buffers the whole sample and SKIPS empty batches,
  returning the first NON-EMPTY one — a size-1 channel let a fast empty reply from
  a genesis peer win the race and starve a peer that actually held the ancestry;
  (b) sampleAncestorBeacons PREFERS beacons the frontier round found genuinely
  ahead (they hold the ancestry) — ava's PeerTracker "ask a prover" bias sourced
  from the replies we already have, no separate tracker. Tests:
  TestNodeBootstrap_WipePath_MixedGenesisPeers_ObtainsAncestry,
  TestSampleAncestorBeacons_PrefersAheadBeacons.

Build: main+chains+nets+service/info compile CGO_ENABLED=0 (ARC/Dockerfile path);
full chains+nets suites green.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-07-02 00:05:36 -07:00
Hanzo AI e5620bb3cd version: bump default to v1.30.6 — final json/v2 + ZAP-internal ship
Tracks v1.30.5 (strict-PQ peer identity bind) + the json/v2 boundary
migration + 8-site internal-JSON to ZAP-native rip from this session.

Default version: 1.30.4 → 1.30.6 (v1.30.5 already exists as a CI auto-bump
on the strict-PQ peer fix).

Includes:
  - xvm/txs/doc.go (canonical //go:generate zapgen directive
    pointing at proto/schemas/xvm/txs.zap)
  - compatibility.json + v1.30.5 + v1.30.6 under RPCChainVMProtocol 42
2026-06-07 01:39:20 -07:00
Hanzo AI c3b398bc7b json: migrate every encoding/json import to json/v2 (go-json-experiment)
External (HTTP / JSON-RPC) is the only place JSON is legitimate. Every
existing encoding/json import in node/ moves to github.com/go-json-experiment/json
(v2 root, not the v1 sub-package). NewEncoder/NewDecoder rewrite to
MarshalWrite/UnmarshalRead. MarshalIndent rewrites to Marshal with
jsontext.WithIndent. json.RawMessage rewrites to jsontext.Value.
*json.SyntaxError rewrites to *jsontext.SyntacticError.

81 files migrated. LLM.md captures the rule + v1->v2 delta table.

Known v2 semantic deltas surfaced by existing tests (followups, not regressions):
- [N]byte fields with no MarshalJSON now marshal as base64 string (v1 marshalled
  as JSON array of byte numbers). Affects vms/platformvm/txs/*_test.go fixtures
  with embedded BLS proofOfPossession.
- time.Duration has no v2 default representation; configs that wire-format
  Duration as nanoseconds (vms/{xvm,platformvm}/config, config/spec) need to
  switch to string-form Duration or carry an explicit option. v2 root does not
  re-export FormatDurationAsNano.
- v2 enforces strict UTF-8 (vms/chainadapter/messaging fixture has non-UTF-8).
- json.MarshalWrite does not append a trailing '\n' (v1 NewEncoder.Encode did);
  service/auth/auth_test.go expectation updated.
- nil []byte round-trips to empty (not nil); config_test deep-equal fixtures
  surface this.

All affected sites are at the API boundary; ZAP wire envelope already covers
the internal data paths (state, P2P, consensus, MPC, threshold). Internal
JSON sites that should move to ZAP next (separate work):
- vms/da/store.go            (DA blob/cert storage as JSON)
- vms/platformvm/airdrop     (airdrop claims as JSON in db)
- vms/chainadapter/appchain  (SQLite materializer schema/data blobs)
- vms/chainadapter/messaging (conversation codec)
- staking/kms.go             (KMS HTTP client — external technically, leave)
- utils/{bimap,ips}          (small marshaler shims — low priority)
2026-06-06 22:26:02 -07:00
Hanzo AI 9c80aeef27 version: bump default to v1.30.4
v1.30.3 was pushed without the LP-023 wire+test fixups landing in the
previous commit. v1.30.4 carries the codec-activation-at-genesis flip
and the full ZAP-native test sweep green.
2026-06-06 18:01:56 -07:00
Hanzo AI 4c6c1affba prep for v1.30.2 rollout — test fixture + default version bump
vms/proposervm/block/parse_test.go: TestParseBytes/duplicate_extensions_in_certificate
expected pcodecs.ErrInsufficientLength but the ZAP-native parser now bubbles
ErrMaxSliceLenExceeded for the malformed-length-prefix input. Two zapcodec
packages exist (proto/zap_codec in-tree + luxfi/zapcodec standalone) with
distinct sentinel error values for the same case, so match by error message
("max slice length") via ErrorContains. Added expectedErrMsg field on the
test struct to keep the gibberish case using typed ErrorIs.

version/constants.go: defaultMinor 28→30, defaultPatch 0→2. Without ldflags
the binary was reporting luxd/1.28.0 even though latest tag is v1.30.1.
v1.30.2 is the rollout candidate this becomes after CI tags.
2026-06-06 17:25:10 -07:00
Hanzo DevandGitHub 5e9942cee1 feat(platformvm): multi-version codec — v0 (Apricot/Banff) + v1 (current) — byte-preserving TxID/BlockID across migration (#123)
Closes the codec-version trap that surfaced when the v1.23.x ("Apricot/Banff") tx + block layout was rip-replaced in 409297a089 without bumping the wire-version prefix: mainnet/testnet on-disk blobs (~1.08M+ C-Chain blocks) lost a decoder, and any code path that round-tripped a tx through tx.Initialize re-marshaled it under the new layout — rotating TxID and breaking chain-commitment continuity.

Strategy A per cryptographer / orchestrator brief:

* Register both layouts on the platformvm tx + block codec.Managers under
  distinct wire-version prefixes:
  - CodecVersionV0=0 = v1.23.x slot map (TransferInput=5, hole=6, ...,
    AddPermissionlessValidator=25, ..., DisableL1Validator=39)
  - CodecVersionV1=1 = current slot map (with MintOutput/MintOp at 6/8,
    +4-skip for Banff txs at 27-30, CreateSovereignL1Tx at 36,
    SlashValidatorTx at 41, CreateAssetTx/OperationTx at 42-43)
  - txs.Codec / block.Codec dispatch by the standard 2-byte wire prefix.

* New byte-preserving init: tx.InitializeFromBytes(c, version, signedBytes)
  and tx.InitializeFromBytesAtVersion(c, version) bind the tx to its
  original signedBytes without re-marshalling. tx.Initialize stays as the
  fresh-build path; from-DB / from-wire paths route through the
  byte-preserving variant. TxID = hash(signedBytes) under the version it
  was written at, forever.

* New vms/platformvm/block/v0/ subpackage: 9 v0-only block kinds
  (ApricotProposalBlock, BanffProposalBlock, ... at slots 0-4 + 29-32).
  Pure DTOs — no codec, no Visit. The block package wraps the decoded
  v0.Block in a liftedV0Block adapter that:
  - returns the original bytes verbatim (no re-marshal),
  - BlockID = hash(raw v0 bytes),
  - dispatches Visit to the v1 Visitor arms (ApricotProposalBlock /
    BanffProposalBlock -> ProposalBlock, etc.),
  - re-binds embedded txs at v0 via InitializeFromBytesAtVersion so
    inner TxIDs are also byte-preserved.

* genesis.Parse is wire-version-aware: pre-codec-v1 genesis blobs decode
  at v0, new blobs at v1. The matching codec is used for tx re-binding.

* L1-tx slot map shifts +1 to accommodate CreateSovereignL1Tx at 36
  (RegisterL1Validator 36->37, SetL1ValidatorWeight 37->38,
  IncreaseL1ValidatorBalance 38->39, DisableL1Validator 39->40). Test
  fixtures regenerated.

* 22 fee-calculator fixtures + 11 serialization fixtures bumped to use
  the v1 wire prefix (0x0001) and the post-CreateSovereignL1Tx slot map.

Migration notes:
* Mainnet + testnet P-Chain DBs: NO rebuild. Pre-codec-v1 blocks
  continue to decode through the v0 path with original BlockID and
  TxIDs preserved. New blocks are written at v1 from the cut-over
  height onward.
* Devnet: must be rebuilt before rolling to v1.28.0. Its existing
  blobs carry wire-version 0 but use the post-rip slot map (not the
  v0 Apricot/Banff layout) — decoding them through the v0 path would
  read the wrong types. A fresh bootstrap at v1.28.0 writes v1 bytes
  from height 0 and is internally consistent thereafter.

Tests:
* TestCodecVersionV0V1Coexist, TestParseDispatchesByVersion,
  TestTxIDStabilityRoundTrip, TestCrossVersionRefuses (txs)
* TestParseV0ApricotProposalBlock, TestParseV0BanffStandardBlock,
  TestParseV1RoundTrip, TestVersionPrefixDispatch (block)
* 150 packages, 0 failures under -race
2026-05-31 01:38:42 -07:00
Hanzo AI 58d7efe2cc node/version: bump to v1.26.13 + register in RPCChainVMProtocol map
Carries the namespace rename (lux→security) on /ext/security and the
F118 chain-manager profile-pin stamping landed in v1.26.12. Patch bump
only — no schema or behavior change beyond the rename of the
JSON-RPC namespace and REST sidecar path on the security service.

compatibility.json: add v1.26.12 + v1.26.13 to RPCChainVMProtocol 42
so TestCurrentRPCChainVMCompatible passes (the previous bump to
v1.26.12 left the map at v1.23.25).
2026-05-11 10:05:05 -07:00
Hanzo AI db9c11bed1 node+chains: stamp ChainSecurityProfile pin into C-Chain plugin config (closes F118)
Companion to coreth: c84950de4. The chain manager now forwards the
chain-wide ChainSecurityProfile resolved at node bootstrap (F102)
into the C-Chain (coreth) plugin Initialize payload by stamping a
profileID + profileHashHex pin into the JSON config bytes that
already cross the rpcchainvm boundary.

- chains/manager.go adds ManagerConfig.SecurityProfile and an
  injectSecurityProfileConfig pass (mirror of injectAutominingConfig)
  that runs only on EVMID and is a no-op when the profile is nil.

- node/node.go threads n.securityProfile into chains.ManagerConfig.

- version/constants.go patch-bumps to 1.26.12.

Four F118 tests in chains/security_profile_f118_test.go:
- StampsCChainOnly — pin appears in EVMID config, not in other VMs.
- NoOpWhenProfileNil — classical-compat path passes through.
- MergesExistingConfig — automining + skip-block-fee survive.
- RoundTripsAcrossPluginBoundary — the wire form decodes cleanly
  into the coreth-side LuxSecurityProfilePin struct shape, with the
  hash decoding to a full 48 bytes (SHA3-384 width).

go.mod bumps consensus v1.23.5 → v1.23.9 to pick up the F113
checkpoint+Merkle SHA3-384 widening.
2026-05-11 10:01:28 -07:00
Hanzo AI f6e63d60b2 clean: squash history (binaries stripped via filter-repo) 2026-04-13 03:45:21 -07:00