Files
Hanzo AI b9e41288cb initial commit: extract ZAP-native codec from luxfi/codec
Wave 2G-Archive extracted github.com/luxfi/codec/zapcodec into its
own top-level module so consumers (proto/zap_codec at the canonical
wallet codec construction site) can depend on it without pulling in
the soon-to-be-archived luxfi/codec module.

Self-contained design:
  - own sentinel errors (errors.go)
  - embedded struct-fielder (struct_fielder.go, lifted from codec/reflectcodec)
  - own packer (packer.go, local little-endian implementation)
  - external dependency only on luxfi/utils/wrappers for the cross-module Packer type

Wire format is byte-identical to codec/zapcodec — extraction is a
code-level move, not a wire-format change.

Migrated callers:
  - github.com/luxfi/proto/zap_codec (v1.3.0+)
  - github.com/luxfi/genesis/builder (post v1.13.12)
2026-06-06 05:46:22 -07:00

3.7 KiB

zapcodec — ZAP-native little-endian reflection codec

What this module is

github.com/luxfi/zapcodec is the standalone reflection-driven codec that emits the ZAP-native little-endian wire layout consumed by proto/p, proto/x, proto/p/warp, and the proto/zap_codec Manager wired into the SDK wallet.

It originated inside github.com/luxfi/codec (as codec/zapcodec) and was extracted into its own top-level module by the Wave 2G-Archive sweep once every production caller of luxfi/codec had been migrated away. The codec module itself is archived at tag v1.1.5; any historical bench fixture or test that wants to compare against the legacy linearcodec output pins that frozen tag.

Wire format

Field shape Encoding
uint8/int8/bool 1 byte
uint16/int16 2 bytes, little-endian
uint32/int32 4 bytes, little-endian
uint64/int64 8 bytes, little-endian
string uint16 LE length prefix + UTF-8 body
[]byte uint32 LE length prefix + raw bytes
[N]byte N raw bytes, no prefix
[]T (T ≠ byte) uint32 LE length prefix + N marshalled elements
[N]T (T ≠ byte) N marshalled elements, no prefix
struct fields emitted in serialize:"true" declaration order
interface uint32 LE registered-type-id + concrete value
map[K]V uint32 LE entry count + key-sorted entries
*T the marshalled T (no nil sentinel — nil is rejected)

Slice/map length prefixes cap at math.MaxInt32. Interface registration is sequential — RegisterType assigns IDs 0, 1, 2, … in call order. SkipRegistrations(n) bumps the counter by n without registering, so callers can preserve historical slot layouts during a migration.

API

import (
    "github.com/luxfi/zapcodec"
    "github.com/luxfi/utils/wrappers"
)

c := zapcodec.NewDefault() // honours `serialize:"true"`
_ = c.RegisterType(&MyConcrete{})

p := &wrappers.Packer{MaxSize: 1 << 20}
_ = c.MarshalInto(value, p)
// p.Bytes[:p.Offset] is the wire payload (no outer version prefix)

q := &wrappers.Packer{Bytes: p.Bytes[:p.Offset], MaxSize: 1 << 20}
var out MyType
_ = c.UnmarshalFrom(q, &out)

For the canonical version-prefix outer layer the SDK wallet / proto consumers use, see github.com/luxfi/proto/zap_codec.NewVersionedManager.

Module boundary

  • No Manager type here. Callers compose the version-prefix outer layer themselves. The canonical Manager wrapper lives at proto/zap_codec.
  • No comparative tests here. Head-to-head benches vs linearcodec live at bench/modes/zap_vs_codec. The standalone module is testable without pulling in the archived codec module.
  • Single external dependency: luxfi/utils/wrappers. That's the canonical home of the Packer type that crosses module boundaries on MarshalInto/UnmarshalFrom. Everything else (sentinels, struct-field discovery, interface dispatch) is internal to this module.

History

Wave Outcome
2A proto/p, proto/x deleted codec.Manager — wire format moved to ZAP-native
2D node/vms/* funneled through node/vms/pcodecs (codec.Manager type alias)
2E vm/chains/atomic deleted codec — hand-rolled big-endian binary
2F codec/wrappers → luxfi/utils/wrappers; codec/jsonrpc → luxfi/utils/json; codec/hierarchycodec deleted
2G-Wallet proto v1.2.1 + sdk v1.17.5 — proto/zap_codec canonical site established; wallet migrated
2G-Genesis genesis v1.13.12 — genesis builder ZAP-native via staging shim
2G-Internal proto v1.3.0 + node 1201692215 + coreth 7f195c239 — pcodecs + test mocks + secpfx migrated
2G-Archive codec/zapcodec → luxfi/zapcodec; codec module archived at v1.1.5