PerformanceBlog
Tempo MCP serverGive agents search and read tools for Tempo docs
Skip to content
LogoLogo

Zone RPC

The zone RPC starts from the standard Ethereum JSON-RPC and restricts it to enforce privacy guarantees. Every RPC request must include an authorization token that proves the caller controls a Tempo account and scopes all responses to that account.

Authorization Tokens

Authorization tokens are short-lived credentials (maximum 1 month) signed by the caller's Tempo account key. Tempo accounts support multiple signature types (secp256k1, P256, WebAuthn), and accounts with Access Keys via the AccountKeychain precompile can use those keys to authenticate.

The signed message includes:

  • "TempoZoneRPC" magic prefix for domain separation
  • Spec version, zone ID, and chain ID for replay protection (zone 0 can be used to allow access to all zones)
  • Issuance and expiry timestamps

Tokens are sent via the X-Authorization-Token HTTP header on every request.

Method Access Control

Each JSON-RPC method falls into one of four categories:

Available to any authenticated caller:

MethodAccess TypeNotes
eth_chainIdAllowedZone chain ID
eth_blockNumberAllowedLatest block number
eth_gasPriceAllowedCurrent gas price
eth_maxPriorityFeePerGasAllowedCurrent priority fee
eth_feeHistoryAllowedFee history
eth_getBlockByNumberAllowedBlock headers without transaction details
eth_getBlockByHashAllowedBlock headers without transaction details
eth_subscribe("newHeads")AllowedBlock headers with logsBloom zeroed
eth_syncingAllowedSync status
eth_coinbaseAllowedSequencer address
net_versionAllowedNetwork ID
net_listeningAllowedNode status
web3_clientVersionAllowedClient version
web3_sha3AllowedPure Keccak-256 hash
eth_getBalanceScopedReturns balance for the authenticated account only. Queries for other accounts return 0x0.
eth_getTransactionCountScopedReturns nonce for the authenticated account only. Other accounts return 0x0.
eth_callScopedExecutes with from set to the authenticated account. Execution-level privacy enforces balanceOf access control at the contract level.
eth_estimateGasScopedOnly allowed when from equals the authenticated account.
eth_getTransactionByHashScopedReturns the transaction only if the authenticated account is the sender. Returns null otherwise.
eth_getTransactionReceiptScopedReturns the receipt only if the authenticated account is the sender. Logs are filtered (see Event Filtering).
eth_sendRawTransactionScopedValidates that the transaction sender matches the authenticated account.
eth_getLogsScopedFiltered to TIP-20 events where the authenticated account is a relevant party (see Event Filtering).
eth_getFilterLogsScopedSame filtering as eth_getLogs.
eth_getFilterChangesScopedSame filtering. Only returns new events since last poll.
eth_newFilterScopedCreates a filter implicitly scoped to the authenticated account.
eth_subscribe("logs")ScopedSubscription scoped to the authenticated account.
eth_newBlockFilterScopedReturns new block hashes.
eth_uninstallFilterScopedRemoves a previously created filter.

Error vs. silent response: Methods where the user explicitly provides a mismatched parameter (eth_sendRawTransaction with wrong sender, eth_call with wrong from) return explicit errors, since the user already knows the address they supplied and the error leaks nothing. Methods that query about other accounts return silent dummy values (0x0, null, empty results) instead of errors; an error would reveal "this data exists but you can't see it."

Restricted (sequencer-only)

MethodReason
eth_getStorageAtRaw storage reads bypass all access control
eth_getCodeNo legitimate non-sequencer use case
eth_createAccessListReveals storage layout
eth_getBlockByNumber (with true)Full block with all transactions
eth_getBlockByHash (with true)Full block with all transactions
eth_getBlockTransactionCountByNumberTransaction counts reveal activity levels
eth_getBlockTransactionCountByHashSame as above
eth_getTransactionByBlockNumberAndIndexArbitrary transaction access
eth_getTransactionByBlockHashAndIndexSame as above
debug_*, admin_*, txpool_*All debug, admin, and txpool namespaces

Disabled

MethodReason
eth_getProofMerkle proofs leak state trie structure
eth_newPendingTransactionFilterMempool observation
eth_subscribe("newPendingTransactions")Mempool observation
Mining-related methodsTempo Zones have no mining

Any method not explicitly listed returns error code -32601 (method not found), ensuring new methods are not accidentally exposed.

Timing Side Channels

Scoped methods that fetch data before checking authorization have a mandatory 100 ms minimum response time. This ensures that eth_getTransactionByHash for a non-existent transaction hash and for another user's transaction have indistinguishable response times, preventing existence probing.

Methods that need the speed bump:

MethodReason
eth_getTransactionByHashMust fetch the transaction to check if sender matches
eth_getTransactionReceiptMust fetch the receipt to check the sender
eth_getLogsResponse time correlates with total log volume, not just the caller's logs
eth_getFilterLogsSame as eth_getLogs
eth_getFilterChangesSame as eth_getLogs

Methods that do not need the speed bump include eth_getBalance and eth_getTransactionCount (address checked before any data fetch), eth_call and eth_estimateGas (from validated before execution), and eth_sendRawTransaction (sender verified during decoding).

Block Responses

Block headers returned to non-sequencer callers are sanitized:

  • transactions is always an empty array.
  • logsBloom is replaced with a zero Bloom. The real Bloom filter would allow probing whether a specific address had activity in a block.
  • All other header fields (number, hash, gasUsed, stateRoot, etc.) are returned normally.

Event Filtering

Log queries are restricted to TIP-20 events where the authenticated account is a relevant party:

EventVisible if
Transferfrom == caller OR to == caller
Approvalowner == caller OR spender == caller
TransferWithMemofrom == caller OR to == caller
Mintto == caller
Burnfrom == caller

All other event topics (system events, role events, configuration events) are filtered out.

Zone-Specific RPC Methods

MethodAccessDescription
zone_getAuthorizationTokenInfoAny authenticatedReturns the authenticated account address and token expiry
zone_getZoneInfoAny authenticatedReturns zone metadata: zoneId, zoneTokens, sequencer, chainId
zone_getDepositStatusScopedReturns whether deposits from a given Tempo block have been processed, filtered to the caller's deposits

Error Codes

CodeMessageMeaning
-32001Authorization token requiredNo authorization token provided
-32002Authorization token expiredThe authorization token has expired
-32003Transaction rejectedTransaction sender does not match authenticated account
-32004Account mismatchThe from field does not match the authenticated account
-32005Sequencer onlyMethod requires sequencer access
-32006Method disabledMethod is not available on zones