Skip to content

Latest commit

 

History

History
1828 lines (1300 loc) · 52.8 KB

JSON_RPC_API.md

File metadata and controls

1828 lines (1300 loc) · 52.8 KB

Shell-Chain JSON-RPC API Reference

Complete reference for the shell-chain JSON-RPC API. All methods follow the JSON-RPC 2.0 specification.

See also: Quickstart Guide · Testnet Operator Guide · Post-Quantum Cryptography Guide · Native Account Abstraction Guide · System Contracts · Prover Guide


Table of Contents


Connection

HTTP endpoint (default):

http://127.0.0.1:8545

WebSocket endpoint (when --ws is enabled):

ws://127.0.0.1:8546

All requests use POST with Content-Type: application/json.

Address note: RPC input and output addresses use canonical 32-byte 0x + 64 lowercase hex throughout the current codebase.

CORS Configuration

Control cross-origin access with --rpc-cors:

# Allow all origins
shell-node run --rpc-cors "*"

# Allow specific origins (comma-separated)
shell-node run --rpc-cors "http://localhost:3000,https://app.example.com"

Or in TOML config:

[rpc]
cors_origins = ["http://localhost:3000", "https://app.example.com"]

API Namespace Whitelist

Control which API namespaces are exposed with --rpc-api:

# Validators (minimal surface)
shell-node run --rpc-api eth,net,web3,shell

# RPC nodes (full API)
shell-node run --rpc-api eth,net,web3,shell,debug,trace

Available namespaces: eth, net, web3, shell, debug, trace

If --rpc-api is not specified, all namespaces registered by the node are available.

Rate Limiting

RPC rate limiting is available via --rpc-rate-limit:

shell-node run --rpc-rate-limit 100  # 100 requests/sec per bearer token/public bucket

Or in TOML config:

[rpc]
rate_limit = 100

When an API key is configured, authentication is evaluated before rate limiting, so bad unauthenticated requests do not consume the authenticated bucket. Valid Bearer tokens get independent buckets; no-token public requests share a public bucket. When the limit is exceeded, the server returns an HTTP 429 response.

WebSocket Support

Enable the WebSocket server with --ws:

shell-node run --ws --ws-port 8546

The WebSocket endpoint supports all the same JSON-RPC methods as HTTP, plus real-time PubSub subscriptions and filter-based polling via eth_newFilter, eth_newBlockFilter, and eth_getFilterChanges.

eth_subscribe (WebSocket only)

Subscribe to live events. Returns a subscription ID.

Subscription types:

Type Description
newHeads Pushes new block headers when blocks are produced or imported
logs Pushes matching log events; reorged logs are replayed with removed: true before replacement-chain logs
newPendingTransactions Pushes transaction hashes as they enter the mempool
syncing Pushes sync status changes (syncing/not syncing)

Example — newHeads:

wscat -c ws://127.0.0.1:8546

> {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
< {"jsonrpc":"2.0","id":1,"result":"0x1"}
< {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x1","result":{"number":"0xa","hash":"0x...","parentHash":"0x...","timestamp":"0x..."}}}

Example — logs with filter:

> {"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x...","topics":["0xddf2..."]}]}
< {"jsonrpc":"2.0","id":2,"result":"0x2"}

logs filters reject invalid address or topics values. Addresses must use the canonical 0x-prefixed 64-hex-character Shell address form. Topic entries must be null, a 0x-prefixed 32-byte hash, or an array of 0x-prefixed 32-byte hashes. The topics array can contain at most four positional entries. Within topics, null is a wildcard for that position; an empty alternatives array ([]) matches no logs at that position. Only address and topics are supported for live log subscriptions; other filter fields are rejected as invalid parameters rather than ignored.

Example — newPendingTransactions:

