mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
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
4.7 KiB
4.7 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[1.28.0]
Added
- Multi-version P-Chain block + tx codec. v1.23.x ("Apricot/Banff") wire layout is now registered as
CodecVersionV0on the platformvm tx and blockcodec.Managers; the current canonical layout isCodecVersionV1. Bytes carry their wire version in the standard 2-byte codec prefix andtxs.Parse/block.Parsedispatch by it. - Byte-preserving tx Initialization:
tx.InitializeFromBytes(c, version, signedBytes)andtx.InitializeFromBytesAtVersion(c, version)bind a tx to its originalsignedByteswithout re-marshalling.TxID = hash(signedBytes)is therefore stable across the v0->v1 migration — mainnet and testnet chain commitments hash back to byte-identical inputs. vms/platformvm/block/v0/subpackage holding the pure-data v0 block kinds (ApricotProposalBlock,BanffProposalBlock, ... — 9 types, slots 0-4 + 29-32). The package is a one-way decoder only; theliftedV0Blockadapter in the parent package translates each v0 block kind into the corresponding canonical v1Visitorarm without ever re-marshalling.- Cross-version tx + block tests:
TestCodecVersionV0V1Coexist,TestParseDispatchesByVersion,TestTxIDStabilityRoundTrip,TestCrossVersionRefuses,TestParseV0ApricotProposalBlock,TestParseV0BanffStandardBlock,TestParseV1RoundTrip,TestVersionPrefixDispatch.
Changed
tx.Initialize(c)is retained for the fresh-build path only (wallet, builder). The from-DB / from-wire paths ingenesis/genesis.goandblock/{standard,proposal}_block.gonow go throughInitializeFromBytesAtVersionagainst the codec version the surrounding container was decoded under.genesis.Parseis wire-version-aware: pre-codec-v1 P-Chain genesis blobs on mainnet / testnet decode atCodecVersionV0; new blobs are written atCodecVersionV1.- The L1-tx slot map advances by one to accommodate
CreateSovereignL1Txat slot 36:RegisterL1ValidatorTx=37,SetL1ValidatorWeightTx=38,IncreaseL1ValidatorBalanceTx=39,DisableL1ValidatorTx=40 (was 36-39). Both pre-rip mainnet/testnet bytes (no slot conflict; L1 txs did not exist) and current code paths line up with the new slot map. - Test fixtures in
vms/platformvm/txs/fee/calculator_test.goand the serialization tests undervms/platformvm/txs/*_test.goare regenerated to use the v1 wire prefix (0x0001) and the post-CreateSovereignL1Txslot map.
Migration notes
- Mainnet + testnet P-Chain DBs do NOT need to be rebuilt: pre-codec-v1 blocks continue to decode via the v0 path with their original
BlockID = hash(v0 bytes)preserved. Newly accepted blocks are written at v1. - Devnet, which was bootstrapped post-rip at wire-version 0 but with the post-rip slot map, must be rebuilt before rolling to
v1.28.0: its existing blobs would now decode against the v0 slot map (the pre-rip layout) and produce wrong types. A fresh bootstrap atv1.28.0writes v1 bytes from height 0 and is internally consistent thereafter.
[1.13.5-alpha] - 2025-01-23
Added
- L1 (Layer 1) validator support with complete transaction types:
ConvertNetToL1Tx- Convert existing chains to L1RegisterL1ValidatorTx- Register new L1 validatorsSetL1ValidatorWeightTx- Adjust validator weightsIncreaseL1ValidatorBalanceTx- Increase validator balanceDisableL1ValidatorTx- Disable validators
- LP-118 protocol implementation for warp message handling:
- Signature aggregation support
- BLS signature verification
- Cached handler for performance optimization
- Handler adapter for P2P integration
- Complete wallet support for L1 validator operations
- Extended AppSender interface for cross-chain messaging
Fixed
- P2P test package compatibility issues
- Set package import conflicts (math/set vs utils/set vs consensus/utils/set)
- Interface compatibility between consensus and local packages
- Handler function signatures for proper interface implementation
- Mock testing with gomock package updates
- BLS signature handling in tests
- AppError type conversions between packages
- All wallet examples now compile and run correctly
Changed
- Updated import paths to use luxfi packages consistently
- Improved error handling in P2P message handlers
- Enhanced test coverage for LP-118 protocol
- Standardized AppError usage across packages
Technical Details
- 100% of internal packages (351 packages) now build successfully
- All tests pass in modified packages
- Full CI/CD pipeline configured with GitHub Actions
- Compatible with Go 1.21.12+
[1.13.4] - Previous Release
[Previous release notes...]