RPC Reference
Normative RPC contract for owner-address-native requests and responses. The canonical protocol reference is protocol/SPECIFICATION.md — AccountKeychain custody, ERC-1271 removal, chain wipe.
Write operations
SubmitMessage
Accepts a fully signed Message.
In Makechain, all committed block messages are user-submitted and carry Ed25519 envelopes. Disabled relay-era message families must be rejected.
BatchSubmitMessages
Accepts a bounded list of signed Message values and returns per-message results.
DryRunMessage
Validates a signed Message against current state without mempool admission.
Merge-request reads
GetMergeRequest
Returns one active merge request identified by (project_id, request_id).
| Field | Type | Description |
|---|---|---|
project_id | bytes (32) | Target project ID |
request_id | bytes (32) | Content-addressed merge request ID |
Returns NOT_FOUND if the merge request is absent, removed, or pruned.
ListMergeRequests
Returns active merge requests under a target project prefix with cursor-based pagination and an optional requester_owner_address filter.
| Field | Type | Description |
|---|---|---|
project_id | bytes (32) | Target project ID |
limit | uint32 | Page size (max 200) |
cursor | bytes | Opaque pagination cursor |
requester_owner_address | bytes (20) | Optional requester filter |
Results are ordered by forward-key lexicographic order (equivalent to request_id order within a project).
ListMergeRequestsByRequester
Returns active merge requests opened by a specific owner_address, ordered by reverse-key lexicographic order.
| Field | Type | Description |
|---|---|---|
owner_address | bytes (20) | Requester owner address |
limit | uint32 | Page size (max 200) |
cursor | bytes | Opaque pagination cursor |
MergeRequestSummary
All three merge-request RPCs return MergeRequestSummary entries with the following fields:
| Field | Type | Description |
|---|---|---|
request_id | bytes (32) | Content-addressed merge request ID |
project_id | bytes (32) | Target (upstream) project ID |
requester_owner_address | bytes (20) | Original requester's owner address |
source_project_id | bytes (32) | Source fork-descendant project ID |
source_ref | bytes | Branch or ref name in the source project |
source_commit_hash | bytes (32) | Head commit of proposed changes |
target_ref | bytes | Suggested target ref in upstream |
title | string | Short description |
added_at | uint32 | Timestamp from the MERGE_REQUEST_ADD message |
Closure attribution is not available from canonical state. To determine whether a merge request was withdrawn by the requester or closed by a maintainer, inspect finalized MERGE_REQUEST_REMOVE messages for the same (project_id, request_id) pair.
Project and account selectors
Selectors are address-native.
| Message | Field |
|---|---|
GetProjectResponse | owner_address |
GetProjectByNameRequest | owner_address |
SearchProjectsRequest | owner_address |
ListProjectsRequest | owner_address |
GetAccountRequest | owner_address |
GetAccountResponse | owner_address, username |
GetKeyRequest | owner_address |
ListKeysRequest | owner_address |
GetCustodyKeyRequest | owner_address, key_id |
ListCustodyKeysRequest | owner_address |
GetAccountActivityRequest | owner_address |
ListVerificationsRequest | owner_address |
GetAccount(owner_address) returns a default-zero account view even when no account row has been materialized.
GetAccountResponse.username is the canonical username when the account has effective active storage and an active reservation. It is the empty string when the account has no effective active username.
Custody key reads
GetCustodyKey and ListCustodyKeys expose the AccountKeychain custody keys authorized under an owner_address. Both are QMDB-direct reads — there is no indexer table behind them.
GetCustodyKey
Returns one custody key identified by (owner_address, key_id).
| Field | Type | Description |
|---|---|---|
owner_address | bytes (20) | Account that owns the keychain |
key_id | bytes (20) | EVM-derived custody key id |
Returns NOT_FOUND when no custody key with that key_id has ever been authorized for the account. A revoked key is still returned, with status = CUSTODY_KEY_STATUS_REVOKED.
ListCustodyKeys
Returns the custody keys under an owner_address with cursor-based pagination.
| Field | Type | Description |
|---|---|---|
owner_address | bytes (20) | Account that owns the keychain |
limit | uint32 | Page size (max 200) |
cursor | bytes | Opaque pagination cursor |
cursor and the returned next_cursor are opaque internal storage keys, not bare key_id values — echo next_cursor verbatim to fetch the next page and stop when it is empty.
CustodyKeyEntry
Both custody-read RPCs, and the GetAccountResponse.custody_keys snapshot, return CustodyKeyEntry records:
| Field | Type | Description |
|---|---|---|
key_id | bytes (20) | EVM-derived custody key id |
signature_type | enum | 1 secp256k1, 2 P256, 3 WebAuthn P256 |
public_key | bytes | Explicit key material — secp256k1 SEC1 65 bytes, or P256 x‖y 64 bytes |
admin | bool | Whether the key can authorize account-level mutations |
expires_at | uint64 | 0 means non-expiring; admin keys are always 0 |
added_at | uint32 | Timestamp of the authorizing KEYCHAIN_AUTHORIZE |
revoked_at | uint32 | 0 while active; set when revoked |
status | enum | 1 CUSTODY_KEY_STATUS_ACTIVE, 2 CUSTODY_KEY_STATUS_REVOKED |
status tracks revocation only — ACTIVE means "not revoked". An expired key is still reported ACTIVE; expiry is enforced separately at authorization time through expires_at. GetAccountResponse carries a custody_keys snapshot for convenience, but ListCustodyKeys is the paginated source of truth.
Links, reactions, and history
These transport fields are also address-native:
| Message | Field |
|---|---|
ListLinksRequest | owner_address |
LinkEntry | target_owner_address, source_owner_address |
ListLinksByTargetRequest | target_owner_address |
ListReactionsRequest | owner_address |
ReactionEntry | source_owner_address |
RefLogEntry | owner_address |
GetStorageQuotaProofRequest | owner_address |
GetStorageQuotaProofResponse | owner_address |
Commit metadata
CommitMeta uses author_address.
Merge request transport
Merge-request transport fields source_ref and target_ref remain raw protobuf bytes fields. REST/OpenAPI surfaces expose them as hex-encoded byte strings so non-UTF-8 ref names are lossless.
Verification transport
Any transport surface that returns verification records exposes the canonical verification identity:
verification_typeaddresschain_id
The claim_signature is validated at write time and persisted in state, but it is intentionally not exposed in the VerificationEntry response — transport surfaces return only the canonical identity above. ERC-1271 validation metadata (claim_key_type, claim_block_hash) is removed in Makechain and is not present in responses.
Block and sync transport
The canonical persisted and streamed verification unit is the finalized Block (header + body). The block body carries the committed message set (account_messages + flat user_messages), authenticated by the header's transactions_root.
Relevant responses carry the Block:
GetBlockResponseGetSyncTargetResponseSubscribeBlocks
Transports must preserve canonical account-message order directly in the committed block body.