> {"jsonrpc":"2.0","id":3,"method":"eth_subscribe","params":["newPendingTransactions"]}
< {"jsonrpc":"2.0","id":3,"result":"0x3"}
< {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x3","result":"0xabc123..."}}

newPendingTransactions currently returns hashes only. Requests with includeTransactions: true are rejected because full transaction objects are not supported. Option objects may contain only includeTransactions; unknown fields are rejected as invalid parameters.

eth_unsubscribe (WebSocket only)

Cancel an active subscription.

> {"jsonrpc":"2.0","id":4,"method":"eth_unsubscribe","params":["0x1"]}
< {"jsonrpc":"2.0","id":4,"result":true}

Limits: Maximum 1024 global subscriptions, 16 per connection. Connections are auto-disconnected after repeated lag events.


eth_ Namespace

Standard Ethereum-compatible JSON-RPC methods.

eth_blockNumber

Returns the current block height.

Parameters: None

Returns: String — Hex-encoded block number.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x1a"}

eth_chainId

Returns the chain ID.

Parameters: None

Returns: String — Hex-encoded chain ID.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x539"}

eth_syncing

Returns sync status. A node may temporarily report syncing while block range catch-up is in flight; otherwise it returns false.

Parameters: None

Returns: Boolean | Object — false when not syncing, or a sync progress object when the node is catching up.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":false}

eth_mining

Returns whether the node is producing blocks.

Parameters: None

Returns: Boolean — true if the node has a validator keystore loaded.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_mining","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":true}

eth_hashrate

Returns mining hashrate. Always "0x0" (PoA consensus, no mining).

Parameters: None

Returns: String — Always "0x0".


eth_accounts

Returns managed accounts. Always empty — the node does not hold user private keys.

Parameters: None

Returns: Array — Always [].


eth_protocolVersion

Returns the protocol version.

Parameters: None

Returns: String — "0x45" (Cancun-compatible).


eth_gasPrice

Returns the current base fee.

Parameters: None

Returns: String — Hex-encoded base fee in wei for the latest chain state. The exact value changes over time as blocks are produced.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x5f7609"}

eth_maxPriorityFeePerGas

Returns the suggested priority fee. Always "0x0" on this PoA chain.

Parameters: None

Returns: String — "0x0".


eth_feeHistory

Returns historical base fee and gas usage data.

Parameters:

# Type Required Description
1 String Yes Block count (hex) — 1 to 1024
2 String Yes Newest block (block tag or hex number)
3 Array<Number> No Reward percentiles, 0 to 100 in non-decreasing order

Returns: Object with oldestBlock, baseFeePerGas, gasUsedRatio, reward.

Unreleased node source computes reward as effective priority fees, sorted by fee and weighted by actual receipt gas consumed. Fee caps limit the effective tip; failed transactions still contribute their charged gas. Empty blocks or zero-tip transactions yield zero rewards. Omitting percentiles or passing [] keeps reward: [].

Fee inputs remain available after body pruning for blocks stored by this implementation. Legacy intact bodies also remain queryable and preserve their fee inputs when subsequently pruned. Already-pruned legacy blocks with missing fee metadata cannot supply reward percentiles: the query returns an error, while queries without percentiles can still return header base fees and gas usage. Positive-tip percentile results on published node versions remain to be verified.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_feeHistory","params":["0x5","latest",[]],"id":1}'
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "oldestBlock": "0x15",
    "baseFeePerGas": ["0x8e4f6f","0x7c4681","0x6c1761","0x5f7609","0x53a8d3","0x48c470"],
    "gasUsedRatio": [0.0, 0.0, 0.0, 0.0, 0.0],
    "reward": []
  }
}

State Query Block Tags

Unreleased node source supports eth_getBalance, eth_getTransactionCount, eth_getCode, eth_getStorageAt, eth_call, and eth_createAccessList against retained canonical state using "earliest", "safe", "finalized", or a numeric block. Historical reads use the selected header's committed state root even when the block body has been pruned. Missing blocks, retained state, or historical contract bytecode return an error rather than current-state data or an empty contract. Queries do not write chain state; simulations discard all writes.

"latest" and "pending" state reads retain their live-state behavior. eth_getTransactionCount with "pending" also includes contiguous queued transactions from the sender; historical nonce queries never include the pool. "safe" and "finalized" select the finalized cursor, while "earliest" selects genesis. Published binaries may still accept only "latest" and "pending"; verify the running version before using historical state reads.

From a source checkout, run the isolated HTTP snapshot regression and the signed execution, independent import, pruning and fresh-process recovery regression:

cargo test -p shell-rpc historical_state_reads_http -- --nocapture
cargo test -p shell-node --features rocksdb fee_history_rewards -- --nocapture

Block, receipt, log, and fee-history methods keep their documented historical block support.


eth_getBalance

Returns the balance of an address.

Parameters:

# Type Required Description
1 String Yes Address (0x... canonical)
2 String No State block tag ("latest" or "pending" only)

Returns: String — Hex-encoded balance in wei.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0xYOUR_ADDRESS_HERE","latest"],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"}

eth_getTransactionCount

Returns the nonce (transaction count) for an address.

Parameters:

# Type Required Description
1 String Yes Address (0x... canonical)
2 String No State block tag ("latest" or "pending" only)

Returns: String — Hex-encoded nonce.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS_HERE","latest"],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x0"}

eth_getBlockByNumber

Returns a block by number.

Parameters:

# Type Required Description
1 String Yes Block tag or hex number
2 Boolean Yes true for full transaction objects, false for hashes only

Supported block tags: "latest", "earliest", "pending", "safe", "finalized".

When "pending" is requested, a pseudo-block is constructed from the current mempool.

Returns: Object|null — Block object or null if not found.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false],"id":1}'
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "number": "0x1a",
    "hash": "0xabc...",
    "parentHash": "0xdef...",
    "timestamp": "0x65a5f200",
    "gasLimit": "0x1c9c380",
    "gasUsed": "0x0",
    "compressionLayer": 1,
    "pruningStatus": "pruned",
    "transactions": []
  }
}

Shell block responses include STARK storage metadata in addition to Ethereum compatibility fields. compressionLayer is the highest accepted compression layer currently known for the block, including pointer blocks in a contiguous range. pruningStatus reports the local witness state (unpruned, compressedWitnessRetained, pruned, notWitnessed, pending, or unknown). STARK proof bytes are no longer carried in block header extraData; canonical settlements use a StarkReward system transaction whose input contains the proof payload, while source blocks expose full-proof or pointer metadata.


