Daemon JSON-RPC Methods¶
Every method the daemon answers on /json_rpc, with the RPC mode each needs and a worked example.
Implementation mapping: src/rpc/RpcServer.cpp method switch in /json_rpc dispatcher.
/json_rpc accepts JSON with a method field. Current methods:
| Method | Handler | Permission Mode |
|---|---|---|
getblocktemplate | getBlockTemplate | Standard |
submitblock | submitBlock | Standard |
getblockcount | getBlockCount | Standard |
getlastblockheader | getLastBlockHeader | Standard |
getblockheaderbyhash | getBlockHeaderByHash | Standard |
getblockheaderbyheight | getBlockHeaderByHeight | Standard |
f_blocks_list_json | getBlocksByHeight | Explorer |
f_block_json | getBlockDetailsByHash | Explorer |
f_transaction_json | getTransactionDetailsByHash | Explorer |
f_on_transactions_pool_json | getTransactionsInPool | Explorer |
f_transactions_by_payment_id_json | getTransactionHashesByPaymentId | Explorer |
Unknown methods return 404.
Request shape¶
Example:
Use X-API-Key or Authorization: Bearer header when rpc-access-token is enabled.
Response shape¶
The response carries back the id of the request it answers, as JSON-RPC 2.0 requires, in whatever type it was sent:
A request that sends no id gets an answer without one. Errors carry the same id alongside an error object, and still return HTTP 200:
Method Examples¶
All examples call POST /json_rpc.
getblockcount:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"1","method":"getblockcount","params":{}}' \
"$DAEMON_RPC_URL/json_rpc"
getlastblockheader:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"2","method":"getlastblockheader","params":{}}' \
"$DAEMON_RPC_URL/json_rpc"
getblockheaderbyhash:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"3","method":"getblockheaderbyhash","params":{"hash":"<block-hash-64-hex>"}}' \
"$DAEMON_RPC_URL/json_rpc"
getblockheaderbyheight:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"4","method":"getblockheaderbyheight","params":{"height":12345}}' \
"$DAEMON_RPC_URL/json_rpc"
getblocktemplate:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"5","method":"getblocktemplate","params":{"reserve_size":8,"wallet_address":"<miner-address>"}}' \
"$DAEMON_RPC_URL/json_rpc"
params takes the reserved space either way round:
reserve_size— how many bytes to leave blank in the miner transaction's extra. The reply'sreserved_offsetsays where they are, and the caller fills them in. This is what a pool wants.extra_nonce— hex bytes to embed directly, in which case the node reserves exactly that much and writes them for you. This is what Monero-lineage solo miners send, and they send noreserve_sizeat all.
Sending neither gets a template with no reserved bytes. Sending both uses extra_nonce. Maximum 255 bytes either way.
The reply carries blocktemplate_blob, difficulty, height, reserved_offset and status.
Before you mine the template¶
The template is not ready to hash as returned. For every block version above 1 the node appends a placeholder merge-mining tag to the parent block's coinbase and does not fill it in — whoever mines the block is expected to. Set mmTag.depth = 0 and mmTag.merkleRoot to the block's auxiliary header hash (CachedBlock::getAuxiliaryBlockHeaderHash(), equivalently getMerkleRoot() in src/miner/BlockUtilities.cpp), clear the parent coinbase's extra, and write the tag back. adjustMergeMiningTag() in src/miner/MinerManager.cpp is the reference implementation.
Skip this and submitblock rejects the finished block with "Proof of work is too weak", no matter how good the proof of work was. That error covers four distinct failures in Currency::checkProofOfWorkV2 — genuinely weak work, a missing merge-mining tag, an over-long blockchain branch, and this mismatch — and only the first is about difficulty. The daemon log tells them apart: the tag failures print Aux block hash wasn't found in merkle tree or merge mining tag wasn't found ... just before the rejection, and genuinely weak work prints nothing extra.
Do this before computing the hashing blob: the tag lives in the parent coinbase, and the parent's merkle root is part of what gets hashed. Rolling the nonce afterwards is safe — the nonce is not part of what the tag commits to.
submitblock:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"6","method":"submitblock","params":["<block-blob-hex>"]}' \
"$DAEMON_RPC_URL/json_rpc"
f_blocks_list_json:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"7","method":"f_blocks_list_json","params":{"height":100000}}' \
"$DAEMON_RPC_URL/json_rpc"
f_block_json:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"8","method":"f_block_json","params":{"hash":"<block-hash-64-hex>"}}' \
"$DAEMON_RPC_URL/json_rpc"
f_transaction_json:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"9","method":"f_transaction_json","params":{"hash":"<tx-hash-64-hex>"}}' \
"$DAEMON_RPC_URL/json_rpc"
f_on_transactions_pool_json:
curl -s -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":"10","method":"f_on_transactions_pool_json","params":{}}' \
"$DAEMON_RPC_URL/json_rpc"
Unknown method example (404):