Files
zeekay 05e7482ac4 run on the native fleet
Adds .hanzo/workflows/cicd.yml calling the canonical pipeline and drops the
GitHub-hosted workflows it replaces. Lands here because this is where the repo
is written — git.hanzo.ai is upstream and github.com is its push mirror, so the
same change made on github.com never reaches the runner fleet.
2026-08-20 20:20:09 -07:00

1168 lines
32 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package zap
// State represents VM state values
type State uint8
const (
StateUnknown State = 0
StateStarting State = 1
StateSyncing State = 2
StateBootstrapping State = 3
StateReady State = 4
StateDegraded State = 5
StateStopping State = 6
StateStopped State = 7
)
// Error represents VM errors
type Error uint8
// The zero value carries "the call succeeded" — a reply whose Err is
// ErrorUnspecified is read as a good answer and its fields are trusted. Every
// other value names a failure, so a failure the vocabulary has no word for
// must reach the caller as ErrorInternal. Mapping it onto the zero instead
// hands back a zero-valued block under the name of success.
const (
ErrorUnspecified Error = iota
ErrorClosed
ErrorNotFound
ErrorStateSyncNotImplemented
ErrorInternal
)
// InitializeRequest contains initialization parameters.
//
// Note: the upstream upgrade-timestamp surface was ripped under the activate-
// all-implicitly directive — every chain runs the post-Granite rule-set from
// genesis, so there are no per-upgrade timestamps to ship over the wire.
type InitializeRequest struct {
NetworkID uint32
ChainID []byte
NodeID []byte
PublicKey []byte
XChainID []byte
CChainID []byte
UTXOAssetID []byte
ChainDataDir string
GenesisBytes []byte
UpgradeBytes []byte
ConfigBytes []byte
DBServerAddr string
ServerAddr string
// AtomicServerAddr is the address of a ZAP server the node bound over THIS
// chain's atomic shared-memory handle before calling Initialize. A plugin
// dials it to reach the primary network's cross-chain import/export
// primitive, which cannot be copied into the plugin's rebuilt Runtime
// because it is an interface over a live database the node owns. Same shape
// and lifetime as DBServerAddr.
//
// Empty means the node wired no shared memory for this chain. The plugin
// MUST then leave Runtime.SharedMemory nil so a settlement precompile
// reverts fail-closed rather than fabricate value.
AtomicServerAddr string
// ValidatorServerAddr is the address of a ZAP server the node bound over its
// validator state before calling Initialize. A plugin dials it to learn who
// the validators are at a P-chain height.
//
// It rides here for the same reason AtomicServerAddr does: validator state is
// an interface over live node-owned state, so it cannot be copied into the
// plugin's rebuilt Runtime. Without it a plugin-hosted VM sees a nil handle
// and can form no committee — which is why M-Chain, whose whole job is a
// threshold ceremony among validators, could never run one.
//
// Empty means the node wired no validator state for this chain. The plugin
// MUST then leave Runtime.ValidatorState nil so a committee lookup fails
// with a clear "no committee" rather than fabricating an empty set — an
// empty validator set is a quorum of nobody.
ValidatorServerAddr string
// DChainID is the D-Chain (dexvm) blockchain id, resolved node-side from the
// chain alias "D". It rides here because the plugin's Runtime has no
// BCLookup — that field is an interface onto the node's chain manager and,
// like SharedMemory, does not survive the boundary. The DEX settlement seam
// needs exactly one alias resolved, so the resolved ID is carried instead of
// proxying a whole lookup service.
//
// Empty means the network has no dexvm deployed; the settlement seam then
// stays closed rather than guess a peer.
DChainID []byte
}
// Encode serializes InitializeRequest to the buffer
func (m *InitializeRequest) Encode(buf *Buffer) {
buf.WriteUint32(m.NetworkID)
buf.WriteBytes(m.ChainID)
buf.WriteBytes(m.NodeID)
buf.WriteBytes(m.PublicKey)
buf.WriteBytes(m.XChainID)
buf.WriteBytes(m.CChainID)
buf.WriteBytes(m.UTXOAssetID)
buf.WriteString(m.ChainDataDir)
buf.WriteBytes(m.GenesisBytes)
buf.WriteBytes(m.UpgradeBytes)
buf.WriteBytes(m.ConfigBytes)
buf.WriteString(m.DBServerAddr)
buf.WriteString(m.ServerAddr)
// OPTIONAL trailing fields — see the EVOLUTION RULE on InitializeResponse.
// Appended, never inserted, so an older decoder stops after ServerAddr and
// ignores these bytes.
buf.WriteString(m.AtomicServerAddr)
buf.WriteBytes(m.DChainID)
buf.WriteString(m.ValidatorServerAddr)
}
// Decode deserializes InitializeRequest from the reader.
//
// LENGTH-TOLERANT trailing fields, the same contract InitializeResponse.Decode
// documents. AtomicServerAddr, DChainID and ValidatorServerAddr were APPENDED for
// the cross-chain
// atomic seam without bumping version.RPCChainVMProtocol, so both skew
// directions stay safe:
//
// - NEW node -> OLD plugin: the old decoder stops after ServerAddr and ignores
// the trailing bytes (ZAP frames are length-prefixed). The plugin keeps its
// nil SharedMemory and its settlements keep reverting fail-closed — the
// behavior it already had, never a silent divergence.
// - OLD node -> NEW plugin: Remaining() is 0 at these reads, so both fields
// stay zero-valued and the plugin treats the atomic capability as absent.
//
// Neither direction changes how any block executes, which is what makes this
// safe to roll one validator at a time.
func (m *InitializeRequest) Decode(r *Reader) error {
var err error
if m.NetworkID, err = r.ReadUint32(); err != nil {
return err
}
if m.ChainID, err = r.ReadBytes(); err != nil {
return err
}
if m.NodeID, err = r.ReadBytes(); err != nil {
return err
}
if m.PublicKey, err = r.ReadBytes(); err != nil {
return err
}
if m.XChainID, err = r.ReadBytes(); err != nil {
return err
}
if m.CChainID, err = r.ReadBytes(); err != nil {
return err
}
if m.UTXOAssetID, err = r.ReadBytes(); err != nil {
return err
}
if m.ChainDataDir, err = r.ReadString(); err != nil {
return err
}
if m.GenesisBytes, err = r.ReadBytes(); err != nil {
return err
}
if m.UpgradeBytes, err = r.ReadBytes(); err != nil {
return err
}
if m.ConfigBytes, err = r.ReadBytes(); err != nil {
return err
}
if m.DBServerAddr, err = r.ReadString(); err != nil {
return err
}
if m.ServerAddr, err = r.ReadString(); err != nil {
return err
}
// OPTIONAL trailing fields. A length-prefixed field costs at least its
// 4-byte count, so Remaining() < 4 ⇒ the peer predates this field; leave it
// zero-valued instead of returning io.ErrUnexpectedEOF.
if r.Remaining() >= 4 {
if m.AtomicServerAddr, err = r.ReadString(); err != nil {
return err
}
}
if r.Remaining() >= 4 {
if m.DChainID, err = r.ReadBytes(); err != nil {
return err
}
}
if r.Remaining() >= 4 {
if m.ValidatorServerAddr, err = r.ReadString(); err != nil {
return err
}
}
return nil
}
// InitializeResponse contains initialization results
type InitializeResponse struct {
LastAcceptedID []byte
LastAcceptedParentID []byte
Height uint64
Bytes []byte
Timestamp int64
// Capabilities is a bitfield of OPTIONAL cross-boundary add-ons the VM
// implements (see the Cap* constants). The node reads it once at handshake
// to decide which add-ons to wire; an unset bit → the node treats that
// capability as absent and stays on the generic path.
Capabilities uint64
}
// VM capability bits advertised in InitializeResponse.Capabilities. A VM sets a
// bit to tell the node it implements the corresponding OPTIONAL add-on that is
// NOT part of the generic ChainVM contract. Discovered at the handshake, never
// braided into ChainVM — generic VMs leave every bit clear.
const (
// CapQuasarExport: the VM tracks a Quasar (⅔-by-stake) EXPORT-FINAL height
// distinct from its reorgable local accept tip, and answers
// MsgSetQuasarFinalized / MsgQuasarHeight. Set by the C-Chain EVM; the node
// wires the consensus export-frontier observer only when this bit is set.
CapQuasarExport uint64 = 1 << 0
// CapStateSync: the VM can adopt a peer's state summary instead of replaying
// to it, and answers the six MsgStateSync*/MsgStateSummary* messages. Set by
// any VM implementing the syncable surface.
//
// The node needs this at the handshake because the alternative is asking and
// reading a refusal, and a VM that cannot answer at all is indistinguishable
// on the wire from one that answered "no". A node repairing a damaged chain
// must tell those apart: the first means find another way, the second means
// this VM chose to replay.
CapStateSync uint64 = 1 << 1
)
// Encode serializes InitializeResponse to the buffer
func (m *InitializeResponse) Encode(buf *Buffer) {
buf.WriteBytes(m.LastAcceptedID)
buf.WriteBytes(m.LastAcceptedParentID)
buf.WriteUint64(m.Height)
buf.WriteBytes(m.Bytes)
buf.WriteInt64(m.Timestamp)
buf.WriteUint64(m.Capabilities)
}
// Decode deserializes InitializeResponse from the reader.
//
// LENGTH-TOLERANT trailing field. Capabilities is OPTIONAL on the wire: it was
// APPENDED in api v1.0.16 (the Quasar-export handshake) WITHOUT bumping
// version.RPCChainVMProtocol, so a peer built before it — a stale VM plugin —
// sends a payload that ends right after Timestamp. Guarding the read on
// Remaining() lets a newer decoder read that short payload as "Capabilities = 0"
// (Nova-only, no optional add-ons) instead of failing with io.ErrUnexpectedEOF —
// exactly the v1.36.11 skew that broke every EVM Initialize with
// "zap decode initialize response: unexpected EOF". The mirror case (an OLDER
// decoder reading a NEWER payload) already works: a length-prefixed ZAP frame
// lets the old decoder stop after Timestamp and ignore the trailing bytes.
//
// EVOLUTION RULE: any FUTURE field is appended AFTER Capabilities and read the
// same way — guard each read on Remaining(), and keep Encode writing fields in
// this exact order. Never insert or reorder a field in the middle: that is a
// breaking wire change and MUST bump version.RPCChainVMProtocol.
func (m *InitializeResponse) Decode(r *Reader) error {
var err error
if m.LastAcceptedID, err = r.ReadBytes(); err != nil {
return err
}
if m.LastAcceptedParentID, err = r.ReadBytes(); err != nil {
return err
}
if m.Height, err = r.ReadUint64(); err != nil {
return err
}
if m.Bytes, err = r.ReadBytes(); err != nil {
return err
}
if m.Timestamp, err = r.ReadInt64(); err != nil {
return err
}
// OPTIONAL trailing field: absent from pre-v1.0.16 peers. Remaining() < 8
// (a uint64 is 8 bytes) ⇒ leave Capabilities at its zero value rather than
// EOF. A count of exactly 8 (or more, from an even-newer peer with further
// appended fields) ⇒ read it and ignore anything past it.
if r.Remaining() >= 8 {
if m.Capabilities, err = r.ReadUint64(); err != nil {
return err
}
}
return nil
}
// SetStateRequest contains state change request.
// State values are defined in github.com/luxfi/vm (vm.State):
//
// Unknown=0, Starting=1, Syncing=2, Bootstrapping=3,
// Ready=4, Degraded=5, Stopping=6, Stopped=7
type SetStateRequest struct {
State State
}
// Encode serializes SetStateRequest to the buffer
func (m *SetStateRequest) Encode(buf *Buffer) {
buf.WriteUint8(uint8(m.State))
}
// Decode deserializes SetStateRequest from the reader
func (m *SetStateRequest) Decode(r *Reader) error {
v, err := r.ReadUint8()
m.State = State(v)
return err
}
// SetStateResponse contains state change results
type SetStateResponse struct {
LastAcceptedID []byte
LastAcceptedParentID []byte
Height uint64
Bytes []byte
Timestamp int64
}
// Encode serializes SetStateResponse to the buffer
func (m *SetStateResponse) Encode(buf *Buffer) {
buf.WriteBytes(m.LastAcceptedID)
buf.WriteBytes(m.LastAcceptedParentID)
buf.WriteUint64(m.Height)
buf.WriteBytes(m.Bytes)
buf.WriteInt64(m.Timestamp)
}
// Decode deserializes SetStateResponse from the reader
func (m *SetStateResponse) Decode(r *Reader) error {
var err error
if m.LastAcceptedID, err = r.ReadBytes(); err != nil {
return err
}
if m.LastAcceptedParentID, err = r.ReadBytes(); err != nil {
return err
}
if m.Height, err = r.ReadUint64(); err != nil {
return err
}
if m.Bytes, err = r.ReadBytes(); err != nil {
return err
}
m.Timestamp, err = r.ReadInt64()
return err
}
// BuildBlockRequest contains block building parameters
type BuildBlockRequest struct {
PChainHeight uint64
HasPChainHeight bool
}
// Encode serializes BuildBlockRequest to the buffer
func (m *BuildBlockRequest) Encode(buf *Buffer) {
buf.WriteBool(m.HasPChainHeight)
if m.HasPChainHeight {
buf.WriteUint64(m.PChainHeight)
}
}
// Decode deserializes BuildBlockRequest from the reader
func (m *BuildBlockRequest) Decode(r *Reader) error {
var err error
if m.HasPChainHeight, err = r.ReadBool(); err != nil {
return err
}
if m.HasPChainHeight {
m.PChainHeight, err = r.ReadUint64()
}
return err
}
// BlockResponse contains block data (used by BuildBlock, ParseBlock, GetBlock)
type BlockResponse struct {
ID []byte
ParentID []byte
Bytes []byte // Zero-copy block data
Height uint64
Timestamp int64
VerifyWithContext bool
Err Error
}
// Encode serializes BlockResponse to the buffer
func (m *BlockResponse) Encode(buf *Buffer) {
buf.WriteBytes(m.ID)
buf.WriteBytes(m.ParentID)
buf.WriteBytes(m.Bytes)
buf.WriteUint64(m.Height)
buf.WriteInt64(m.Timestamp)
buf.WriteBool(m.VerifyWithContext)
buf.WriteUint8(uint8(m.Err))
}
// Decode deserializes BlockResponse from the reader
func (m *BlockResponse) Decode(r *Reader) error {
var err error
if m.ID, err = r.ReadBytes(); err != nil {
return err
}
if m.ParentID, err = r.ReadBytes(); err != nil {
return err
}
if m.Bytes, err = r.ReadBytes(); err != nil {
return err
}
if m.Height, err = r.ReadUint64(); err != nil {
return err
}
if m.Timestamp, err = r.ReadInt64(); err != nil {
return err
}
if m.VerifyWithContext, err = r.ReadBool(); err != nil {
return err
}
v, err := r.ReadUint8()
m.Err = Error(v)
return err
}
// ParseBlockRequest contains bytes to parse
type ParseBlockRequest struct {
Bytes []byte // Zero-copy input
}
// Encode serializes ParseBlockRequest to the buffer
func (m *ParseBlockRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.Bytes)
}
// Decode deserializes ParseBlockRequest from the reader
func (m *ParseBlockRequest) Decode(r *Reader) error {
var err error
m.Bytes, err = r.ReadBytes()
return err
}
// GetBlockRequest contains block ID to retrieve
type GetBlockRequest struct {
ID []byte
}
// Encode serializes GetBlockRequest to the buffer
func (m *GetBlockRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.ID)
}
// Decode deserializes GetBlockRequest from the reader
func (m *GetBlockRequest) Decode(r *Reader) error {
var err error
m.ID, err = r.ReadBytes()
return err
}
// SetPreferenceRequest contains preferred block ID
type SetPreferenceRequest struct {
ID []byte
}
// Encode serializes SetPreferenceRequest to the buffer
func (m *SetPreferenceRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.ID)
}
// Decode deserializes SetPreferenceRequest from the reader
func (m *SetPreferenceRequest) Decode(r *Reader) error {
var err error
m.ID, err = r.ReadBytes()
return err
}
// BlockVerifyRequest contains block verification parameters
type BlockVerifyRequest struct {
Bytes []byte
PChainHeight uint64
HasPChainHeight bool
}
// Encode serializes BlockVerifyRequest to the buffer
func (m *BlockVerifyRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.Bytes)
buf.WriteBool(m.HasPChainHeight)
if m.HasPChainHeight {
buf.WriteUint64(m.PChainHeight)
}
}
// Decode deserializes BlockVerifyRequest from the reader
func (m *BlockVerifyRequest) Decode(r *Reader) error {
var err error
if m.Bytes, err = r.ReadBytes(); err != nil {
return err
}
if m.HasPChainHeight, err = r.ReadBool(); err != nil {
return err
}
if m.HasPChainHeight {
m.PChainHeight, err = r.ReadUint64()
}
return err
}
// BlockVerifyResponse contains verification result
type BlockVerifyResponse struct {
Timestamp int64
}
// Encode serializes BlockVerifyResponse to the buffer
func (m *BlockVerifyResponse) Encode(buf *Buffer) {
buf.WriteInt64(m.Timestamp)
}
// Decode deserializes BlockVerifyResponse from the reader
func (m *BlockVerifyResponse) Decode(r *Reader) error {
var err error
m.Timestamp, err = r.ReadInt64()
return err
}
// BlockAcceptRequest contains block ID to accept
type BlockAcceptRequest struct {
ID []byte
}
// Encode serializes BlockAcceptRequest to the buffer
func (m *BlockAcceptRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.ID)
}
// Decode deserializes BlockAcceptRequest from the reader
func (m *BlockAcceptRequest) Decode(r *Reader) error {
var err error
m.ID, err = r.ReadBytes()
return err
}
// BlockRejectRequest contains block ID to reject
type BlockRejectRequest struct {
ID []byte
}
// Encode serializes BlockRejectRequest to the buffer
func (m *BlockRejectRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.ID)
}
// Decode deserializes BlockRejectRequest from the reader
func (m *BlockRejectRequest) Decode(r *Reader) error {
var err error
m.ID, err = r.ReadBytes()
return err
}
// BatchedParseBlockRequest contains multiple blocks to parse
type BatchedParseBlockRequest struct {
Requests [][]byte
}
// Encode serializes BatchedParseBlockRequest to the buffer
func (m *BatchedParseBlockRequest) Encode(buf *Buffer) {
buf.WriteUint32(uint32(len(m.Requests)))
for _, req := range m.Requests {
buf.WriteBytes(req)
}
}
// Decode deserializes BatchedParseBlockRequest from the reader
func (m *BatchedParseBlockRequest) Decode(r *Reader) error {
count, err := r.ReadCount()
if err != nil {
return err
}
m.Requests = make([][]byte, count)
for i := uint32(0); i < count; i++ {
if m.Requests[i], err = r.ReadBytes(); err != nil {
return err
}
}
return nil
}
// BatchedParseBlockResponse contains parsed blocks
type BatchedParseBlockResponse struct {
Responses []BlockResponse
}
// Encode serializes BatchedParseBlockResponse to the buffer
func (m *BatchedParseBlockResponse) Encode(buf *Buffer) {
buf.WriteUint32(uint32(len(m.Responses)))
for i := range m.Responses {
m.Responses[i].Encode(buf)
}
}
// Decode deserializes BatchedParseBlockResponse from the reader
func (m *BatchedParseBlockResponse) Decode(r *Reader) error {
count, err := r.ReadCount()
if err != nil {
return err
}
m.Responses = make([]BlockResponse, count)
for i := uint32(0); i < count; i++ {
if err := m.Responses[i].Decode(r); err != nil {
return err
}
}
return nil
}
// GetAncestorsRequest contains ancestor retrieval parameters
type GetAncestorsRequest struct {
BlkID []byte
MaxBlocksNum int32
MaxBlocksSize int32
MaxBlocksRetrivalTime int64
}
// Encode serializes GetAncestorsRequest to the buffer
func (m *GetAncestorsRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.BlkID)
buf.WriteInt32(m.MaxBlocksNum)
buf.WriteInt32(m.MaxBlocksSize)
buf.WriteInt64(m.MaxBlocksRetrivalTime)
}
// Decode deserializes GetAncestorsRequest from the reader
func (m *GetAncestorsRequest) Decode(r *Reader) error {
var err error
if m.BlkID, err = r.ReadBytes(); err != nil {
return err
}
if m.MaxBlocksNum, err = r.ReadInt32(); err != nil {
return err
}
if m.MaxBlocksSize, err = r.ReadInt32(); err != nil {
return err
}
m.MaxBlocksRetrivalTime, err = r.ReadInt64()
return err
}
// GetAncestorsResponse contains ancestor blocks
type GetAncestorsResponse struct {
BlksBytes [][]byte
}
// Encode serializes GetAncestorsResponse to the buffer
func (m *GetAncestorsResponse) Encode(buf *Buffer) {
buf.WriteUint32(uint32(len(m.BlksBytes)))
for _, blk := range m.BlksBytes {
buf.WriteBytes(blk)
}
}
// Decode deserializes GetAncestorsResponse from the reader
func (m *GetAncestorsResponse) Decode(r *Reader) error {
count, err := r.ReadCount()
if err != nil {
return err
}
m.BlksBytes = make([][]byte, count)
for i := uint32(0); i < count; i++ {
if m.BlksBytes[i], err = r.ReadBytes(); err != nil {
return err
}
}
return nil
}
// GetBlockIDAtHeightRequest contains height to query
type GetBlockIDAtHeightRequest struct {
Height uint64
}
// Encode serializes GetBlockIDAtHeightRequest to the buffer
func (m *GetBlockIDAtHeightRequest) Encode(buf *Buffer) {
buf.WriteUint64(m.Height)
}
// Decode deserializes GetBlockIDAtHeightRequest from the reader
func (m *GetBlockIDAtHeightRequest) Decode(r *Reader) error {
var err error
m.Height, err = r.ReadUint64()
return err
}
// GetBlockIDAtHeightResponse contains block ID at height
type GetBlockIDAtHeightResponse struct {
BlkID []byte
Err Error
}
// Encode serializes GetBlockIDAtHeightResponse to the buffer
func (m *GetBlockIDAtHeightResponse) Encode(buf *Buffer) {
buf.WriteBytes(m.BlkID)
buf.WriteUint8(uint8(m.Err))
}
// Decode deserializes GetBlockIDAtHeightResponse from the reader
func (m *GetBlockIDAtHeightResponse) Decode(r *Reader) error {
var err error
if m.BlkID, err = r.ReadBytes(); err != nil {
return err
}
v, err := r.ReadUint8()
m.Err = Error(v)
return err
}
// RequestMsg contains incoming request data
type RequestMsg struct {
NodeID []byte
RequestID uint32
Deadline int64
Request []byte
}
// Encode serializes RequestMsg to the buffer
func (m *RequestMsg) Encode(buf *Buffer) {
buf.WriteBytes(m.NodeID)
buf.WriteUint32(m.RequestID)
buf.WriteInt64(m.Deadline)
buf.WriteBytes(m.Request)
}
// Decode deserializes RequestMsg from the reader
func (m *RequestMsg) Decode(r *Reader) error {
var err error
if m.NodeID, err = r.ReadBytes(); err != nil {
return err
}
if m.RequestID, err = r.ReadUint32(); err != nil {
return err
}
if m.Deadline, err = r.ReadInt64(); err != nil {
return err
}
m.Request, err = r.ReadBytes()
return err
}
// RequestFailedMsg contains failed request info
type RequestFailedMsg struct {
NodeID []byte
RequestID uint32
ErrorCode int32
ErrorMessage string
}
// Encode serializes RequestFailedMsg to the buffer
func (m *RequestFailedMsg) Encode(buf *Buffer) {
buf.WriteBytes(m.NodeID)
buf.WriteUint32(m.RequestID)
buf.WriteInt32(m.ErrorCode)
buf.WriteString(m.ErrorMessage)
}
// Decode deserializes RequestFailedMsg from the reader
func (m *RequestFailedMsg) Decode(r *Reader) error {
var err error
if m.NodeID, err = r.ReadBytes(); err != nil {
return err
}
if m.RequestID, err = r.ReadUint32(); err != nil {
return err
}
if m.ErrorCode, err = r.ReadInt32(); err != nil {
return err
}
m.ErrorMessage, err = r.ReadString()
return err
}
// ResponseMsg contains response data
type ResponseMsg struct {
NodeID []byte
RequestID uint32
Response []byte
}
// Encode serializes ResponseMsg to the buffer
func (m *ResponseMsg) Encode(buf *Buffer) {
buf.WriteBytes(m.NodeID)
buf.WriteUint32(m.RequestID)
buf.WriteBytes(m.Response)
}
// Decode deserializes ResponseMsg from the reader
func (m *ResponseMsg) Decode(r *Reader) error {
var err error
if m.NodeID, err = r.ReadBytes(); err != nil {
return err
}
if m.RequestID, err = r.ReadUint32(); err != nil {
return err
}
m.Response, err = r.ReadBytes()
return err
}
// GossipMsg contains gossip message
type GossipMsg struct {
NodeID []byte
Msg []byte
}
// Encode serializes GossipMsg to the buffer
func (m *GossipMsg) Encode(buf *Buffer) {
buf.WriteBytes(m.NodeID)
buf.WriteBytes(m.Msg)
}
// Decode deserializes GossipMsg from the reader
func (m *GossipMsg) Decode(r *Reader) error {
var err error
if m.NodeID, err = r.ReadBytes(); err != nil {
return err
}
m.Msg, err = r.ReadBytes()
return err
}
// ConnectedRequest contains connection info
type ConnectedRequest struct {
NodeID []byte
Name string
Major uint32
Minor uint32
Patch uint32
}
// Encode serializes ConnectedRequest to the buffer
func (m *ConnectedRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.NodeID)
buf.WriteString(m.Name)
buf.WriteUint32(m.Major)
buf.WriteUint32(m.Minor)
buf.WriteUint32(m.Patch)
}
// Decode deserializes ConnectedRequest from the reader
func (m *ConnectedRequest) Decode(r *Reader) error {
var err error
if m.NodeID, err = r.ReadBytes(); err != nil {
return err
}
if m.Name, err = r.ReadString(); err != nil {
return err
}
if m.Major, err = r.ReadUint32(); err != nil {
return err
}
if m.Minor, err = r.ReadUint32(); err != nil {
return err
}
m.Patch, err = r.ReadUint32()
return err
}
// DisconnectedRequest contains disconnection info
type DisconnectedRequest struct {
NodeID []byte
}
// Encode serializes DisconnectedRequest to the buffer
func (m *DisconnectedRequest) Encode(buf *Buffer) {
buf.WriteBytes(m.NodeID)
}
// Decode deserializes DisconnectedRequest from the reader
func (m *DisconnectedRequest) Decode(r *Reader) error {
var err error
m.NodeID, err = r.ReadBytes()
return err
}
// HealthResponse contains health check result
type HealthResponse struct {
Details []byte
}
// Encode serializes HealthResponse to the buffer
func (m *HealthResponse) Encode(buf *Buffer) {
buf.WriteBytes(m.Details)
}
// Decode deserializes HealthResponse from the reader
func (m *HealthResponse) Decode(r *Reader) error {
var err error
m.Details, err = r.ReadBytes()
return err
}
// VersionResponse contains version info
type VersionResponse struct {
Version string
}
// Encode serializes VersionResponse to the buffer
func (m *VersionResponse) Encode(buf *Buffer) {
buf.WriteString(m.Version)
}
// Decode deserializes VersionResponse from the reader
func (m *VersionResponse) Decode(r *Reader) error {
var err error
m.Version, err = r.ReadString()
return err
}
// WaitForEventResponse contains event type
type WaitForEventResponse struct {
Message uint8
}
// Encode serializes WaitForEventResponse to the buffer
func (m *WaitForEventResponse) Encode(buf *Buffer) {
buf.WriteUint8(m.Message)
}
// Decode deserializes WaitForEventResponse from the reader
func (m *WaitForEventResponse) Decode(r *Reader) error {
var err error
m.Message, err = r.ReadUint8()
return err
}
// HTTPHandler contains HTTP handler info
type HTTPHandler struct {
Prefix string
ServerAddr string
}
// Encode serializes HTTPHandler to the buffer
func (m *HTTPHandler) Encode(buf *Buffer) {
buf.WriteString(m.Prefix)
buf.WriteString(m.ServerAddr)
}
// Decode deserializes HTTPHandler from the reader
func (m *HTTPHandler) Decode(r *Reader) error {
var err error
if m.Prefix, err = r.ReadString(); err != nil {
return err
}
m.ServerAddr, err = r.ReadString()
return err
}
// CreateHandlersResponse contains handler list
type CreateHandlersResponse struct {
Handlers []HTTPHandler
}
// Encode serializes CreateHandlersResponse to the buffer
func (m *CreateHandlersResponse) Encode(buf *Buffer) {
buf.WriteUint32(uint32(len(m.Handlers)))
for i := range m.Handlers {
m.Handlers[i].Encode(buf)
}
}
// Decode deserializes CreateHandlersResponse from the reader
func (m *CreateHandlersResponse) Decode(r *Reader) error {
count, err := r.ReadCount()
if err != nil {
return err
}
m.Handlers = make([]HTTPHandler, count)
for i := uint32(0); i < count; i++ {
if err := m.Handlers[i].Decode(r); err != nil {
return err
}
}
return nil
}
// NewHTTPHandlerResponse contains HTTP handler address
type NewHTTPHandlerResponse struct {
ServerAddr string
}
// Encode serializes NewHTTPHandlerResponse to the buffer
func (m *NewHTTPHandlerResponse) Encode(buf *Buffer) {
buf.WriteString(m.ServerAddr)
}
// Decode deserializes NewHTTPHandlerResponse from the reader
func (m *NewHTTPHandlerResponse) Decode(r *Reader) error {
var err error
m.ServerAddr, err = r.ReadString()
return err
}
// SetQuasarFinalizedRequest carries a new Quasar (⅔-by-stake) EXPORT-FINAL height
// from the node's consensus export-frontier observer to the VM (MsgSetQuasarFinalized).
// The VM persists it; the response is empty.
type SetQuasarFinalizedRequest struct {
Height uint64
}
// Encode serializes SetQuasarFinalizedRequest to the buffer
func (m *SetQuasarFinalizedRequest) Encode(buf *Buffer) {
buf.WriteUint64(m.Height)
}
// Decode deserializes SetQuasarFinalizedRequest from the reader
func (m *SetQuasarFinalizedRequest) Decode(r *Reader) error {
var err error
m.Height, err = r.ReadUint64()
return err
}
// QuasarHeightResponse carries the VM's current accept-tip-CLAMPED Quasar
// EXPORT-FINAL height (MsgQuasarHeight) — 0 before the first export forms. The
// MsgQuasarHeight request has no fields (empty payload).
type QuasarHeightResponse struct {
Height uint64
}
// Encode serializes QuasarHeightResponse to the buffer
func (m *QuasarHeightResponse) Encode(buf *Buffer) {
buf.WriteUint64(m.Height)
}
// Decode deserializes QuasarHeightResponse from the reader
func (m *QuasarHeightResponse) Decode(r *Reader) error {
var err error
m.Height, err = r.ReadUint64()
return err
}
// State sync over the boundary.
//
// A state-syncable VM is asked five questions and hands back summaries; a
// summary is then accepted, which starts the sync. The five questions are
// ordinary request/response. Accept is not: a summary is an object with
// behaviour on the VM's side, and only its identity can cross. So Accept
// travels as an id, and the server answers it against the summary it produced
// under that id — the same shape a block takes, for the same reason.
// StateSyncEnabledResponse answers whether this VM syncs state at all.
type StateSyncEnabledResponse struct {
Enabled bool
Err Error
}
func (m *StateSyncEnabledResponse) Encode(buf *Buffer) {
buf.WriteBool(m.Enabled)
buf.WriteUint8(uint8(m.Err))
}
func (m *StateSyncEnabledResponse) Decode(r *Reader) error {
var err error
if m.Enabled, err = r.ReadBool(); err != nil {
return err
}
v, err := r.ReadUint8()
m.Err = Error(v)
return err
}
// SummaryResponse carries one state summary: what a caller can read off it
// without holding the object. Every question that answers with a summary
// answers with this, because the answers differ only in which summary they
// name, never in what a summary is.
//
// An absent summary is not an error and not a zero-valued one: Err says
// ErrorNotFound and the caller must not read the fields. A VM that does not
// sync state at all says ErrorStateSyncNotImplemented, which is a different
// answer from "I sync, and have nothing".
type SummaryResponse struct {
ID []byte
Height uint64
Bytes []byte
Err Error
}
func (m *SummaryResponse) Encode(buf *Buffer) {
buf.WriteBytes(m.ID)
buf.WriteUint64(m.Height)
buf.WriteBytes(m.Bytes)
buf.WriteUint8(uint8(m.Err))
}
func (m *SummaryResponse) Decode(r *Reader) error {
var err error
if m.ID, err = r.ReadBytes(); err != nil {
return err
}
if m.Height, err = r.ReadUint64(); err != nil {
return err
}
if m.Bytes, err = r.ReadBytes(); err != nil {
return err
}
v, err := r.ReadUint8()
m.Err = Error(v)
return err
}
// ParseStateSummaryRequest carries a peer's summary bytes for the VM to read.
type ParseStateSummaryRequest struct {
Bytes []byte
}
func (m *ParseStateSummaryRequest) Encode(buf *Buffer) { buf.WriteBytes(m.Bytes) }
func (m *ParseStateSummaryRequest) Decode(r *Reader) error {
var err error
m.Bytes, err = r.ReadBytes()
return err
}
// GetStateSummaryRequest names the height whose summary is wanted.
type GetStateSummaryRequest struct {
Height uint64
}
func (m *GetStateSummaryRequest) Encode(buf *Buffer) { buf.WriteUint64(m.Height) }
func (m *GetStateSummaryRequest) Decode(r *Reader) error {
var err error
m.Height, err = r.ReadUint64()
return err
}
// StateSummaryAcceptRequest names the summary to accept.
//
// By id, because accepting is the summary's own behaviour and the summary is on
// the far side. The server resolves the id against the summaries it has handed
// out; an id it never produced is refused rather than reconstructed, since a
// summary rebuilt from bytes a caller supplies is not the one that was ratified.
type StateSummaryAcceptRequest struct {
ID []byte
}
func (m *StateSummaryAcceptRequest) Encode(buf *Buffer) { buf.WriteBytes(m.ID) }
func (m *StateSummaryAcceptRequest) Decode(r *Reader) error {
var err error
m.ID, err = r.ReadBytes()
return err
}
// StateSummaryAcceptResponse reports which way the VM decided to sync.
type StateSummaryAcceptResponse struct {
Mode uint8
Err Error
}
func (m *StateSummaryAcceptResponse) Encode(buf *Buffer) {
buf.WriteUint8(m.Mode)
buf.WriteUint8(uint8(m.Err))
}
func (m *StateSummaryAcceptResponse) Decode(r *Reader) error {
var err error
if m.Mode, err = r.ReadUint8(); err != nil {
return err
}
v, err := r.ReadUint8()
m.Err = Error(v)
return err
}