eth_getBlockByHash

Returns a block by hash.

Parameters:

# Type Required Description
1 String Yes Block hash (0x-prefixed, 32 bytes)
2 Boolean Yes true for full tx objects, false for hashes

Returns: Object|null — Block object or null.


eth_getTransactionByHash

Returns a transaction by hash. Checks the mempool first, then on-chain storage. Shell reward records are first-class system transactions, so block gas rewards and STARK rewards are also discoverable by deterministic transaction hash.

Parameters:

# Type Required Description
1 String Yes Transaction hash (0x-prefixed, 32 bytes)

Returns: Object|null — Transaction object or null.

Shell-specific transaction metadata:

Field Description
shellType Product-readable type: transfer, contractCreate, contractCall, aaBatch, blockGasReward, or starkReward
rewardKind Present for reward system transactions: blockGasReward or starkReward
rewardLayer STARK layer for prover rewards, hex encoded
rewardSourceHash Parent block, source range, or artifact hash used to derive the reward
originalSize / compressedSize STARK compression accounting, hex byte counts
curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_getTransactionByHash","params":["0xabc123..."],"id":1}'

eth_getTransactionReceipt

Returns the receipt of a mined transaction.

Parameters:

# Type Required Description
1 String Yes Transaction hash

Returns: Object|null — Receipt object (includes status, gasUsed, logs, blockNumber, shellType, rewardKind, etc.) or null if not yet mined.


eth_sendRawTransaction

Submits a signed transaction. Accepts RLP-encoded or JSON-encoded transaction bytes.

Parameters:

# Type Required Description
1 String Yes Hex-encoded signed transaction data

Returns: String — Transaction hash.

Validation: The transaction's max_fee_per_gas must be ≥ the current base fee.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_sendRawTransaction","params":["0x...signed_tx_bytes..."],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0xabc123..."}

eth_call

Executes a read-only call against the EVM (no state changes).

Parameters:

# Type Required Description
1 Object Yes Call request: {from?, to, data?, value?, gas?}
2 String No State block tag; historical calls require the unreleased source and retained canonical state described above

Returns: String — Hex-encoded return data.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xCONTRACT_ADDRESS","data":"0x..."},"latest"],"id":1}'

eth_estimateGas

Estimates gas for a transaction. Returns gas_used × 1.2 with a minimum of 21,000.

Parameters:

# Type Required Description
1 Object Yes Call request: {from?, to?, data?, value?}

Returns: String — Hex-encoded gas estimate.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_estimateGas","params":[{"to":"0xRECIPIENT_ADDRESS","value":"0xde0b6b3a7640000"}],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x5208"}

eth_createAccessList

Creates an EIP-2930 access list for a transaction.

Parameters:

# Type Required Description
1 Object Yes Call request
2 String No Block tag or canonical hex block number (retained state required)

Returns: Object with accessList and gasUsed.

Unreleased node source discovers accessed accounts and storage keys by executing on isolated state. Supplied entries are merged and deduplicated; accesses in reverted child calls are retained. gasUsed reflects execution with the final returned list, including its intrinsic gas. Discovery passes use one captured header and state root; historical queries require retained canonical state and never substitute current state. Existing execution-profile restrictions apply.

Generated lists are bounded by transaction limits: 256 addresses and 512 keys per address. A call that exceeds these limits or does not converge within eight simulations returns an error. Published node versions must be verified before relying on discovery or historical support.

From a source checkout, run the self-contained acceptance regression:

cargo test -p shell-rpc create_access_list -- --nocapture

The regression uses temporary contracts and checks real HTTP history, returned list usability, gas-dependent discovery, reverted child accesses and state isolation. It does not enable the development execution profile on a network.


eth_getCode

Returns the bytecode at an address.

Parameters:

# Type Required Description
1 String Yes Address
2 String No State block tag ("latest" or "pending" only)

Returns: String — Hex-encoded bytecode, or "0x" for accounts without runtime code.


eth_getStorageAt

Returns a storage slot value.

Parameters:

# Type Required Description
1 String Yes Address
2 String Yes Storage position (hex-encoded, 32-byte key)
3 String No State block tag ("latest" or "pending" only)

Returns: String — Zero-padded 32-byte hex value.


eth_getLogs

Returns logs matching a filter.

Parameters:

# Type Required Description
1 Object Yes Filter: {address?, topics?, fromBlock?, toBlock?}. Addresses use the canonical 0x-prefixed 64-hex-character Shell address form; topics can contain at most four positional entries. Topic entries are null, a 0x-prefixed 32-byte hash, or an array of 0x-prefixed 32-byte hashes. null is a positional wildcard; an empty alternatives array ([]) matches no logs at that position.

Unsupported filter fields are rejected as invalid parameters rather than ignored.

