The shapes every chain answers in state their own ZAP wire

A JSONTxID, a GetTxArgs, a GetBlockArgs and the ids inside them are what
P and X reply with, and each holds an ids.ID — [32]byte, bytes_fixed[32]
on the wire, which the derived codec refuses to carry. So none of those
calls could cross the op-call plane. zap_gen.go is generated by
zip.Codecs from the same layout the plane encodes against, and the JSON
edge does not move: encoding/json reads the tags and knows nothing about
a ZAP codec.
This commit is contained in:
2026-08-29 18:58:36 -07:00
parent 9098761124
commit 1de772ad2d
7 changed files with 1990 additions and 0 deletions
+660
View File
@@ -0,0 +1,660 @@
// Code generated by zip; DO NOT EDIT.
package types
import (
"encoding/binary"
"encoding/json"
"fmt"
"strings"
formatting "github.com/luxfi/formatting"
zap "github.com/zap-proto/go"
)
// ---- EmptyReply --------------------------------------------------------
const (
emptyReplySize = 0
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*EmptyReply)(nil)
// MarshalZAP writes EmptyReply from constant offsets.
func (x *EmptyReply) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(emptyReplySize + 256)
ob := b.StartObject(emptyReplySize)
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads EmptyReply out of the buffer that arrived.
func (x *EmptyReply) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("EmptyReply: %w", err)
}
_ = m
return nil
}
// ---- FormattedTx -------------------------------------------------------
const (
formattedTxTxAt = 0
formattedTxEncodingAt = 8
formattedTxSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*FormattedTx)(nil)
// MarshalZAP writes FormattedTx from constant offsets.
func (x *FormattedTx) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(formattedTxSize + 256)
ob := b.StartObject(formattedTxSize)
ob.SetText(formattedTxTxAt, string(x.Tx))
ob.SetUint8(formattedTxEncodingAt, uint8(x.Encoding))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads FormattedTx out of the buffer that arrived.
func (x *FormattedTx) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("FormattedTx: %w", err)
}
o := m.Root()
x.Tx = string(strings.Clone(o.Text(formattedTxTxAt)))
x.Encoding = formatting.Encoding(o.Uint8(formattedTxEncodingAt))
return nil
}
// ---- GetBlockArgs ------------------------------------------------------
const (
getBlockArgsBlockIDAt = 0
getBlockArgsEncodingAt = 32
getBlockArgsSize = 40
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GetBlockArgs)(nil)
// MarshalZAP writes GetBlockArgs from constant offsets.
func (x *GetBlockArgs) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(getBlockArgsSize + 256)
ob := b.StartObject(getBlockArgsSize)
ob.SetBytesFixed(getBlockArgsBlockIDAt, x.BlockID[:])
ob.SetUint8(getBlockArgsEncodingAt, uint8(x.Encoding))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GetBlockArgs out of the buffer that arrived.
func (x *GetBlockArgs) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GetBlockArgs: %w", err)
}
o := m.Root()
copy(x.BlockID[:], o.BytesFixed(getBlockArgsBlockIDAt, 32))
x.Encoding = formatting.Encoding(o.Uint8(getBlockArgsEncodingAt))
return nil
}
// ---- GetBlockByHeightArgs ----------------------------------------------
const (
getBlockByHeightArgsHeightAt = 0
getBlockByHeightArgsEncodingAt = 8
getBlockByHeightArgsSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GetBlockByHeightArgs)(nil)
// MarshalZAP writes GetBlockByHeightArgs from constant offsets.
func (x *GetBlockByHeightArgs) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(getBlockByHeightArgsSize + 256)
ob := b.StartObject(getBlockByHeightArgsSize)
ob.SetUint64(getBlockByHeightArgsHeightAt, uint64(x.Height))
ob.SetUint8(getBlockByHeightArgsEncodingAt, uint8(x.Encoding))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GetBlockByHeightArgs out of the buffer that arrived.
func (x *GetBlockByHeightArgs) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GetBlockByHeightArgs: %w", err)
}
o := m.Root()
x.Height = Uint64(o.Uint64(getBlockByHeightArgsHeightAt))
x.Encoding = formatting.Encoding(o.Uint8(getBlockByHeightArgsEncodingAt))
return nil
}
// ---- GetBlockResponse --------------------------------------------------
const (
getBlockResponseBlockAt = 0
getBlockResponseEncodingAt = 8
getBlockResponseSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GetBlockResponse)(nil)
// MarshalZAP writes GetBlockResponse from constant offsets.
func (x *GetBlockResponse) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(getBlockResponseSize + 256)
ob := b.StartObject(getBlockResponseSize)
ob.SetBytes(getBlockResponseBlockAt, []byte(x.Block))
ob.SetUint8(getBlockResponseEncodingAt, uint8(x.Encoding))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GetBlockResponse out of the buffer that arrived.
func (x *GetBlockResponse) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GetBlockResponse: %w", err)
}
o := m.Root()
x.Block = json.RawMessage(append([]byte(nil), o.Bytes(getBlockResponseBlockAt)...))
x.Encoding = formatting.Encoding(o.Uint8(getBlockResponseEncodingAt))
return nil
}
// ---- GetHeightResponse -------------------------------------------------
const (
getHeightResponseHeightAt = 0
getHeightResponseSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GetHeightResponse)(nil)
// MarshalZAP writes GetHeightResponse from constant offsets.
func (x *GetHeightResponse) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(getHeightResponseSize + 256)
ob := b.StartObject(getHeightResponseSize)
ob.SetUint64(getHeightResponseHeightAt, uint64(x.Height))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GetHeightResponse out of the buffer that arrived.
func (x *GetHeightResponse) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GetHeightResponse: %w", err)
}
o := m.Root()
x.Height = Uint64(o.Uint64(getHeightResponseHeightAt))
return nil
}
// ---- GetTxArgs ---------------------------------------------------------
const (
getTxArgsTxIDAt = 0
getTxArgsEncodingAt = 32
getTxArgsSize = 40
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GetTxArgs)(nil)
// MarshalZAP writes GetTxArgs from constant offsets.
func (x *GetTxArgs) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(getTxArgsSize + 256)
ob := b.StartObject(getTxArgsSize)
ob.SetBytesFixed(getTxArgsTxIDAt, x.TxID[:])
ob.SetUint8(getTxArgsEncodingAt, uint8(x.Encoding))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GetTxArgs out of the buffer that arrived.
func (x *GetTxArgs) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GetTxArgs: %w", err)
}
o := m.Root()
copy(x.TxID[:], o.BytesFixed(getTxArgsTxIDAt, 32))
x.Encoding = formatting.Encoding(o.Uint8(getTxArgsEncodingAt))
return nil
}
// ---- GetTxReply --------------------------------------------------------
const (
getTxReplyTxAt = 0
getTxReplyEncodingAt = 8
getTxReplySize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GetTxReply)(nil)
// MarshalZAP writes GetTxReply from constant offsets.
func (x *GetTxReply) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(getTxReplySize + 256)
ob := b.StartObject(getTxReplySize)
ob.SetBytes(getTxReplyTxAt, []byte(x.Tx))
ob.SetUint8(getTxReplyEncodingAt, uint8(x.Encoding))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GetTxReply out of the buffer that arrived.
func (x *GetTxReply) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GetTxReply: %w", err)
}
o := m.Root()
x.Tx = json.RawMessage(append([]byte(nil), o.Bytes(getTxReplyTxAt)...))
x.Encoding = formatting.Encoding(o.Uint8(getTxReplyEncodingAt))
return nil
}
// ---- GetUTXOsArgs ------------------------------------------------------
const (
getUTXOsArgsAddressesAt = 0
getUTXOsArgsSourceChainAt = 8
getUTXOsArgsLimitAt = 16
getUTXOsArgsStartIndexAt = 24
getUTXOsArgsEncodingAt = 32
getUTXOsArgsSize = 40
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GetUTXOsArgs)(nil)
// MarshalZAP writes GetUTXOsArgs from constant offsets.
func (x *GetUTXOsArgs) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(getUTXOsArgsSize + 256)
addressesAt, addressesN := 0, len(x.Addresses)
if addressesN > 0 {
var blob []byte
for i := range x.Addresses {
enc := []byte(x.Addresses[i])
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
addressesAt = b.WriteBytes(blob)
}
ob := b.StartObject(getUTXOsArgsSize)
ob.SetText(getUTXOsArgsSourceChainAt, string(x.SourceChain))
ob.SetUint32(getUTXOsArgsLimitAt, uint32(x.Limit))
innerStartIndex, err := x.StartIndex.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(getUTXOsArgsStartIndexAt, innerStartIndex)
ob.SetUint8(getUTXOsArgsEncodingAt, uint8(x.Encoding))
if addressesN > 0 {
ob.SetList(getUTXOsArgsAddressesAt, addressesAt, addressesN)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GetUTXOsArgs out of the buffer that arrived.
func (x *GetUTXOsArgs) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GetUTXOsArgs: %w", err)
}
o := m.Root()
if l := o.List(getUTXOsArgsAddressesAt); l.Len() > 0 {
rows := make([]string, l.Len())
for i := range rows {
rows[i] = string(l.BytesAt(i))
}
x.Addresses = rows
}
x.SourceChain = string(strings.Clone(o.Text(getUTXOsArgsSourceChainAt)))
x.Limit = Uint32(o.Uint32(getUTXOsArgsLimitAt))
if raw := o.Bytes(getUTXOsArgsStartIndexAt); len(raw) > 0 {
if err := x.StartIndex.UnmarshalZAP(raw); err != nil {
return err
}
}
x.Encoding = formatting.Encoding(o.Uint8(getUTXOsArgsEncodingAt))
return nil
}
// ---- GetUTXOsReply -----------------------------------------------------
const (
getUTXOsReplyNumFetchedAt = 0
getUTXOsReplyUTXOsAt = 8
getUTXOsReplyEndIndexAt = 16
getUTXOsReplyEncodingAt = 24
getUTXOsReplySize = 32
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*GetUTXOsReply)(nil)
// MarshalZAP writes GetUTXOsReply from constant offsets.
func (x *GetUTXOsReply) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(getUTXOsReplySize + 256)
uTXOsAt, uTXOsN := 0, len(x.UTXOs)
if uTXOsN > 0 {
var blob []byte
for i := range x.UTXOs {
enc := []byte(x.UTXOs[i])
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
uTXOsAt = b.WriteBytes(blob)
}
ob := b.StartObject(getUTXOsReplySize)
ob.SetUint64(getUTXOsReplyNumFetchedAt, uint64(x.NumFetched))
innerEndIndex, err := x.EndIndex.MarshalZAP()
if err != nil {
return nil, err
}
ob.SetBytes(getUTXOsReplyEndIndexAt, innerEndIndex)
ob.SetUint8(getUTXOsReplyEncodingAt, uint8(x.Encoding))
if uTXOsN > 0 {
ob.SetList(getUTXOsReplyUTXOsAt, uTXOsAt, uTXOsN)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads GetUTXOsReply out of the buffer that arrived.
func (x *GetUTXOsReply) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("GetUTXOsReply: %w", err)
}
o := m.Root()
x.NumFetched = Uint64(o.Uint64(getUTXOsReplyNumFetchedAt))
if l := o.List(getUTXOsReplyUTXOsAt); l.Len() > 0 {
rows := make([]string, l.Len())
for i := range rows {
rows[i] = string(l.BytesAt(i))
}
x.UTXOs = rows
}
if raw := o.Bytes(getUTXOsReplyEndIndexAt); len(raw) > 0 {
if err := x.EndIndex.UnmarshalZAP(raw); err != nil {
return err
}
}
x.Encoding = formatting.Encoding(o.Uint8(getUTXOsReplyEncodingAt))
return nil
}
// ---- Index -------------------------------------------------------------
const (
indexAddressAt = 0
indexUTXOAt = 8
indexSize = 16
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*Index)(nil)
// MarshalZAP writes Index from constant offsets.
func (x *Index) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(indexSize + 256)
ob := b.StartObject(indexSize)
ob.SetText(indexAddressAt, string(x.Address))
ob.SetText(indexUTXOAt, string(x.UTXO))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads Index out of the buffer that arrived.
func (x *Index) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("Index: %w", err)
}
o := m.Root()
x.Address = string(strings.Clone(o.Text(indexAddressAt)))
x.UTXO = string(strings.Clone(o.Text(indexUTXOAt)))
return nil
}
// ---- JSONAddress -------------------------------------------------------
const (
jSONAddressAddressAt = 0
jSONAddressSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*JSONAddress)(nil)
// MarshalZAP writes JSONAddress from constant offsets.
func (x *JSONAddress) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(jSONAddressSize + 256)
ob := b.StartObject(jSONAddressSize)
ob.SetText(jSONAddressAddressAt, string(x.Address))
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads JSONAddress out of the buffer that arrived.
func (x *JSONAddress) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("JSONAddress: %w", err)
}
o := m.Root()
x.Address = string(strings.Clone(o.Text(jSONAddressAddressAt)))
return nil
}
// ---- JSONAddresses -----------------------------------------------------
const (
jSONAddressesAddressesAt = 0
jSONAddressesSize = 8
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*JSONAddresses)(nil)
// MarshalZAP writes JSONAddresses from constant offsets.
func (x *JSONAddresses) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(jSONAddressesSize + 256)
addressesAt, addressesN := 0, len(x.Addresses)
if addressesN > 0 {
var blob []byte
for i := range x.Addresses {
enc := []byte(x.Addresses[i])
var n [4]byte
binary.LittleEndian.PutUint32(n[:], uint32(len(enc)))
blob = append(blob, n[:]...)
blob = append(blob, enc...)
}
addressesAt = b.WriteBytes(blob)
}
ob := b.StartObject(jSONAddressesSize)
if addressesN > 0 {
ob.SetList(jSONAddressesAddressesAt, addressesAt, addressesN)
}
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads JSONAddresses out of the buffer that arrived.
func (x *JSONAddresses) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("JSONAddresses: %w", err)
}
o := m.Root()
if l := o.List(jSONAddressesAddressesAt); l.Len() > 0 {
rows := make([]string, l.Len())
for i := range rows {
rows[i] = string(l.BytesAt(i))
}
x.Addresses = rows
}
return nil
}
// ---- JSONTxID ----------------------------------------------------------
const (
jSONTxIDTxIDAt = 0
jSONTxIDSize = 32
)
var _ interface {
MarshalZAP() ([]byte, error)
UnmarshalZAP([]byte) error
} = (*JSONTxID)(nil)
// MarshalZAP writes JSONTxID from constant offsets.
func (x *JSONTxID) MarshalZAP() ([]byte, error) {
if x == nil {
return nil, nil
}
b := zap.NewBuilder(jSONTxIDSize + 256)
ob := b.StartObject(jSONTxIDSize)
ob.SetBytesFixed(jSONTxIDTxIDAt, x.TxID[:])
ob.FinishAsRoot()
return b.Finish(), nil
}
// UnmarshalZAP reads JSONTxID out of the buffer that arrived.
func (x *JSONTxID) UnmarshalZAP(data []byte) error {
if x == nil || len(data) == 0 {
return nil
}
m, err := zap.Parse(data)
if err != nil {
return fmt.Errorf("JSONTxID: %w", err)
}
o := m.Root()
copy(x.TxID[:], o.BytesFixed(jSONTxIDTxIDAt, 32))
return nil
}
+77
View File
@@ -0,0 +1,77 @@
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package types
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/formatting"
"github.com/luxfi/ids"
)
// These are the shapes every chain's RPC answers in, and each of them holds an
// ids.ID — [32]byte, which is bytes_fixed[32] on the ZAP wire and what a DERIVED
// codec refuses to carry. zap_gen.go is why they cross; this is that the id
// arrives whole and that the JSON mainnet answers on did not move.
func TestTheIDsCrossAndTheJSONDoesNotMove(t *testing.T) {
id := ids.ID{0: 0xf0, 15: 0x5a, 31: 0x0d}
t.Run("JSONTxID", func(t *testing.T) {
require := require.New(t)
sent := JSONTxID{TxID: id}
enc, err := sent.MarshalZAP()
require.NoError(err)
var back JSONTxID
require.NoError(back.UnmarshalZAP(enc))
require.Equal(sent, back)
is, err := json.Marshal(sent)
require.NoError(err)
was, err := json.Marshal(struct {
TxID ids.ID `json:"txID"`
}{id})
require.NoError(err)
require.Equal(string(was), string(is))
})
t.Run("GetTxArgs", func(t *testing.T) {
require := require.New(t)
sent := GetTxArgs{TxID: id, Encoding: formatting.Hex}
enc, err := sent.MarshalZAP()
require.NoError(err)
var back GetTxArgs
require.NoError(back.UnmarshalZAP(enc))
require.Equal(sent, back)
})
t.Run("GetBlockArgs", func(t *testing.T) {
require := require.New(t)
sent := GetBlockArgs{BlockID: id, Encoding: formatting.JSON}
enc, err := sent.MarshalZAP()
require.NoError(err)
var back GetBlockArgs
require.NoError(back.UnmarshalZAP(enc))
require.Equal(sent, back)
})
t.Run("GetUTXOsArgs", func(t *testing.T) {
require := require.New(t)
sent := GetUTXOsArgs{
Addresses: []string{"P-a", "P-b"},
SourceChain: "X",
Limit: 10,
Encoding: formatting.Hex,
}
sent.StartIndex.Address = "P-a"
sent.StartIndex.UTXO = "utxo"
enc, err := sent.MarshalZAP()
require.NoError(err)
var back GetUTXOsArgs
require.NoError(back.UnmarshalZAP(enc))
require.Equal(sent, back)
})
}