mirror of
https://github.com/luxfi/utxo.git
synced 2026-10-30 15:13:57 +00:00
Adds github.com/luxfi/utxo/wire package + per-fx wire.go adapters so
that luxfi/node's vms/{platformvm,xvm}/txs/codec.go can be deleted.
wire/ package mirrors luxfi/node/vms/wire — every fxs primitive carries
a (TypeKind, ShapeKind) discriminator pair on its wire envelope, then
a ZAP message describing its fields. Decomposes the legacy
codec.Manager slot map (which braided "fx family" and "primitive shape"
into a single dense uint32 slot id) into two orthogonal 1-byte tags.
PQ-specific schemas (pq_output_owners, pq_transfer_output,
pq_mint_output) handle the mldsafx/slhdsafx case where addresses are
full PQ pubkeys (1312-2592 bytes) rather than 20-byte hashed ShortIDs.
The wire layer is stride-agnostic — the per-fx wire.go resolves
SecurityLevel → pubkey stride before parsing.
Per-fx wire.go adapters provide (value T).Bytes() []byte (Go type →
wire envelope) and Wrap*(b []byte) (*T, error) (wire envelope → Go
type). The Initialize(vm)/codec.Manager.RegisterType chain stays in
place pending downstream coordination; this commit gets the wire/
package + adapters in so consumer agents (platformvm/warp,
platformvm/state, xvm) can pin a SHA and start their migrations.
UTXO.WireBytes() builds the outer envelope by calling the polymorphic
Out's Bytes() (any fxs primitive implementing wireSerializable).
WrapUTXOBytes(b) parses the outer envelope; the inner output is
dispatched by the caller via OutputDiscriminator() → fx-package
WrapTransferOutput / WrapMintOutput / WrapAttestationOutput.
Tests: 35 round-trip tests across 9 packages. go vet clean. go test
-race clean. gofmt clean.
Activation: 2025-12-25T16:20:00-08:00 (unix 1766708400). No
backwards compat — pre-activation legacy codec blobs are a
protocol-violation reject after activation.
88 lines
2.5 KiB
Go
88 lines
2.5 KiB
Go
// Copyright (C) 2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package bls12381fx
|
|
|
|
import (
|
|
"github.com/luxfi/utxo/wire"
|
|
)
|
|
|
|
// TypeKind is the wire-level discriminator for every bls12381fx primitive's
|
|
// wire envelope. bls12381fx is attestation-only: AttestationOutput,
|
|
// AttestationInput, Credential — no transfer or mint primitives.
|
|
const TypeKind = wire.TypeKindBLS12381
|
|
|
|
// Bytes returns the ZAP-native wire envelope for this AttestationOutput.
|
|
// Envelope = (TypeKindBLS12381, ShapeKindAttestationOut, ZAP message).
|
|
func (out *AttestationOutput) Bytes() []byte {
|
|
return wire.NewAttestationOutput(wire.AttestationOutputInput{
|
|
AttestedHash: out.AttestedHash,
|
|
Threshold: out.Threshold,
|
|
PubKeys: out.PubKeys,
|
|
})
|
|
}
|
|
|
|
// WrapAttestationOutput parses a wire envelope into a fresh
|
|
// AttestationOutput.
|
|
func WrapAttestationOutput(b []byte) (*AttestationOutput, error) {
|
|
v, err := wire.WrapAttestationOutput(b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &AttestationOutput{
|
|
AttestedHash: v.AttestedHash(),
|
|
Threshold: v.Threshold(),
|
|
PubKeys: v.PubKeys(),
|
|
}, nil
|
|
}
|
|
|
|
// Bytes returns the ZAP-native wire envelope for this AttestationInput.
|
|
// Envelope = (TypeKindBLS12381, ShapeKindAttestationIn, ZAP message).
|
|
func (in *AttestationInput) Bytes() []byte {
|
|
return wire.NewAttestationInput(wire.AttestationInputInput{
|
|
SignerBitmap: in.Signers,
|
|
})
|
|
}
|
|
|
|
// WrapAttestationInput parses a wire envelope into a fresh
|
|
// AttestationInput.
|
|
func WrapAttestationInput(b []byte) (*AttestationInput, error) {
|
|
v, err := wire.WrapAttestationInput(b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
bitmap := v.SignerBitmap()
|
|
signers := make([]byte, len(bitmap))
|
|
copy(signers, bitmap)
|
|
return &AttestationInput{Signers: signers}, nil
|
|
}
|
|
|
|
// Bytes returns the ZAP-native wire envelope for this Credential.
|
|
// bls12381fx Credentials carry a single aggregate G2 signature (96 bytes);
|
|
// there is no notion of "per-signer signature" in BLS aggregate semantics.
|
|
func (cr *Credential) Bytes() []byte {
|
|
return wire.NewCredential(wire.CredentialInput{
|
|
TypeKind: TypeKind,
|
|
SecurityLevel: 0,
|
|
Signatures: cr.AggSig[:],
|
|
})
|
|
}
|
|
|
|
// WrapCredential parses a wire envelope into a fresh Credential.
|
|
func WrapCredential(b []byte) (*Credential, error) {
|
|
v, err := wire.WrapCredential(b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if v.TypeKind() != TypeKind {
|
|
return nil, wire.ErrWrongTypeKind
|
|
}
|
|
out := &Credential{}
|
|
sig := v.SignatureBytes()
|
|
if len(sig) != SigLen {
|
|
return nil, ErrWrongAggSigLen
|
|
}
|
|
copy(out.AggSig[:], sig)
|
|
return out, nil
|
|
}
|