Returns: Array — Log objects with address, topics, data, blockNumber, blockHash, transactionHash, transactionIndex, logIndex, removed.

Uses bloom filters for fast block-level filtering. The block range is capped at MAX_BLOCK_RANGE to prevent DoS.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x0","toBlock":"latest"}],"id":1}'

eth_newFilter

Creates a poll-based log filter.

Parameters:

# Type Required Description
1 Object Yes Filter: {address?, topics?, fromBlock?, toBlock?}. Addresses use the canonical 0x-prefixed 64-hex-character Shell address form; topics can contain at most four positional entries. Topic entries are null, a 0x-prefixed 32-byte hash, or an array of 0x-prefixed 32-byte hashes. null is a positional wildcard; an empty alternatives array ([]) matches no logs at that position.

Unsupported filter fields are rejected as invalid parameters rather than ignored.

Returns: String — Filter ID.


eth_newBlockFilter

Creates a poll-based block filter.

Parameters: None

Returns: String — Filter ID.


eth_getFilterChanges

Returns changes since last poll for a filter. If the canonical chain is reorganized, log filters first return matching orphaned logs with removed: true, followed by matching logs from the replacement chain. Block filters return the canonical replacement block hashes.

Parameters:

# Type Required Description
1 String Yes Filter ID

Returns: Array — Logs (for log filters) or block hashes (for block filters). Logs from orphaned blocks have removed: true.


eth_getFilterLogs

Re-queries all logs matching a filter's criteria.

Parameters:

# Type Required Description
1 String Yes Filter ID

Returns: Array — Log objects.


eth_uninstallFilter

Removes a filter.

Parameters:

# Type Required Description
1 String Yes Filter ID

Returns: Boolean — true if the filter was removed.


eth_blobBaseFee

Returns the current blob gas price (EIP-4844).

Parameters: None

Returns: String — Hex-encoded blob gas price, calculated from excess_blob_gas.


eth_sign (not supported)

Returns error code -32601. The node does not hold private keys — sign transactions client-side with the CLI or SDK.

eth_signTransaction (not supported)

Returns error code -32601. Same reason as eth_sign.

eth_getCompilers

Returns []. This legacy Ethereum method is retained for compatibility.


net_ Namespace

net_version

Returns the network/chain ID as a decimal string.

Parameters: None

Returns: String — Chain ID (e.g., "1337").

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"net_version","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"1337"}

net_listening

Returns whether the node is accepting connections. Always true.

Parameters: None

Returns: Boolean — true.


net_peerCount

Returns the number of connected peers.

Parameters: None

Returns: String — Hex-encoded peer count (e.g., "0x3").

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}'

web3_ Namespace

web3_clientVersion

Returns the client identifier string.

Parameters: None

Returns: String — "shell-chain/0.27.4".

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"shell-chain/0.27.4"}

web3_sha3

Returns the Keccak-256 hash of the given data.

Parameters:

# Type Required Description
1 String Yes Hex-encoded data (max 32 KB)

Returns: String — Hex-encoded Keccak-256 hash.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f"],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8"}

shell_ Namespace

Shell-chain custom extensions for post-quantum features, validator governance, and node information.

shell_getPqPubkey

Returns the post-quantum public key associated with an address.

Parameters:

# Type Required Description
1 String Yes Address (0x... canonical)

Returns: String|null — Hex-encoded PQ public key, or null if not found.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_getPqPubkey","params":["0xYOUR_ADDRESS_HERE"],"id":1}'

shell_pendingCount

Returns the number of pending transactions in the mempool.

Parameters: None

Returns: String — Hex-encoded count.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_pendingCount","params":[],"id":1}'
{"jsonrpc":"2.0","id":1,"result":"0x0"}

shell_sendTransaction

Submits a pre-signed shell-chain transaction.

Parameters:

# Type Required Description
1 Object Yes Signed transaction object

Returns: String — Transaction hash.


shell_getValidators

Returns the current validator set.

Parameters: None

Returns: Array<String> — List of validator addresses.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_getValidators","params":[],"id":1}'
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    "0x0000000000000000000000000000000000000000000000000000000000000001",
    "0x0000000000000000000000000000000000000000000000000000000000000002"
  ]
}

shell_getValidatorStatus

Returns whether an address is a validator.

Parameters:

# Type Required Description
1 String Yes Address

Returns: Object:

{
  "address": "0x...",
  "isValidator": true
}

shell_proposeAddValidator

Submits a governance transaction to add a validator (requires the node to have a proposer keystore). On non-loopback RPC listeners, this signer-backed method is registered only when --rpc-api-key is configured.

Parameters:

# Type Required Description
1 String Yes Address to add

Returns: String — Transaction hash.


shell_proposeRemoveValidator

Submits a governance transaction to remove a validator. On non-loopback RPC listeners, this signer-backed method is registered only when --rpc-api-key is configured.

Parameters:

# Type Required Description
1 String Yes Address to remove

Returns: String — Transaction hash.


shell_encodeAddValidator

Generates calldata for the validator management system contract (does not submit a transaction).

Parameters:

# Type Required Description
1 String Yes Address to add

