vms/pcodecs: route every codec construction through proto/zap_codec

Wave 2G-Internal (#101). node/vms/pcodecs no longer imports
github.com/luxfi/codec / linearcodec / wrappers / zapcodec directly.
Type aliases and constructor helpers route through
github.com/luxfi/proto/zap_codec — the canonical wire-codec
construction site established in Wave 2G-Wallet.

Surface changes (all back-compatible by shape for callers in
node/vms/*):

- Manager   = zap_codec.MultiManager (was codec.Manager)
- Registry  = zap_codec.Registry     (was codec.Registry)
- LinearCodec = zap_codec.LinearCodec (was linearcodec.Codec)
- ZAPCodec  = zap_codec.ZAPCodec     (was zapcodec.Codec)
- Errs      = zap_codec.Errs         (was wrappers.Errs)
- Packer    = zap_codec.Packer       (was wrappers.Packer)
- All sentinel errors + byte-len constants come from zap_codec.

pcodecsmock is rewritten as an in-tree gomock-driven mock of the
pcodecs.Manager interface (no longer a re-export of
luxfi/codec/codecmock). RegisterCodec / Marshal / Unmarshal / Size
expectations land via mock.EXPECT().<Method>(...).

Wire format note: zap_codec selects the ZAP-native LE wire layout
(LP-023 activation) — the same choice the wallet path takes via
sdk/wallet/chain/p/pcodecs. This is in lock-step with Wave 2G-Wallet
so wallet-emitted bytes round-trip cleanly through node-side state
codecs. Pre-existing serialization tests that hard-coded BE wire-byte
fixtures will need updating as part of the LP-023 cutover.

go.mod: bumps github.com/luxfi/proto v1.0.2 → v1.3.0 to pull in the
new proto/zap_codec MultiManager and helper surface.

Grep zero `"github.com/luxfi/codec"` imports in both pcodecs.go and
pcodecsmock/manager.go.
This commit is contained in:
Hanzo AI
2026-06-06 05:19:31 -07:00
parent f00dc8060d
commit 17b0e7457d
4 changed files with 213 additions and 105 deletions
+3 -3
View File
@@ -128,7 +128,7 @@ require (
github.com/luxfi/atomic v1.0.0
github.com/luxfi/chains v1.2.3
github.com/luxfi/compress v0.0.5
github.com/luxfi/constants v1.5.7
github.com/luxfi/constants v1.5.8-0.20260603055356-93c2c2ceb9ca
github.com/luxfi/container v0.0.4
github.com/luxfi/filesystem v0.0.1
github.com/luxfi/genesis v1.13.8
@@ -201,8 +201,8 @@ require (
require (
github.com/luxfi/concurrent v0.0.3
github.com/luxfi/proto v1.0.2
github.com/luxfi/upgrade v1.0.0 // indirect
github.com/luxfi/proto v1.3.0
github.com/luxfi/upgrade v1.0.1-0.20260603055252-f51810805436 // indirect
github.com/luxfi/version v1.0.1
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
)
+6
View File
@@ -276,6 +276,8 @@ github.com/luxfi/consensus v1.25.13 h1:hqbFq6W+oRvCrovj6Yu1zOsJNiRymHpjGdqZT1LvZ
github.com/luxfi/consensus v1.25.13/go.mod h1:7/tlpy+byv2tP7YZSMG+XtS8C2bbz3qpB4H8jxXhHxk=
github.com/luxfi/constants v1.5.7 h1:a1tCMdxd+pClPMIPOaI9vcYGNy6cQIc2rubac2Trc0k=
github.com/luxfi/constants v1.5.7/go.mod h1:z+Wc7skybZAA+xuBWNcmtv402S/BFqixL+FiSQXPg8U=
github.com/luxfi/constants v1.5.8-0.20260603055356-93c2c2ceb9ca h1:N2lM2gMJ2Hk5yZ6GqURWtg6nIVtodsjqMe+MGNiuCNw=
github.com/luxfi/constants v1.5.8-0.20260603055356-93c2c2ceb9ca/go.mod h1:z+Wc7skybZAA+xuBWNcmtv402S/BFqixL+FiSQXPg8U=
github.com/luxfi/container v0.0.4 h1:BXhF82WyfqVP5mjlNcr7tP0Fcnvl0Ap1rkiu+rq5XuM=
github.com/luxfi/container v0.0.4/go.mod h1:Z3SpmMF5d4t77MM0nHYXURpn+EMVaeu1fhbd/3BGaek=
github.com/luxfi/corona v0.7.6 h1:CJP6smygD55dL0HHkKkWryL9H24a+wXvs+L+WchK7Nc=
@@ -340,6 +342,8 @@ github.com/luxfi/precompile v0.5.27 h1:lEF5gXY8ny5xXp8Qg8PK0Y2RQlaRNOZeDU+wP6Sj2
github.com/luxfi/precompile v0.5.27/go.mod h1:boKRJeoa4XEhCoylRnPI/0IGfBgm5bZnFNI9llDktWo=
github.com/luxfi/proto v1.0.2 h1:kT/2c6M85nqJOzOZ9SYyZHCSGH32qexovMCB7ZPGk8g=
github.com/luxfi/proto v1.0.2/go.mod h1:pZLKsCmhiPtmm3z7ezBbnsYT2m79q+cFSmzxvuBeANE=
github.com/luxfi/proto v1.3.0 h1:OkBQ72K+2cvck1LlZVbMxrUJbjov2ci2JUWF2P6986o=
github.com/luxfi/proto v1.3.0/go.mod h1:JkzinRBQu02HsVPIGQvLVhG/xyO1ovTqoEAphOiNBso=
github.com/luxfi/protocol v0.0.4 h1:wf3JSyeNMEabOUG0vExtIAtjfpJAyHXlepGBwv5g9NE=
github.com/luxfi/protocol v0.0.4/go.mod h1:9f35GLNlcHAz6LCvFBDZP5fTD2QnN0URXWGUOcD1JPU=
github.com/luxfi/pulsar v1.1.2 h1:iPQlEpnVCggQSTZzUa9i/la2WLEN7fl7/4QVahGs9Ag=
@@ -372,6 +376,8 @@ github.com/luxfi/units v1.0.0 h1:2aNVB+WsP1XeDob71IsO0w3jJqP3FtZdYnFsmORkJZg=
github.com/luxfi/units v1.0.0/go.mod h1:tma28v4ed1tupdS0kpSeyO+u1wWK/g1NqODPbN1YzmA=
github.com/luxfi/upgrade v1.0.0 h1:mM6YXvU8VzoclA7IdtuE5bmnMuFquYxjKUUW84LJz54=
github.com/luxfi/upgrade v1.0.0/go.mod h1:DZF7dO4erhUEKf907B2e65k4/vGkCPkUngpvIEUS3eI=
github.com/luxfi/upgrade v1.0.1-0.20260603055252-f51810805436 h1:0VTZNA1+rXh9Tr0OpGmkwg+mYC6xgLv+XymMlZvLH/E=
github.com/luxfi/upgrade v1.0.1-0.20260603055252-f51810805436/go.mod h1:zBBG2VkZmWLr6u6DxzI/4DSFYjHizHrr7MqCDZkMSJc=
github.com/luxfi/utils v1.1.4 h1:8OY0jXCkpp6OotN1Y++6DATJkvtEwzq2k0p56imJlAk=
github.com/luxfi/utils v1.1.4/go.mod h1:c3yz1RjzrB+cs5GZm+q1T3/2cCKElO9vxm9yRRtgSEM=
github.com/luxfi/utils v1.1.5 h1:6q85557b7djbZ/OF6S1k5wyGddozWnsoUuhokPHQRvo=
+103 -90
View File
@@ -2,150 +2,163 @@
// See the file LICENSE for licensing terms.
// Package pcodecs is the canonical construction site for every
// codec.Manager + linearcodec / zapcodec instance under node/vms. Wave 2D
// of the codec rip (#101) consolidates direct `github.com/luxfi/codec`
// imports here so the rest of node/vms can reach for typed Manager /
// Registry values without importing luxfi/codec themselves.
// codec.Manager + codec instance under node/vms. Wave 2G-Internal of
// the codec rip (#101) replaces the previous direct imports of
// github.com/luxfi/codec / linearcodec / zapcodec with a single
// import of github.com/luxfi/proto/zap_codec the proto-layer wire
// codec entry point established in Wave 2G-Wallet.
//
// Layout:
//
// - Type aliases re-export the codec / linearcodec / zapcodec / wrappers
// surfaces every VM consumer needs (Manager, Registry, LinearCodec,
// ZAPCodec, Errs, Packer, VersionSize, sentinel errors).
// - Constructor helpers return fresh Manager / linearcodec / zapcodec
// instances at canonical size budgets (Default, MaxInt32, MaxInt,
// Sized). They are wire-agnostic — each VM's own codec.go layer
// registers its type set on top.
// - Genesis / runtime helpers compose Manager + LinearCodec pairs for
// the recurring "register types + register codec at version" pattern
// used by every VM's init().
// - Type aliases re-export the proto/zap_codec surfaces every VM
// consumer needs (Manager, Registry, LinearCodec, ZAPCodec, Errs,
// Packer, VersionSize, sentinel errors).
// - Constructor helpers return fresh Manager / Codec instances at
// canonical size budgets (Default, MaxInt32, MaxInt, Sized). They
// are wire-agnostic — each VM's own codec.go layer registers its
// type set on top.
//
// pcodecs has NO knowledge of any specific VM's type set. VM-specific
// registration stays in the VM's own codec.go (e.g.
// vms/platformvm/txs/codec.go). This split keeps pcodecs a leaf package
// — every node/vms subpackage is free to import it without closing an
// import cycle.
//
// Wire format: ZAP-native (little-endian) — the underlying impl is
// luxfi/codec/zapcodec routed through proto/zap_codec. The "Linear"
// name on LinearCodec / NewLinearCodec refers to LINEAR TYPE-ID
// ASSIGNMENT (sequential ids assigned in registration order), NOT to
// the historical linearcodec big-endian wire format. Activation
// per LP-023 (proto/zap_native/codec_select.go: ZAPActivationUnix=0).
package pcodecs
import (
"math"
"github.com/luxfi/codec"
"github.com/luxfi/codec/linearcodec"
"github.com/luxfi/codec/wrappers"
"github.com/luxfi/codec/zapcodec"
"github.com/luxfi/proto/zap_codec"
)
// Manager is the codec.Manager surface every node/vms consumer holds.
// Aliased so the rest of node/vms references pcodecs.Manager rather than
// importing luxfi/codec directly.
type Manager = codec.Manager
// Manager is the multi-version wire codec surface every node/vms
// consumer holds. Aliased to zap_codec.MultiManager so the rest of
// node/vms references pcodecs.Manager rather than reaching into
// proto/zap_codec or luxfi/codec directly.
type Manager = zap_codec.MultiManager
// Registry is the codec.Registry surface used for type registration.
type Registry = codec.Registry
// Registry is the type-registration surface. Aliased to
// zap_codec.Registry — structurally identical to the legacy
// codec.Registry interface (RegisterType only).
type Registry = zap_codec.Registry
// LinearCodec is the linearcodec.Codec surface (Registry +
// SkipRegistrations). Several VMs need the SkipRegistrations method on
// their per-version codec, so the alias exposes the concrete linearcodec
// type rather than just codec.Registry.
type LinearCodec = linearcodec.Codec
// LinearCodec is the union of Registry + Codec + SkipRegistrations.
// Used by VMs that need SkipRegistrations on their per-version codec
// to preserve historical type-id slot layouts (Apricot / Banff /
// Durango / Quasar registration sequences).
//
// Despite the name, this codec is backed by luxfi/codec/zapcodec — the
// "Linear" refers to LINEAR TYPE-ID ASSIGNMENT, not to the legacy
// linearcodec big-endian wire layout.
type LinearCodec = zap_codec.LinearCodec
// ZAPCodec is the zapcodec.Codec surface used by post-cutover wire
// layouts (platformvm V2). Same shape as LinearCodec; different wire
// encoding.
type ZAPCodec = zapcodec.Codec
// ZAPCodec is an explicit alias for the same zapcodec-backed Codec
// surface — used by post-cutover wire layouts (currently platformvm
// txs V2) that want to emphasise the ZAP-native wire layout. Same
// backing type as LinearCodec; the alias exists for readability.
type ZAPCodec = zap_codec.ZAPCodec
// Errs is the wrappers.Errs multi-error accumulator. Used by per-VM
// codec.go files that fan in many RegisterCodec / RegisterType calls
// under a single error tap.
type Errs = wrappers.Errs
// Errs is the multi-error accumulator used by per-VM codec.go files
// that fan in many RegisterCodec / RegisterType calls under a single
// error tap.
type Errs = zap_codec.Errs
// Packer re-exports wrappers.Packer for VM tests that drive
// Packer is the wire-byte packer used by VM tests that drive
// MarshalInto / UnmarshalFrom byte streams directly.
type Packer = wrappers.Packer
type Packer = zap_codec.Packer
// VersionSize is the on-wire length of the codec-version prefix
// (codec.VersionSize == 2). VM fee-complexity calculations subtract
// this from observed byte sizes to isolate the payload component.
const VersionSize = codec.VersionSize
// (2 bytes). VM fee-complexity calculations subtract this from
// observed byte sizes to isolate the payload component.
const VersionSize = zap_codec.VersionSize
// Sentinel errors re-exported from luxfi/codec / luxfi/codec/wrappers so
// VM packages can assert on them without importing luxfi/codec.
// Sentinel errors re-exported from proto/zap_codec so VM packages can
// assert on them without importing proto/zap_codec themselves.
var (
ErrCantPackVersion = codec.ErrCantPackVersion
ErrCantUnpackVersion = codec.ErrCantUnpackVersion
ErrUnknownVersion = codec.ErrUnknownVersion
ErrMaxSliceLenExceeded = codec.ErrMaxSliceLenExceeded
ErrMarshalNil = codec.ErrMarshalNil
ErrUnmarshalNil = codec.ErrUnmarshalNil
ErrDoesNotImplementInterface = codec.ErrDoesNotImplementInterface
ErrExtraSpace = codec.ErrExtraSpace
ErrCantPackVersion = zap_codec.ErrCantPackVersion
ErrCantUnpackVersion = zap_codec.ErrCantUnpackVersion
ErrUnknownVersion = zap_codec.ErrUnknownVersion
ErrMaxSliceLenExceeded = zap_codec.ErrMaxSliceLenExceeded
ErrMarshalNil = zap_codec.ErrMarshalNil
ErrUnmarshalNil = zap_codec.ErrUnmarshalNil
ErrDoesNotImplementInterface = zap_codec.ErrDoesNotImplementInterface
ErrExtraSpace = zap_codec.ErrExtraSpace
ErrInsufficientLength = wrappers.ErrInsufficientLength
ErrInsufficientLength = zap_codec.ErrInsufficientLength
)
// LongLen re-exports wrappers.LongLen (the on-wire length of a uint64
// — 8 bytes). Used by index code to size cursor buffers.
const LongLen = wrappers.LongLen
// LongLen is the on-wire length of a uint64 (8 bytes). Used by index
// code to size cursor buffers.
const LongLen = zap_codec.LongLen
// IntLen re-exports wrappers.IntLen (the on-wire length of a uint32
// — 4 bytes). Used by p2p response-size accounting code.
const IntLen = wrappers.IntLen
// IntLen is the on-wire length of a uint32 (4 bytes). Used by p2p
// response-size accounting code.
const IntLen = zap_codec.IntLen
// ShortLen re-exports wrappers.ShortLen (the on-wire length of a uint16
// — 2 bytes).
const ShortLen = wrappers.ShortLen
// ShortLen is the on-wire length of a uint16 (2 bytes).
const ShortLen = zap_codec.ShortLen
// ByteLen re-exports wrappers.ByteLen (1).
const ByteLen = wrappers.ByteLen
// ByteLen is the on-wire length of a uint8 (1 byte).
const ByteLen = zap_codec.ByteLen
// BoolLen re-exports wrappers.BoolLen (1).
const BoolLen = wrappers.BoolLen
// BoolLen is the on-wire length of a bool (1 byte).
const BoolLen = zap_codec.BoolLen
// NewLinearCodec returns a fresh linearcodec-backed Codec instance with
// the default tag set. Mirrors linearcodec.NewDefault().
// NewLinearCodec returns a fresh ZAP-native Codec instance with the
// default ("serialize") struct tag. The "Linear" name refers to
// LINEAR TYPE-ID ASSIGNMENT (sequential ids assigned in registration
// order), NOT to the legacy linearcodec big-endian wire format.
func NewLinearCodec() LinearCodec {
return linearcodec.NewDefault()
return zap_codec.NewLinearCodec()
}
// NewLinearCodecWithTags returns a fresh linearcodec.Codec with the
// supplied struct-tag names. Mirrors linearcodec.New([]string{tag...}).
// Used by the metadata codec wiring where v0:"true" / v1:"true" tags
// select per-version field sets.
// NewLinearCodecWithTags returns a fresh ZAP-native Codec instance
// that honours the supplied struct-tag names. Used by the metadata
// codec wiring where v0:"true" / v1:"true" tags select per-version
// field sets.
func NewLinearCodecWithTags(tags ...string) LinearCodec {
return linearcodec.New(tags)
return zap_codec.NewLinearCodecWithTags(tags...)
}
// NewZAPCodec returns a fresh zapcodec-backed Codec instance with the
// default tag set. Mirrors zapcodec.NewDefault(). Used by post-cutover
// wire formats (currently platformvm txs V2).
// NewZAPCodec returns a fresh ZAP-native Codec instance. Alias for
// NewLinearCodec — both return the same zapcodec-backed Codec; the
// name exists for call sites that want to emphasise the ZAP-native
// wire layout (e.g. platformvm txs V2).
func NewZAPCodec() ZAPCodec {
return zapcodec.NewDefault()
return zap_codec.NewZAPCodec()
}
// NewDefaultManager returns a fresh codec.Manager with the default wire
// payload size. Mirrors codec.NewDefaultManager().
// NewDefaultManager returns a fresh multi-version Manager with the
// default 1 MiB wire-payload size.
func NewDefaultManager() Manager {
return codec.NewDefaultManager()
return zap_codec.NewDefaultManager()
}
// NewManager returns a fresh codec.Manager with the supplied max wire
// payload size. Mirrors codec.NewManager(maxSize).
// NewManager returns a fresh multi-version Manager with the supplied
// max wire-payload size.
func NewManager(maxSize uint64) Manager {
return codec.NewManager(maxSize)
return zap_codec.NewManager(maxSize)
}
// NewMaxInt32Manager returns a fresh codec.Manager sized for
// NewMaxInt32Manager returns a fresh multi-version Manager sized for
// genesis-style blobs (math.MaxInt32 budget). VM genesis codec wiring
// reaches for this rather than re-deriving the budget at every call
// site.
func NewMaxInt32Manager() Manager {
return codec.NewManager(math.MaxInt32)
return zap_codec.NewMaxInt32Manager()
}
// NewMaxIntManager returns a fresh codec.Manager sized for warp /
// proposervm-block style payloads (math.MaxInt budget — effectively
// unbounded). The p2p layer caps real-world wire sizes well below this.
// NewMaxIntManager returns a fresh multi-version Manager sized for
// warp / proposervm-block style payloads (math.MaxInt budget —
// effectively unbounded). The p2p layer caps real-world wire sizes
// well below this.
func NewMaxIntManager() Manager {
return codec.NewManager(math.MaxInt)
return zap_codec.NewManager(uint64(math.MaxInt))
}
+101 -12
View File
@@ -1,24 +1,113 @@
// Copyright (C) 2019-2026, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// Package pcodecsmock re-exports luxfi/codec/codecmock so node/vms test
// files can mock codec.Manager via pcodecsmock.NewManager(ctrl) without
// importing luxfi/codec directly. Wave 2D of the codec rip (#101).
// Package pcodecsmock provides a gomock-driven mock of the
// pcodecs.Manager interface (= proto/zap_codec.MultiManager) so
// node/vms test files can program codec expectations without
// importing proto/zap_codec or luxfi/codec directly.
//
// Wave 2G-Internal of the codec rip (#101) replaces the previous
// re-export of luxfi/codec/codecmock with an in-tree mock of the
// proto/zap_codec.MultiManager interface. The mock satisfies
// pcodecs.Manager by shape — RegisterCodec / Marshal / Unmarshal /
// Size — and is independent of the underlying codec wire format.
package pcodecsmock
import (
"go.uber.org/mock/gomock"
"reflect"
"github.com/luxfi/codec/codecmock"
"github.com/luxfi/proto/zap_codec"
gomock "go.uber.org/mock/gomock"
)
// Manager is the codecmock.Manager mock — a gomock-generated double for
// codec.Manager. Re-exported as pcodecsmock.Manager so test files don't
// pull in luxfi/codec/codecmock directly.
type Manager = codecmock.Manager
// Compile-time check: Manager satisfies zap_codec.MultiManager (the
// interface pcodecs.Manager aliases). Keeps the mock in sync with the
// underlying interface — any new method on MultiManager fails this
// assertion until the mock is updated.
var _ zap_codec.MultiManager = (*Manager)(nil)
// NewManager builds a fresh Manager mock against the supplied controller.
// Mirrors codecmock.NewManager.
// Manager is the gomock-driven mock of pcodecs.Manager (=
// zap_codec.MultiManager). Tests reach for pcodecsmock.NewManager(ctrl)
// to obtain a mock that satisfies pcodecs.Manager by shape.
type Manager struct {
ctrl *gomock.Controller
recorder *ManagerRecorder
}
// ManagerRecorder is the gomock recorder for Manager. Tests program
// expectations via mock.EXPECT().<Method>(...).Return(...).
type ManagerRecorder struct {
mock *Manager
}
// NewManager constructs a fresh Manager mock against the supplied
// gomock controller.
func NewManager(ctrl *gomock.Controller) *Manager {
return codecmock.NewManager(ctrl)
m := &Manager{ctrl: ctrl}
m.recorder = &ManagerRecorder{mock: m}
return m
}
// EXPECT returns the recorder so tests can program expectations.
func (m *Manager) EXPECT() *ManagerRecorder {
return m.recorder
}
// RegisterCodec mocks the corresponding MultiManager method.
func (m *Manager) RegisterCodec(version uint16, codec zap_codec.Codec) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RegisterCodec", version, codec)
ret0, _ := ret[0].(error)
return ret0
}
// RegisterCodec expectation.
func (mr *ManagerRecorder) RegisterCodec(version, codec any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterCodec", reflect.TypeOf((*Manager)(nil).RegisterCodec), version, codec)
}
// Marshal mocks the corresponding MultiManager method.
func (m *Manager) Marshal(version uint16, source interface{}) ([]byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Marshal", version, source)
ret0, _ := ret[0].([]byte)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Marshal expectation.
func (mr *ManagerRecorder) Marshal(version, source any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Marshal", reflect.TypeOf((*Manager)(nil).Marshal), version, source)
}
// Unmarshal mocks the corresponding MultiManager method.
func (m *Manager) Unmarshal(source []byte, destination interface{}) (uint16, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Unmarshal", source, destination)
ret0, _ := ret[0].(uint16)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Unmarshal expectation.
func (mr *ManagerRecorder) Unmarshal(source, destination any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Unmarshal", reflect.TypeOf((*Manager)(nil).Unmarshal), source, destination)
}
// Size mocks the corresponding MultiManager method.
func (m *Manager) Size(version uint16, value interface{}) (int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Size", version, value)
ret0, _ := ret[0].(int)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Size expectation.
func (mr *ManagerRecorder) Size(version, value any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Size", reflect.TypeOf((*Manager)(nil).Size), version, value)
}