Protocol Specification v0.6
Open Issues
This page records the limits of this edition so an implementer can choose the correct integration boundary. It describes only what this edition implements. A feature outside this contract must not be assumed merely because its name or discriminator appears in a design document.
Edition limits
A request that meets a limit of this edition stops at a fixed step with a named result and no effect.
- 1
In the table, not accepted
Six operations keep their full layout in the operation table. The reference answers each with
UNSUPPORTED_VERSIONbefore any signature is checked. - 2
No THRESHOLD verifier
SINGLE with Ed25519 is the implemented scheme. A packet that names scheme 2 is refused before any signature verification.
- 3
Amounts fit in u64
An amount travels as 32 bytes. The product accepts it only when the first 24 bytes are zero and never truncates it.
- 4
Busy is recorded
Requests on different assets share one cut, so a request signed at a cut that another commit has moved is
BUSYwithout effect. The outcome is recorded and consumes the call identifier; a resend needs a new signed cut and a new call sequence number.
- Path of a request that passes
- Refused with this result and no effect
- In the operation table, not accepted by the reference
Schematic: refusals for frame size, source binding, the delivery window and an invalid signature are not drawn. The drawn steps run in this order in the Rust reference.
Executable scope#
NormativeBytes, test vectors and proofs
The reference profile (opens in a new tab)'s supported inbound operations are listed in Field Tables. SINGLE (opens in a new tab) with Ed25519 (opens in a new tab) is implemented; a THRESHOLD (opens in a new tab) discriminator does not provide a threshold verifier. The Go package implements its documented wire/admission (opens in a new tab) surface and is not a durable authority or signed-response verifier.
| Limit | Integration consequence |
|---|---|
| Position-based operands | Match the family, opcode, exact counts and each operand's meaning |
| Registered 64-bit handles | Establish identity and domain registration out of band |
| Product amounts limited to u64 | Reject out-of-range base-unit amounts instead of truncating |
| Global revision and epoch cut | Another committed write can make a fresh signed request Busy |
| Configured size, depth and time limits | Read the host profile; do not assume universal constants |
| Absent and indefinite appeal deadline | Different wire forms, same product meaning in this edition |
| JSON reference signing inputs | Reproduce the exact defined serialization |
| Request-admission errors before signature verification | Account for the documented registration-disclosure limitation |
Where the reference stops#
An operation outside the reference set keeps its full layout in the operation table and is marked as not accepted:
{ "family": 3, "opcode": 7, "name": "Write", "title": "write", "summary": "Writes a permitted data value for the asset.", "reference_accepts": false, "words": [ {"kind": "use", "group": "call_prefix"}, {"kind": "use", "group": "credential"}, {"kind": "use", "group": "version_vector"}, {"kind": "word", "name": "generation", "type": "generation"}, {"kind": "word", "name": "value", "type": "u64", "description": "Data value to write."} ], "blobs": [ {"name": "amount", "type": "amount_u256"} ], "deadline": "absent", "target_domain": "origin_domain", "call": true, "recorded_codes": [1, 2, 3, 20]},The reference configuration accepts a fixed set of opcodes per family (opens in a new tab), none for heartbeat (opens in a new tab), and its receiving path answers any other operation with UNSUPPORTED_VERSION before the signature is checked:
fn supported_frame(core: &Core) -> bool { match core.body.as_ref() { Some(Body::StateSync(op)) => matches!(op.opcode, Some(1..=6)), Some(Body::RegulatoryAction(op)) => matches!(op.opcode, Some(1..=3)), Some(Body::Ack(op)) => op.opcode == Some(1), Some(Body::Query(op)) => matches!(op.opcode, Some(1..=8)), Some(Body::LockManagement(op)) => matches!(op.opcode, Some(1..=6)), Some(Body::Governance(op)) => op.opcode == Some(1), _ => false, }}Generic admission then checks the negotiated version and family, the source binding and the delivery window, and refuses scheme 2 before any signature verification because this edition has no THRESHOLD verifier:
pub fn admit_packet( packet: &CanonicalPacket, profile: &Profile, boundary: &Boundary,) -> Result<()> { check_scope(packet.core(), profile, boundary)?; let scheme = packet .core() .signature_scheme .ok_or(WireError::InvalidFormat)?; if scheme == 2 { return Err(WireError::InvalidThresholdSignature); } if !profile.schemes.contains(&scheme) || !verify( &boundary.public_key, &packet.signing_bytes()?, packet.signature(), ) { return Err(WireError::InvalidSignature); } Ok(())}An amount travels as a 32-byte unsigned integer, and the product accepts it only when its first 24 bytes are zero:
#[derive(Clone, Copy, Debug, Eq, PartialEq)]pub struct Unsigned256(pub [u8; 32]);impl Unsigned256 { pub fn from_bytes(bytes: &[u8]) -> Result<Self> { Ok(Self(bytes.try_into().map_err(|_| BAD)?)) } pub fn product_amount(self) -> Result<u64> { if self.0[..24].iter().any(|&byte| byte != 0) { return Err(BAD); } Ok(u64::from_be_bytes(self.0[24..].try_into().unwrap())) }}type Unsigned256 [32]bytefunc DecodeAmount(raw []byte) (Unsigned256, error) { if len(raw) != 32 { return Unsigned256{}, ErrFormat } return Unsigned256(raw), nil}func (amount Unsigned256) ProductAmount() (uint64, error) { for _, byte := range amount[:24] { if byte != 0 { return 0, ErrFormat } } return binary.BigEndian.Uint64(amount[24:]), nil}Two requests on different assets share one authority cut, so the second request signed at that cut is Busy without effect once the first commits:
Columnsidoperationinputsexpectedevidence
distinct-assets-share-the-authority-cut pair operation_a=execute;operation_b=execute;asset_a=17;asset_b=22;epoch=9;same_initial_cut=true;request_exchange=true schedule=serial;second_fresh_result=busy;second_effect=false compatible_actions_have_no_shared_writer,actual_primary_write_changes_the_reply_to_the_same_signed_cut,prior_call_on_any_route_cannot_repeat_an_authority_effect The size and nesting limits, the clock skew and the TTL (opens in a new tab) floor are fields of the receiving boundary that the host fills in, and the largest signed delivery TTL is a separate configuration value. The code fixes no number for any of them:
#[derive(Clone, Copy, Debug, Eq, PartialEq)]pub struct Boundary { pub deployment: u64, pub source: u64, pub target: u64, pub principal: u64, pub key_id: u64, pub epoch: u64, pub route_scope: u64, pub now: u64, pub asset_ttl_floor: u64, pub future_skew: u64, pub max_frame: usize, pub max_nesting: usize, pub version_floor: u64, pub critical_allowed: bool, pub public_key: [u8; 32],}The schema gives a regulatory operation three appeal deadline (opens in a new tab) forms on the wire, and this edition gives the absent and the indefinite form one meaning:
// The appeal deadline of a regulatory action (family 2). Operations of// other families reject both members. In this version an absent member and// appeal_deadline_indefinite both mean that no appeal deadline applies.oneof appeal_deadline { // Only the value true is canonical. bool appeal_deadline_indefinite = 4; // Unix time in UTC seconds. fixed64 appeal_deadline_utc_seconds = 5;}Recovery assumptions#
NormativeBytes, test vectors and proofs
The rollback-resistant profile requires separately administered authority and witness transports, exact authenticated control values, durable archive selection and the configured key custody. A stale but cryptographically valid snapshot must hold. The protocol does not make an unavailable independent witness available or turn a local timeout into evidence of reversal.
Architecture outside this profile#
DesignCarried from v0.5, without bytes or test vectors in this version
Channels are installed out of band. General peer discovery, multi-hop relaying, condition expressions (opens in a new tab), signed Registry records on the wire, retention periods and the complete deployed OSS (opens in a new tab) service are outside this edition. Migration from v0.5 states how the related v0.5 topics are treated.
Assurance and reporting#
The formal result applies to the model and source correspondence (opens in a new tab) stated in the artifact mapping, under its assumptions. It is not a security audit of the entire compiled service, external adapters or operating environment.
Reproduce the relevant checks in Conformance and report a concrete difference with the exact input, selected profile and observed outcome through the repository's support or security process.
Related Pages#
Edition history#
- 0.6.0: Added this edition. The v0.5 specification remains available at its original addresses.