Returns: String — Hex-encoded calldata.


shell_encodeRemoveValidator

Generates calldata for validator removal.

Parameters:

# Type Required Description
1 String Yes Address to remove

Returns: String — Hex-encoded calldata.


shell_estimateGovernanceGas

Estimates gas for a governance operation.

Parameters:

# Type Required Description
1 String Yes Operation: "addValidator", "removeValidator", "getValidators", or "isValidator"

Returns: String — Hex-encoded gas estimate.


shell_getGovernanceInfo

Returns governance configuration.

Parameters: None

Returns:

{
  "validatorCount": 3,
  "validators": ["0x...", "0x...", "0x..."],
  "systemContractAddress": "0x0000000000000000000000000000000000000001",
  "proposalGasLimit": 100000
}

shell_getNodeInfo

Returns node status information.

Parameters: None

Returns:

{
  "version": "ShellChain/v0.27.4/rust",
  "chainId": 1337,
  "blockHeight": 42,
  "peerCount": 0,
  "txPoolSize": 5,
  "isMining": true,
  "uptime": 3600,
  "baseFee": "0x5f7609"
}
curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_getNodeInfo","params":[],"id":1}'

shell_getNetworkStats

Returns live P2P network statistics. peerCount uses the same connected-peer counter as net_peerCount. listeningAddress is an actual bound multiaddr: when several listeners are available, the first address in sorted order is returned. A configured port of zero is replaced by the assigned port. This local address does not establish reachability from another network. protocols lists enabled gossipsub, Kademlia and mDNS behaviours; disabled behaviours are omitted.

Parameters: None

Example result (address, peer count and protocols depend on the running node):

{
  "peerCount": 1,
  "protocolVersion": "shell/1.0.0",
  "listeningAddress": "/ip4/127.0.0.1/tcp/40123",
  "protocols": ["gossipsub", "kademlia"]
}

No bound listener yields an empty listeningAddress. With P2P disabled or its transport stopped, protocols is empty as well. Local transport metadata is rebuilt on startup rather than persisted; shell_getNodeInfo.peer_id and admin_nodeInfo.id read the same live identity.

Version: This correction is in unreleased node source. Older binaries may return the fixed default address and protocol list; verify the installed version before using this response to diagnose connectivity.

Local acceptance: From the node repository, build with the libp2p feature and run the existing Python 3 regression (standard library only):

cargo build -p shell-cli --features libp2p
python3 tests/e2e/operator-p2p-monitoring.py --network-stats

The script creates fresh test keys and isolated RocksDB nodes, connects a follower to a 16-block backlog, compares canonical block hashes and live RPC listeners, then restarts the follower with P2P enabled and disabled. Results and isolated data are retained at the printed temporary directory. This checks local connectivity and restart behaviour; the default script mode separately checks transient catch-up monitoring.


shell_getChainStats

Returns aggregate chain statistics. totalTransactions and gasUsedTotal cover the canonical chain from block 0 through the current head; avgBlockTime is computed from the most recent block-time window.

Parameters: None

Returns:

{
  "blockHeight": 1500,
  "totalTransactions": 3200,
  "avgBlockTime": 2.01,
  "gasUsedTotal": "0x...",
  "latestBaseFee": "0x5f7609"
}

shell_getFinalityInfo

Returns finality status for the connected node.

Parameters: None

Returns:

{
  "currentHead": "0x1a",
  "finalityLag": 2,
  "lastFinalizedBlock": "0x18",
  "lastFinalizedHash": "0xabc...",
  "pendingAttestations": 2
}

shell_finalityProof

Returns a wrapper object for a finalized block hash. The certificate field maps validator addresses to post-quantum signatures and is null when the local node has no certificate for the requested hash.

Parameters:

# Type Required Description
1 String Yes Block hash

Returns:

{
  "blockHash": "0xabc...",
  "certificate": {
    "0x...": {
      "sig_type": "Dilithium3",
      "data": [1, 2, 3]
    }
  }
}

shell_getBlockSigners

Returns the post-quantum signature details for validators who signed a specific block.

Unreleased node source implements this method using authenticated proposer and quorum signing evidence. It retains the signing public keys and signatures separately from the header, so block hashes and consensus messages are unchanged. Retained evidence remains queryable after body pruning and changes to the live key lookup. signatureValid checks the actual signature against the captured block hash and the native signer identity; it reports historical cryptographic validity, independent of whether that algorithm may accept new transactions now.

Legacy intact blocks and certificates remain queryable when the matching identity-bound key is available. Missing historical keys or proposer evidence return an error; current rotated keys are never substituted. Genesis without signatures returns an empty signer list. Invalid block tags and missing blocks are rejected. The query does not change chain state. Published node versions must be verified before relying on this method.

From a source checkout, run the self-contained production, import, HTTP, pruning and fresh-process recovery regression:

cargo test -p shell-node --features rocksdb block_signers -- --nocapture

Parameters:

# Type Required Description
1 String Yes Block number (hex) or block tag

