mirror of
https://github.com/zap-proto/zip.git
synced 2026-10-19 15:38:57 +00:00
A Rust developer writes Rust handlers, with Rust types and Rust doc comments,
and gets every projection from that source — the same deal a Go developer has
had. No .zap is written by hand and no Go program declares a Rust service's
ops.
The split falls on a measured seam. What is native per language is DECLARING an
op and RUNNING it; what is shared is the projection logic, driven from a neutral
description of the registry.
Manifest the registry with the Go taken out: ops, types, fields, wire
names, prose. App.Manifest fills one in by reflection; a
proc-macro fills one in as a Rust crate compiles.
Project* the OpenAPI document, the MCP tool list, the CLI and the ZAP
IDL, read off a Manifest. Go's own three now go through them —
the whole existing suite is the oracle — so Go keeps no private
path for them and the other languages cannot rot.
cmd/zipc the build-time projector. It reads a manifest, or the fragments
a compiler wrote, and writes the four documents.
rust/ zip in Rust: #[zip::ops] on an impl block, #[derive(zip::Wire)]
on a type, a router, a JSON binder, an HTTP door and a ZAP door.
The wire is generated by zapgen from wire.zap; nothing here
spells a byte offset by hand and nothing links Go.
The layout rule moved out of the manifest and into the projector, so the offsets
in a .zap are derived once for all three languages rather than three times;
TestProjectZAPMatchesRegistry pins that derivation against the layout the Go
encoder actually writes.
One service, written twice — corpus/info in Go and rust/examples/info in Rust,
fourteen ops each — is the gate. The OpenAPI document, the MCP tool list and the
CLI command tree come out byte-identical, and the ZAP schema agrees on every
struct, type and offset; it differs only where a field carries the declaring
language's own case convention and where the ledger names a type the way the
person who must change it would grep for it.
119 lines
3.3 KiB
Plaintext
119 lines
3.3 KiB
Plaintext
# Generated from typed ops. Do not edit.
|
|
# Every struct and method below is derived from one op's In and Out, and
|
|
# every offset from the layout the op-call plane encodes against.
|
|
|
|
package info
|
|
|
|
struct Bootstrapped {
|
|
is_bootstrapped bool @0
|
|
}
|
|
|
|
struct BootstrappedArgs {
|
|
chain text @0
|
|
}
|
|
|
|
struct ChainAlias {
|
|
alias text @0
|
|
}
|
|
|
|
struct ChainID {
|
|
blockchain_id text @0
|
|
}
|
|
|
|
struct Chains {
|
|
chains list<bytes> @0
|
|
}
|
|
|
|
struct Fees {
|
|
tx_fee u64 @0
|
|
create_asset_tx_fee u64 @8
|
|
create_chain_tx_fee u64 @16
|
|
}
|
|
|
|
struct NetworkID {
|
|
network_id u32 @0
|
|
}
|
|
|
|
struct NetworkName {
|
|
network_name text @0
|
|
}
|
|
|
|
struct NodeID {
|
|
node_id text @0
|
|
node_pop bytes @8
|
|
}
|
|
|
|
struct NodeIP {
|
|
ip text @0
|
|
}
|
|
|
|
struct NodeVersion {
|
|
version text @0
|
|
database_version text @8
|
|
rpc_protocol_version u32 @16
|
|
git_commit text @24
|
|
}
|
|
|
|
struct Peers {
|
|
num_peers u64 @0
|
|
peers list<bytes> @8
|
|
}
|
|
|
|
struct PeersArgs {
|
|
node_ids list<text> @0
|
|
}
|
|
|
|
struct Upgrades {
|
|
stop_vertex_id text @0
|
|
epoch_duration u64 @8
|
|
}
|
|
|
|
struct Uptime {
|
|
rewarding_stake_percentage text @0
|
|
weighted_average_percentage text @8
|
|
}
|
|
|
|
interface info {
|
|
# Bootstrapped reports whether a chain has finished bootstrapping on this node.
|
|
get_chain_bootstrapped(req: BootstrappedArgs) returns (rep: Bootstrapped)
|
|
# ChainID resolves a chain's alias to the id it names.
|
|
get_chain_id(req: ChainAlias) returns (rep: ChainID)
|
|
# Chains are the chains this node is running, which is a subset of the chains
|
|
# the P-Chain knows about.
|
|
get_chains() returns (rep: Chains)
|
|
# Fees are the transaction fees this node charges, in nLUX.
|
|
get_fees() returns (rep: Fees)
|
|
# NetworkID is the number of the network this node is on.
|
|
get_network_id() returns (rep: NetworkID)
|
|
# NetworkName is the name of the network this node is on.
|
|
get_network_name() returns (rep: NetworkName)
|
|
# Identity is this node's id, with the proof it holds the staking key that id is
|
|
# derived from.
|
|
get_node_id() returns (rep: NodeID)
|
|
# Address is where this node tells its peers to reach it.
|
|
get_node_ip() returns (rep: NodeIP)
|
|
# NodeVersion is what this node is running: its own release, the database format
|
|
# it reads, and the VM protocol it speaks.
|
|
get_node_version() returns (rep: NodeVersion)
|
|
# Peers are the nodes this one is connected to. A list of node ids narrows the
|
|
# answer to those, and no list asks for all of them.
|
|
get_peers(req: PeersArgs) returns (rep: Peers)
|
|
# Upgrades is the upgrade schedule this node runs.
|
|
get_upgrades() returns (rep: Upgrades)
|
|
# Uptime is how much of the network, by stake, reports having seen this node up.
|
|
get_uptime() returns (rep: Uptime)
|
|
}
|
|
|
|
# ---------------------------------------------------------------------
|
|
# 12 op(s) here. What follows is what this schema does not carry.
|
|
#
|
|
# blocked (3) — the op is absent; the field has no wire form:
|
|
# get_lps LPs.lps HashMap<String, LP> (map)
|
|
# get_vms VMs.fxs HashMap<String, String> (map)
|
|
# get_vms VMs.vms HashMap<String, Vec<String>> (map)
|
|
#
|
|
# opaque (3) — crosses, arrives without its name:
|
|
# Chains.chains Chain (list element)
|
|
# NodeID.node_pop ProofOfPossession
|
|
# Peers.peers Peer (list element)
|