Tags select stored canonical headers: latest and pending use the current head, safe and finalized use the finalized cursor, and earliest selects genesis. The method does not fabricate signatures for an unsealed candidate.

Returns:

{
  "blockNumber": "0x1a",
  "signers": [
    {
      "address": "0x<64 lowercase hex>",
      "pqPubkey": "0x...",
      "signatureValid": true
    }
  ]
}
curl -s http://localhost:8545 -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_getBlockSigners","params":["latest"],"id":1}'

shell_verifyPqSignature

Verifies an ML-DSA-65 post-quantum signature against a message and public key. Unreleased node source also preserves the legacy Dilithium3 verification promise using the existing core verifier. This three-parameter query accepts raw signature and key bytes and reports cryptographic validity; it does not determine a native account identity or authorize a transaction. Algorithm registry rules, signing domains and account permissions are unchanged.

All three values must be 0x-prefixed, whole-byte hexadecimal strings. 0x is a valid empty message. Malformed hex returns -32602; invalid keys, unsupported raw formats, incorrect signature lengths and cryptographic mismatches return false. The query does not write chain state and follows the configured shell namespace exposure. The server's existing request-body limits apply. Published node versions must be verified before relying on this method.

From a source checkout, run the self-contained real-key HTTP regression. On Unix platforms it also runs the example below, using curl and a POSIX shell with temporary keys held in memory:

cargo test -p shell-rpc verify_pq_signature -- --nocapture

Parameters:

# Type Required Description
1 String Yes Hex-encoded message
2 String Yes Hex-encoded ML-DSA-65 or legacy Dilithium3 signature
3 String Yes Hex-encoded public key

Returns: Boolean — true if the signature is valid.

# Set SIGNATURE_HEX and PUBKEY_HEX to the actual 0x-prefixed raw signature
# and public key for the message "hello" (0x68656c6c6f).
curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d "{\"jsonrpc\":\"2.0\",\"method\":\"shell_verifyPqSignature\",\"params\":[\"0x68656c6c6f\",\"$SIGNATURE_HEX\",\"$PUBKEY_HEX\"],\"id\":1}"

shell_getEpochInfo

Returns information about the current consensus epoch.

Unreleased node source reads the canonical head and configured consensus engine. currentEpoch refers to the head's epoch, rather than the next proposer slot. For a positive epochLength, blocksInEpoch is the head's zero-based block offset within that epoch. With length zero, epochs are disabled: currentEpoch is zero and blocksInEpoch is the head height. activeValidators counts the engine's active authorities, which can differ from pending head Registry changes. currentBlockTime is the mean timestamp interval over up to ten canonical intervals ending at the head, or zero at genesis. Missing engine, head or required canonical history returns an error. The query needs retained headers, not block bodies, and does not write state. Published node versions must be checked before relying on this method.

From a node source checkout, run the isolated HTTP regression and the existing signed execution/import fixture, which also checks this query after body pruning and an abrupt child-process exit followed by RocksDB recovery:

cargo test -p shell-rpc epoch_info -- --nocapture
cargo test -p shell-node --features rocksdb fee_history_rewards -- --nocapture

The isolated regression covers genesis, length-five boundaries, continuous epochs, active-engine counts, invalid context and unchanged state. On Unix it also runs the curl example below and requires curl and a POSIX shell. The recovery fixture uses real legacy Dilithium3 signed transactions and continuous epochs; it does not prove every algorithm, nonzero-epoch recovery, network reorganization or machine power-loss combination.

For nonzero epochs with pending Registry changes, the existing two-node acceptance also checks this query before and after follower restarts. It uses real ML-DSA-65 signed weight, addition and removal transactions, length-five boundaries and restarts at heights 7, 12, 17 and 21. Both nodes must report the canonical epoch and active member count, even when the head Registry already contains a pending addition or removal; repeated queries must preserve state. The final restarted follower also runs the curl example below. Follow the epoch acceptance prerequisites in docs/CONSENSUS_DETAILS.md, including Node.js 20 or later, curl, a POSIX shell and a compatible built source SDK (0.14.0-rc.1 tested):

cargo build -p shell-cli --features libp2p
SHELL_SDK_ENTRY=/path/to/shell-sdk/dist/index.js \
node tests/e2e/native-aa-registry.mjs --epoch-restart

For a follower with actual rolling state and body pruning, run the same acceptance with:

SHELL_SDK_ENTRY=/path/to/shell-sdk/dist/index.js \
node tests/e2e/native-aa-registry.mjs --epoch-pruned-restart

This variant retains all data on the producer and uses a light follower with one-block state/body retention. It checks that expired bodies remain absent, including after the final restart at an idle head, while the last finalized epoch snapshot still supplies its historical nonce and active authorities. Expired historical state must return an error rather than current values. The shortened window proves this isolated case, not the default retention window or public package availability.

This case uses one producer retaining quorum weight and graceful follower restarts with unchanged genesis. It does not establish multi-authority availability, network reorganization, machine power-loss recovery or public SDK/binary delivery.

Parameters: None

Returns:

{
  "currentEpoch": 0,
  "epochLength": 0,
  "blocksInEpoch": 1500,
  "currentBlockTime": 2.01,
  "activeValidators": 3
}
curl -s http://localhost:8545 -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_getEpochInfo","params":[],"id":1}'

shell_getValidatorVotes

Returns voting activity statistics for validators in recent blocks.

Parameters: None

Returns:

{
  "validators": [
    {
      "address": "0x...",
      "blocksProduced": 500,
      "lastBlockProduced": "0x1a",
      "uptime": 99.8
    }
  ]
}

shell_getPendingGovernanceProposals

Returns pending governance proposals that have not yet been finalized.

Parameters: None

Returns:

{
  "proposals": [
    {
      "type": "addValidator",
      "target": "0x...",
      "proposer": "0x...",
      "proposedAt": "0x18",
      "status": "pending"
    }
  ]
}

shell_addValidator / shell_removeValidator (disabled)

These methods return error -32601. Direct validator set mutation is disabled to prevent split-brain issues. Use shell_proposeAddValidator and shell_proposeRemoveValidator instead, which go through the governance transaction flow.

shell_transactionCount

Returns the total number of transactions stored across all blocks (chain-wide counter, not per-address nonce).

Parameters: none

Response: "0x<hex>" — total transaction count as a hex string.

curl -s http://localhost:8545 -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_transactionCount","params":[],"id":1}'
# → {"result":"0x1a4f"}

shell_getTransactionsByAddress

Returns transactions sent from or received by an address. Supports pagination and inclusive block-range filters. There is no artificial deep-offset cap; under live load, clients should pin toBlock from the first page and reuse it for older pages to avoid gaps or duplicates while new blocks arrive.

Unreleased node source accepts legacy offsets above 10,000 and exact totals over ranges spanning more than 10,000 blocks, including the default 0 through latest range. Pages past the exact range total return an empty transactions list while retaining pagination metadata. Overflowing page * limit remains invalid. Counts and pages use the existing retained address index without query writes or an index migration. The v2 address-history and address-summary methods use the same exact counter when includeTotal is enabled. Published node versions must be checked before relying on these corrections.

From a node source checkout, run the real stored-index HTTP regression and the native storage regressions. They cover sender and recipient history, deep ordering, wide default ranges, empty pages, shared exact totals, unchanged chain state, and forward-only index reads after RocksDB reopen. On Unix, the HTTP regression also executes the curl example below and requires curl and a POSIX shell. These regressions do not run block production or transaction admission:

cargo test -p shell-rpc address_history_deep_pages_http -- --nocapture
cargo test -p shell-storage --features rocksdb address_history -- --nocapture

Parameters:

Name Type Description
address string 0x... address
fromBlock number | null Start block (inclusive, default 0)
toBlock number | null End block (inclusive, default latest)
page number | null Page index, 0-based (default 0)
limit number | null Results per page (default 20)

Response: paginated object:

Field Type Description
address string Queried 0x... address
fromBlock string Effective inclusive lower block bound, hex encoded
toBlock string Effective inclusive upper block snapshot, hex encoded
page number Page index, 0-based
limit number Page size
total number Total matches in the requested range
transactions array Transaction summaries, including shellType/reward metadata when present
curl -s http://localhost:8545 -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_getTransactionsByAddress","params":["0x0000000000000000000000000000000000000000000000000000000000000000",0,null,0,20],"id":1}'

shell_getBlockWitnesses

Returns the PQ witness bundle for a block — the individual Dilithium3 signatures stored separately from TX bodies. Returns null when witnesses have been pruned (STARK proof received) or the block predates B3 storage.

Parameters:

Name Type Description
block string Block hash (0x...) or block number ("0x<hex>" / "latest")

Response fields:

Field Type Description
blockHash string Block hash
witnessRoot string witness_root from block header
witnessCount number Number of witnesses in bundle
witnesses array [{ txIndex, sigType, signature, pubkey? }, ...]

Returns null when no witness bundle is stored (pruned or not applicable).

curl -s http://localhost:8545 -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_getBlockWitnesses","params":["latest"],"id":1}'

shell_setBalance (dev/testnet only)

Directly sets the balance of an address. Only available when api_modules includes dev. Returns -32601 on production nodes.

Parameters:

Name Type Description
address string Target 0x... address
balance string New balance in wei as decimal string

Response: true on success.

curl -s http://localhost:8545 -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"shell_setBalance","params":["0xabc...","1000000000000000000"],"id":1}'

debug_ Namespace

Note: The debug namespace must be explicitly enabled via --rpc-api eth,net,web3,shell,debug. It is not enabled by default on validator nodes.

debug_traceTransaction

Replays a transaction and returns an execution trace.

Parameters:

# Type Required Description
1 String Yes Transaction hash
2 Object No Trace options. Only tracer: "callTracer" is supported; unknown options are rejected.

Returns:

{
  "frame": {
    "type": "CALL",
    "from": "0x...",
    "to": "0x...",
    "gas": 21000,
    "gasUsed": 21000,
    "input": "0x",
    "output": "0x",
    "value": "0xde0b6b3a7640000",
    "error": null
  },
  "failed": false
}
curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"debug_traceTransaction","params":["0xabc123..."],"id":1}'

debug_traceBlockByNumber

Traces all transactions in a block.

Parameters:

# Type Required Description
1 String Yes Block number (hex) or block tag
2 Object No Trace options. Only tracer: "callTracer" is supported; unknown options are rejected.

Returns: Array — Array of trace result objects (one per transaction).

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"debug_traceBlockByNumber","params":["0x1a"],"id":1}'

trace_ Namespace

OpenEthereum-shaped call and creation traces from isolated historical execution. trace_transaction and its trace_oeTransaction alias return the root and nested frames in depth-first order. traceAddress identifies each frame; subtraces counts its immediate children. Calls include actual return data; creations use action.init and result.code/result.address. Failed frames contain error and omit result. AA bundles use a root call with callType: "batch" and their executed calls as children; this is a Shell-specific extension.

Replay requires retained parent state and matching receipts. AccountManager rotateKey and clearValidationCode are replayable and return actual native output and gas without opcode logs. Guardian, recovery and validation-code changes also support replay, including earlier transactions in the same block, using a consistent metadata snapshot and the original parent height. These methods require history within the latest 128 blocks, retained undo journals, and a native metadata snapshot no larger than 64 MiB. Upgrades do not restore already-pruned journals. ValidatorRegistry governance calls use the same native history bounds. Replay uses historical validator/public-key state and parent height; algorithm changes stay in the worker's private registry. Missing history and capture/response limits return an RPC error instead of a receipt-derived approximation. PQVM removes SELFDESTRUCT and CALLCODE, so they do not produce successful externality events. The same capture and concurrency bounds as debug_ apply.

Note: Like debug, the trace namespace must be explicitly enabled via --rpc-api.

trace_block

Returns traces for all transactions in a block.

Parameters:

# Type Required Description
1 String Yes Block number (hex) or block tag

Returns: Array — OpenEthereum-format trace objects.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"trace_block","params":["latest"],"id":1}'

trace_oeTransaction

Alias for trace_transaction, with the same parameters and executed frame list.

Parameters:

# Type Required Description
1 String Yes Transaction hash

Returns: Array — Root and nested call/creation traces for the transaction.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"trace_oeTransaction","params":["0xabc123..."],"id":1}'

trace_transaction

Returns the trace for a specific transaction in standard format.

Parameters:

# Type Required Description
1 String Yes Transaction hash

Returns: Array — Trace objects for the transaction.

curl -s http://localhost:8545 \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"trace_transaction","params":["0xabc123..."],"id":1}'

shell_getAlgorithmRegistry

Returns the live algorithm registry as an array of objects: { algo, status, description }.

Status is active, deprecated, or pending_activation. At startup, the node restores this registry from the recovered canonical world state before starting RPC and transaction admission. Restarting does not activate pending algorithms, reset deprecated entries, or change saved proposal heights and verifier hashes. Malformed persisted registry state prevents startup instead of falling back to the compile-time active allowlist. Chains without governance entries retain the initial allowlist.

Parameters: None

Returns: Array — one entry per registered signature algorithm.

[
  {
    "algo": "MlDsa65",
    "description": "FIPS 204 ML-DSA-65 (NIST post-quantum standard; primary algorithm)",
    "status": "active"
  },
  {
    "algo": "Dilithium3",
    "description": "CRYSTALS-Dilithium3 (Round-3 pre-FIPS; active for legacy compatibility)",
    "status": "active"
  }
]

shell_getProofAmendment

Returns the STARK proof amendment for a block if one has been generated asynchronously. See stark-aggregation.md for the full response schema.

Parameters:

# Type Required Description
1 String Yes Block hash (0x...)

Returns: Object|null — Proof amendment object or null if not yet generated.


shell_estimateBatch

Estimates gas for an AA batch transaction.

Parameters:

# Type Required Description
1 Object Yes Batch transaction object

Returns: String — Hex-encoded gas estimate.


shell_getPaymasterPolicy

Returns the paymaster policy for a given paymaster address.

Parameters:

# Type Required Description
1 String Yes Paymaster address (0x..., 32 bytes)

Returns: Object|null — Policy object or null if no policy registered.


shell_isSponsored

Returns whether a transaction would be sponsored by a paymaster.

Parameters:

# Type Required Description
1 Object Yes Transaction object

Returns: Boolean — true if the transaction would be sponsored.


shell_consensusInfo

Returns current consensus engine state.

Parameters: None

Returns:

{
  "engine": "wpoa",
  "currentProposer": "0x...",
  "epochNumber": 5,
  "validatorCount": 3,
  "finalizedHeight": "0x18"
}

Method Summary

For the canonical method list (currently 79 methods across web3_, net_, eth_, debug_, trace_, evm_, shell_ namespaces), see docs/rpc-reference.md, which is auto-generated from crates/rpc/src/api.rs.


Last updated: 2026-06-17