oxen-core/src/rpc/core_rpc_server_commands_de...

2862 lines
121 KiB
C++

// Copyright (c) 2018-2020, The Loki Project
// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
// vim help for nicely wrapping/formatting comments in here:
// Global options for wrapping and indenting lists within comments with gq:
//
// set formatoptions+=n
// set formatlistpat=^\\s*\\d\\+[\\]:.)}\\t\ ]\\s\\+\\\\|^\\s*[-+*]\\s\\+
//
// cpp-specific options to properly recognize `///` as a comment when wrapping, to go in
// ~/.vim/after/ftplugin/cpp.vim:
//
// setlocal comments-=://
// setlocal comments+=:///
// setlocal comments+=://
#include "rpc/common/rpc_version.h"
#include "rpc/common/command_decorators.h"
#include "crypto/crypto.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "epee/string_tools.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/verification_context.h"
#include "cryptonote_basic/difficulty.h"
#include "crypto/hash.h"
#include "cryptonote_config.h"
#include "cryptonote_core/service_node_voting.h"
#include "cryptonote_core/service_node_list.h"
#include "common/varint.h"
#include "common/meta.h"
#include "common/hex.h"
#include "checkpoints/checkpoints.h"
#include "cryptonote_core/service_node_quorum_cop.h"
#include "cryptonote_core/service_node_list.h"
#include "common/oxen.h"
#include <nlohmann/json.hpp>
#include <oxenc/bt_serialize.h>
#include <type_traits>
#include <unordered_set>
namespace cryptonote {
void to_json(nlohmann::json& j, const checkpoint_t& c);
}
namespace service_nodes {
void to_json(nlohmann::json& j, const key_image_blacklist_entry& b);
void to_json(nlohmann::json& j, const quorum_signature& s);
}
/// Namespace for core RPC commands. Every RPC commands gets defined here (including its name(s),
/// access, and data type), and added to `core_rpc_types` list at the bottom of the file.
namespace cryptonote::rpc {
// When making *any* change here, bump minor
// If the change is incompatible, then bump major and set minor to 0
// This ensures rpc::VERSION always increases, that every change
// has its own version, and that clients can just test major to see
// whether they can talk to a given daemon without having to know in
// advance which version they will stop working with
constexpr version_t VERSION = {4, 1};
const static std::string
STATUS_OK = "OK",
STATUS_FAILED = "FAILED",
STATUS_BUSY = "BUSY",
STATUS_NOT_MINING = "NOT MINING",
STATUS_TX_LONG_POLL_TIMED_OUT = "Long polling client timed out before txpool had an update";
/// RPC: blockchain/get_height
///
/// Get the node's current height.
///
/// Inputs: none.
///
/// Outputs:
///
/// - `height` -- The current blockchain height according to the queried daemon.
/// - `status` -- Generic RPC error code. "OK" is the success value.
/// - `hash` -- Hash of the block at the current height
/// - `immutable_height` -- The latest height in the blockchain that cannot be reorganized
/// because of a hardcoded checkpoint or 2 SN checkpoints. Omitted if not available.
/// - `immutable_hash` -- Hash of the highest block in the chain that cannot be reorganized.
///
/// Example-JSON-Fetch
struct GET_HEIGHT : PUBLIC, LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("get_height", "getheight"); }
};
/// RPC: blockchain/get_transactions
///
/// Look up one or more transactions by hash.
///
/// Inputs:
///
/// - `tx_hashes` -- List of transaction hashes to look up. (Will also be accepted as json input
/// key `"txs_hashes"` for backwards compatibility). Exclusive of `memory_pool`.
/// - `memory_pool` -- If true then return all transactions and spent key images currently in the
/// memory pool. This field is exclusive of `tx_hashes`.
/// - `tx_extra` -- If set to true then parse and return tx-extra information
/// - `tx_extra_raw` -- If set to true then include the raw tx-extra information in the
/// `tx_extra_raw` field. This will be hex-encoded for json, raw bytes for bt-encoded requests.
/// - `data` -- Controls whether the `data` (or `pruned`, if pruned) field containing raw tx data
/// is included. By default it is not included; you typically want `details` rather than this
/// field.
/// - `split` -- If set to true then always split transactions into non-prunable and prunable
/// parts in the response.
/// - `prune` -- Like `split`, but also omits the prunable part of transactions from the response
/// details.
///
/// Outputs:
///
/// - `status` -- Generic RPC error code. "OK" is the success value.
/// - `missed_tx` -- set of transaction hashes that were not found. If all were found then this
/// field is omitted. There is no particular ordering of hashes in this list.
/// - `txs` -- list of transaction details; each element is a dict containing:
/// - `tx_hash` -- Transaction hash.
/// - `size` -- Size of the transaction, in bytes. Note that if the transaction has been pruned
/// this is the post-pruning size, not the original size.
/// - `in_pool` -- Will be set to true if the transaction is in the transaction pool (`true`)
/// and omitted if mined into a block.
/// - `blink` -- True if this is an approved, blink transaction; this information is generally
/// only available for approved in-pool transactions and txes in very recent blocks.
/// - `fee` -- the transaction fee (in atomic OXEN) incurred in this transaction (not including
/// any burned amount).
/// - `burned` -- the amount of OXEN (in atomic units) burned by this transaction.
/// - `block_height` -- Block height including the transaction. Omitted for tx pool
/// transactions.
/// - `block_timestamp` -- Unix time at which the block has been added to the blockchain.
/// Omitted for tx pool transactions.
/// - `output_indices` -- List of transaction indexes. Omitted for tx pool transactions.
/// - `relayed` -- For `in_pool` transactions this field will be set to indicate whether the
/// transaction has been relayed to the network.
/// - `double_spend_seen` -- Will be set to true for tx pool transactions that are
/// double-spends (and thus cannot be added to the blockchain). Omitted for mined
/// transactions.
/// - `received_timestamp` -- Timestamp transaction was received in the pool. Omitted for
/// mined blocks.
/// - `max_used_block` -- the hash of the highest block referenced by this transaction; only
/// for mempool transactions.
/// - `max_used_height` -- the height of the highest block referenced by this transaction; only
/// for mempool transactions.
/// - `last_failed_block` -- the hash of the last block where this transaction was attempted to
/// be mined (but failed).
/// - `max_used_height` -- the height of the last block where this transaction failed to be
/// acceptable for a block.
/// - `weight` -- the transaction "weight" which is the size of the transaction with padding
/// removed. Only included for mempool transactions (for mined transactions the size and
/// weight at the same and so only `size` is included).
/// - `kept_by_block` will be present and true if this is a mempool transaction that was added
/// to the mempool after being popped off a block (e.g. because of a blockchain
/// reorganization).
/// - `last_relayed_time` indicates the last time this block was relayed to the network; only
/// for mempool transactions.
/// - `do_not_relay` -- set to true for mempool blocks that are marked "do not relay"
/// - `double_spend_seen` -- set to true if one or more outputs in this mempool transaction
/// have already been spent (and thus the tx cannot currently be added to the blockchain).
/// - `data` -- Full, unpruned transaction data. For a json request this is hex-encoded; for a
/// bt-encoded request this is raw bytes. This field is omitted if any of `tx_extra`,
/// `split`, or `prune` is requested; or if the transaction has been pruned in the database.
/// - `pruned` -- The non-prunable part of the transaction, encoded as hex (for json requests).
/// Always included if `split` or `prune` are specified; without those options it will be
/// included instead of `data` if the transaction has been pruned.
/// - `prunable` -- The prunable part of the transaction. Only included when `split` is
/// specified, the transaction is prunable, and the tx has not been pruned from the database.
/// - `prunable_hash` -- The hash of the prunable part of the transaction. Will be provided if
/// either: the tx has been pruned; or the tx is prunable and either of `prune` or `split` are
/// specified.
/// - `extra` -- Parsed "extra" transaction information; omitted unless specifically requested
/// (via the `tx_extra` request parameter). This is a dict containing one or more of the
/// following keys.
/// - `pubkey` -- The tx extra public key
/// - `burn_amount` -- The amount of OXEN that this transaction burns, if any.
/// - `extra_nonce` -- Optional extra nonce value (in hex); will be empty if nonce is
/// recognized as a payment id
/// - `payment_id` -- The payment ID, if present. This is either a 16 hex character (8-byte)
/// encrypted payment id, or a 64 hex character (32-byte) deprecated, unencrypted payment ID
/// - `mm_depth` -- (Merge-mining) the merge-mined depth
/// - `mm_root` -- (Merge-mining) the merge mining merkle root hash
/// - `additional_pubkeys` -- Additional public keys
/// - `sn_winner` -- Service node block reward winner public key
/// - `sn_pubkey` -- Service node public key (e.g. for registrations, stakes, unlocks)
/// - `sn_contributor` -- Service node contributor wallet address (for stakes)
/// - `tx_secret_key` -- The transaction secret key, included in registrations/stakes to
/// decrypt transaction amounts and recipients
/// - `locked_key_images` -- Key image(s) locked by the transaction (for registrations,
/// stakes)
/// - `key_image_unlock` -- A key image being unlocked in a stake unlock request (an unlock
/// will be started for *all* key images locked in the same SN contributions).
/// - `sn_registration` -- Service node registration details; this is a dict containing:
/// - `fee` the operator fee expressed in millionths (i.e. 234567 == 23.4567%)
/// - `expiry` the unix timestamp at which the registration signature expires
/// - `contributors`: dict of (wallet => portion) pairs indicating the staking portions
/// reserved for the operator and any reserved contribution spots in the registration.
/// Portion is expressed in millionths (i.e. 250000 = 25% staking portion).
/// - `sn_state_change` -- Information for a "state change" transaction such as a
/// deregistration, decommission, recommission, or ip change reset transaction. This is a
/// dict containing:
/// - `old_dereg` will be set to true if this is an "old" deregistration transaction
/// (before the Loki 4 hardfork), omitted for more modern state change txes.
/// - `type` string indicating the state change type: "dereg", "decomm", "recomm", or "ip"
/// for a deregistration, decommission, recommission, or ip change penalty transaction.
/// - `height` the voting block height for the changing service node and voting service
/// nodes that produced this state change transaction.
/// - `index` the position of the affected node in the random list of tested nodes for this
/// `height`.
/// - `voters` the positions of validators in the testing quorum for this `height` who
/// tested and voted for this state change. This typically contains the first 7 voters
/// who voted for the state change (out of a possible set of 10).
/// - `reasons` list of reported reasons for a decommission or deregistration as reported
/// by the voting quorum. This contains any reasons that all 7+ voters agreed on, and
/// contains one or more of:
/// - `"uptime"` -- the service node was missing uptime proofs
/// - `"checkpoints"` -- the service node missed too many recent checkpoint votes
/// - `"pulse"` -- the service node missed too many recent pulse votes
/// - `"storage"` -- the service node's storage server was unreachable for too long
/// - `"lokinet"` -- the service node's lokinet router was unreachable for too long
/// - `"timecheck"` -- the service node's oxend was not reachable for too many recent
/// time synchronization checks. (This generally means oxend's quorumnet port is not
/// reachable).
/// - `"timesync"` -- the service node's clock was too far out of sync
/// The list is omitted entirely if there are no reasons at all or if there are no reasons
/// that were agreed upon by all voting service nodes.
/// - `reasons_maybe` list of reported reasons that some but not all service nodes provided
/// for the deregistration/decommission. Possible values are identical to the above.
/// This list is omitted entirely if it would be empty (i.e. there are no reasons at all,
/// or all voting service nodes agreed on all given reasons).
/// - `ons` -- ONS registration or update transaction details. This contains keys:
/// - `buy` -- set to true if this is an ONS buy record; omitted otherwise.
/// - `update` -- set to true if this is an ONS record update; omitted otherwise.
/// - `renew` -- set to true if this is an ONS renewal; omitted otherwise.
/// - `type` -- the ONS request type string. For registrations: "lokinet", "session",
/// "wallet"; for a record update: "update".
/// - `blocks` -- The registration length in blocks; omitted for registrations (such as
/// Session/Wallets) that do not expire.
/// - `name_hash` -- The hashed name of the record being purchased/updated. Encoded in hex
/// for json requests. Note that the actual name is not provided on the blockchain.
/// - `prev_txid` -- For an update this field is set to the txid of the previous ONS update
/// or registration (i.e. the most recent transaction that this record is updating).
/// - `value` -- The encrypted value of the record (in hex for json requests) being
/// set/updated. See [`ons_resolve`](#ons_resolve) for details on encryption/decryption.
/// - `owner` -- the owner of this record being set in a registration or update; this can
/// be a primary wallet address, wallet subaddress, or a plain public key.
/// - `backup_owner` -- an optional backup owner who also has permission to edit the
/// record.
/// - `stake_amount` -- Set to the calculated transaction stake amount (only applicable if the
/// transaction is a service node registration or stake).
/// - `mempool_key_images` -- dict of spent key images of mempool transactions. Only included
/// when `memory_pool` is set to true. Each key is the key image (in hex, for json requests)
/// and each value is a list of transaction hashes that spend that key image (typically just
/// one, but in the case of conflicting transactions there can be multiple).
struct GET_TRANSACTIONS : PUBLIC, LEGACY
{
static constexpr auto names() { return NAMES("get_transactions", "gettransactions"); }
struct request_parameters
{
std::vector<crypto::hash> tx_hashes;
bool memory_pool = false;
bool tx_extra = false;
bool tx_extra_raw = false;
bool data = false;
bool split = false;
bool prune = false;
} request;
};
/// RPC: daemon/get_transaction_pool
///
/// DEPRECATED. This endpoint is for backwards compatibility for old clients obtaining
/// transactions in the transaction pool. The replacement is to use `get_transactions` with
/// `"memory_pool": true`.
///
/// Inputs:
///
/// - Takes all the same inputs as get_transactions, except for `memory_pool` and `tx_hashes`.
///
/// Outputs:
///
/// - Same as get_transactions with `"memory_pool": true`.
struct GET_TRANSACTION_POOL : GET_TRANSACTIONS
{
static constexpr auto names() { return NAMES("get_transaction_pool"); }
};
/// RPC: blockchain/is_key_image_spent
///
/// Queries whether outputs have been spent using the key image associated with the output.
///
/// Inputs:
///
/// - `key_images` -- list of key images to check. For json requests these must be hex or
/// base64-encoded; for bt-requests they can be hex/base64 or raw bytes.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `spent_status` -- array of status codes returned in the same order as the `key_images` input.
/// Each value is one of:
/// - `0` -- the key image is unspent
/// - `1` -- the key image is spent in a mined block
/// - `2` -- the key image is spent in a transaction currently in the mempool
struct IS_KEY_IMAGE_SPENT : PUBLIC, LEGACY
{
static constexpr auto names() { return NAMES("is_key_image_spent"); }
enum class SPENT : uint8_t {
UNSPENT = 0,
BLOCKCHAIN = 1,
POOL = 2,
};
struct request_parameters {
std::vector<crypto::key_image> key_images;
} request;
};
/// RPC: blockchain/get_outs
///
/// Retrieve transaction outputs
///
/// Inputs:
///
/// - `outputs` -- Array of output indices. For backwards compatibility these may also be passed as
/// an array of {"amount":0,"index":n} dicts.
/// - `get_txid` -- Request the TXID (i.e. hash) of the transaction as well.
/// - `as_tuple` -- Requests the returned outs variable as a tuple of values rather than a dict.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `outs` -- List of outkey information; if `as_tuple` is not set then these are dicts containing
/// keys:
/// - `key` -- The public key of the output.
/// - `mask`
/// - `unlocked` -- States if output is locked (`false`) or not (`true`).
/// - `height` -- Block height of the output.
/// - `txid` -- Transaction id; only present if requested via the `get_txid` parameter.
/// Otherwise, when `as_tuple` is set, these are 4- or 5-element arrays (depending on whether
/// `get_txid` is desired) containing the values in the order listed above.
struct GET_OUTPUTS : PUBLIC, LEGACY
{
static constexpr auto names() { return NAMES("get_outs"); }
/// Maximum outputs that may be requested in a single request (unless admin)
static constexpr size_t MAX_COUNT = 5000;
struct request_parameters
{
bool get_txid = false;
bool as_tuple = false;
std::vector<uint64_t> output_indices;
} request;
};
/// RPC: blockchain/submit_transaction
///
/// Submit a transaction to be broadcast to the network.
///
/// Inputs:
///
/// - `tx` -- the full transaction data itself. Can be hex- or base64-encoded for json requests;
/// can also be those or raw bytes for bt-encoded requests. For backwards compatibility,
/// hex-encoded data can also be passed in a json request via the parameter `tx_as_hex` but
/// that is deprecated and will eventually be removed.
/// - `blink` -- Should be set to true if this transaction is a blink transaction that should be
/// submitted to a blink quorum rather than distributed through the mempool.
///
/// Output:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `reason` -- String containing additional information on why a transaction failed.
/// - `blink_status` -- Set to the result of submitting this transaction to the Blink quorum. 1
/// means the quorum rejected the transaction; 2 means the quorum accepted it; 3 means there was
/// a timeout connecting to or waiting for a response from the blink quorum. Note that a
/// timeout response does *not* necessarily mean the transaction has not made it to the network.
/// - `not_relayed` -- will be set to true if some problem with the transactions prevents it from
/// being relayed to the network, omitted otherwise.
/// - `reason_codes` -- If the transaction was rejected this will be set to a set of reason string
/// codes indicating why the transaction failed:
/// - `"failed"` -- general "bad transaction" code
/// - `"altchain"` -- the transaction is spending outputs that exist on an altchain.
/// - `"mixin"` -- the transaction has the wrong number of decoys
/// - `"double_spend"` -- the transaction is spending outputs that are already spent
/// - `"invalid_input"` -- one or more inputs in the transaction are invalid
/// - `"invalid_output"` -- out or more outputs in the transaction are invalid
/// - `"too_few_outputs"` -- the transaction does not create enough outputs (at least two are
/// required, currently).
/// - `"too_big"` -- the transaction is too large
/// - `"overspend"` -- the transaction spends (via outputs + fees) more than the inputs
/// - `"fee_too_low"` -- the transaction fee is insufficient
/// - `"invalid_version"` -- the transaction version is invalid (the wallet likely needs an
/// update).
/// - `"invalid_type"` -- the transaction type is invalid
/// - `"snode_locked"` -- one or more outputs are currently staked to a registred service node
/// and thus are not currently spendable on the blockchain.
/// - `"blacklisted"` -- the outputs are currently blacklisted (from being in the 30-day penalty
/// period following a service node deregistration).
/// - `"blink"` -- the blink transaction failed (see `blink_status`)
struct SUBMIT_TRANSACTION : PUBLIC, LEGACY
{
static constexpr auto names() { return NAMES("submit_transaction", "send_raw_transaction", "sendrawtransaction"); }
struct request_parameters
{
std::string tx;
bool blink = false;
} request;
};
/// RPC: daemon/start_mining
///
/// Start mining on the daemon
///
/// Inputs:
///
/// - `miner_address` -- Account address to mine to.
/// - `threads_count` -- Number of mining threads to run. Defaults to 1 thread if omitted or 0.
/// - `num_blocks` -- Mine until the blockchain has this many new blocks, then stop (no limit if 0,
/// the default).
/// - `slow_mining` -- Do slow mining (i.e. don't allocate RandomX cache); primarily intended for
/// testing.
///
/// Outputs:
///
/// `status` -- General RPC status string. `"OK"` means everything looks good.
struct START_MINING : LEGACY
{
static constexpr auto names() { return NAMES("start_mining"); }
struct request_parameters {
std::string miner_address;
int threads_count = 1;
int num_blocks = 0;
bool slow_mining = false;
} request;
};
/// RPC: daemon/stop_mining
///
/// Stop mining on the daemon.
///
/// Inputs: none
///
/// Outputs:
///
/// `status` -- General RPC status string. `"OK"` means everything looks good.
struct STOP_MINING : LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("stop_mining"); }
};
/// RPC: daemon/mining_status
///
/// Get the mining status of the daemon.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `active` -- States if mining is enabled (`true`) or disabled (`false`).
/// - `speed` -- Mining power in hashes per seconds.
/// - `threads_count` -- Number of running mining threads.
/// - `address` -- Account address daemon is mining to. Empty if not mining.
/// - `pow_algorithm` -- Current hashing algorithm name
/// - `block_target` -- The expected time to solve per block, i.e. TARGET_BLOCK_TIME
/// - `block_reward` -- Block reward for the current block being mined.
/// - `difficulty` -- The difficulty for the current block being mined.
struct MINING_STATUS : LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("mining_status"); }
};
/// RPC: network/get_info
///
/// Retrieve general information about the state of the node and the network.
///
/// Inputs: none.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `height` -- Current length of longest chain known to daemon.
/// - `target_height` -- The height of the next block in the chain.
/// - `immutable_height` -- The latest height in the blockchain that can not be reorganized (i.e.
/// is backed by at least 2 Service Node, or 1 hardcoded checkpoint, 0 if N/A). Omitted if it
/// cannot be determined (typically because the node is still syncing).
/// - `pulse` -- will be true if the next expected block is a pulse block, false otherwise.
/// - `pulse_ideal_timestamp` -- For pulse blocks this is the ideal timestamp of the next block,
/// that is, the timestamp if the network was operating with perfect 2-minute blocks since the
/// pulse hard fork.
/// - `pulse_target_timestamp` -- For pulse blocks this is the target timestamp of the next block,
/// which targets 2 minutes after the previous block but will be slightly faster/slower if the
/// previous block is behind/ahead of the ideal timestamp.
/// - `difficulty` -- Network mining difficulty; omitted when the network is expecting a pulse
/// block.
/// - `target` -- Current target for next proof of work.
/// - `tx_count` -- Total number of non-coinbase transaction in the chain.
/// - `tx_pool_size` -- Number of transactions that have been broadcast but not included in a block.
/// - `mainnet` -- Indicates whether the node is on the main network (`true`) or not (`false`).
/// - `testnet` -- Indicates that the node is on the test network (`true`). Will be omitted for
/// non-testnet.
/// - `devnet` -- Indicates that the node is on the dev network (`true`). Will be omitted for
/// non-devnet.
/// - `fakechain` -- States that the node is running in "fakechain" mode (`true`). Omitted
/// otherwise.
/// - `nettype` -- String value of the network type (mainnet, testnet, devnet, or fakechain).
/// - `top_block_hash` -- Hash of the highest block in the chain. Will be hex for JSON requests,
/// 32-byte binary value for bt requests.
/// - `immutable_block_hash` -- Hash of the highest block in the chain that can not be reorganized.
/// Hex string for json, bytes for bt.
/// - `cumulative_difficulty` -- Cumulative difficulty of all blocks in the blockchain.
/// - `block_size_limit` -- Maximum allowed block size.
/// - `block_size_median` -- Median block size of latest 100 blocks.
/// - `ons_counts` -- ONS registration counts, as a three-element list: [session, wallet, lokinet]
/// - `offline` -- Indicates that the node is offline, if true. Omitted for online nodes.
/// - `database_size` -- Current size of Blockchain data. Over public RPC this is rounded up to the
/// next-largest GB value.
/// - `version` -- Current version of this daemon, as a string. For a public node this will just be
/// the major and minor version (e.g. "9"); for an admin rpc endpoint this will return the full
/// version (e.g. "9.2.1").
/// - `status_line` -- A short one-line summary string of the node (requires an admin/unrestricted
/// connection for most details)
///
/// If the endpoint is a restricted (i.e. admin) endpoint then the following fields are also
/// included:
///
/// - `alt_blocks_count` -- Number of alternative blocks to main chain.
/// - `outgoing_connections_count` -- Number of peers that you are connected to and getting
/// information from.
/// - `incoming_connections_count` -- Number of peers connected to and pulling from your node.
/// - `white_peerlist_size` -- White Peerlist Size
/// - `grey_peerlist_size` -- Grey Peerlist Size
/// - `service_node` -- Will be true if the node is running in --service-node mode.
/// - `start_time` -- Start time of the daemon, as UNIX time.
/// - `last_storage_server_ping` -- Last ping time of the storage server (0 if never or not running
/// as a service node)
/// - `last_lokinet_ping` -- Last ping time of lokinet (0 if never or not running as a service node)
/// - `free_space` -- Available disk space on the node.
///
/// Example-JSON-Fetch
struct GET_INFO : PUBLIC, LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("get_info", "getinfo"); }
};
/// RPC: daemon/get_net_stats
///
/// Retrieve general information about the network statistics of the daemon.
///
/// Inputs: none.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `start_time` -- something.
/// - `total_packets_in` -- something.
/// - `total_bytes_in` -- something.
/// - `total_packets_out` -- something.
/// - `total_bytes_out` -- something.
struct GET_NET_STATS : LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("get_net_stats"); }
};
/// RPC: daemon/save_bc
///
/// Save the blockchain. The blockchain does not need saving and is always saved when modified,
/// however it does a sync to flush the filesystem cache onto the disk for safety purposes,
/// against Operating System or Hardware crashes.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
struct SAVE_BC : LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("save_bc"); }
};
/// RPC: blockchain/get_block_count
///
/// Look up how many blocks are in the longest chain known to the node.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `count` -- Number of blocks in logest chain seen by the node.
///
/// Example-JSON-Fetch
struct GET_BLOCK_COUNT : PUBLIC, NO_ARGS
{
static constexpr auto names() { return NAMES("get_block_count", "getblockcount"); }
};
/// RPC: blockchain/get_block_hash
///
/// Look up one or more blocks' hashes by their height.
///
/// Inputs:
/// - heights array of block heights of which to look up the block hashes. Accepts at most 1000
/// heights per request.
///
/// Output:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `height` -- the current blockchain height of this node
/// - `"<height>"` the block hash of the block with the given height. Note that each height key
/// is the stringified integer value, e.g. "3456" rather than 3456.
///
/// Example input:
///
/// ```json
/// { "heights": [42, 123456] }
/// ```
///
/// Example output:
///
/// ```json
/// {
/// "status": "OK",
/// "height": 123456,
/// "42": "b269367374fa87ec517405bf120f831e9b13b12c0ee6721dcca69d2c0fe73a0f",
/// "123456": "aa1f3b566aba42e522f8097403a3c513069206286ff08c2ff2871757dbc3e436"
/// }
/// ```
struct GET_BLOCK_HASH : PUBLIC
{
static constexpr auto names() { return NAMES("get_block_hash", "on_get_block_hash", "on_getblockhash"); }
static constexpr size_t MAX_HEIGHTS = 1000;
struct request_parameters {
std::vector<uint64_t> heights;
} request;
};
// FIXME: This struct should go; it's just a bit of indirection (in _commands_defs.cpp) that isn't
// solve anything (because we can just set the fields directly in the output json values rather
// than use `fill_block_header_response`).
struct block_header_response
{
uint8_t major_version;
uint8_t minor_version;
uint64_t timestamp;
std::string prev_hash;
uint32_t nonce;
bool orphan_status;
uint64_t height;
uint64_t depth;
std::string hash;
difficulty_type difficulty;
difficulty_type cumulative_difficulty;
uint64_t reward;
uint64_t coinbase_payouts;
uint64_t block_size;
uint64_t block_weight;
uint64_t num_txes;
std::optional<std::string> pow_hash;
uint64_t long_term_weight;
std::string miner_tx_hash;
std::vector<std::string> tx_hashes;
std::string service_node_winner;
};
void to_json(nlohmann::json& j, const block_header_response& h);
void from_json(const nlohmann::json& j, block_header_response& h);
/// RPC: blockchain/get_last_block_header
///
/// Block header information for the most recent block is easily retrieved with this method. No
/// inputs are needed.
///
/// Inputs:
/// - `fill_pow_hash` -- Tell the daemon if it should fill out pow_hash field.
/// - `get_tx_hashes` -- If true (default false) then include the hashes of non-coinbase
/// transactions
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `block_header` -- A dict containing block header information. Contains keys:
/// - `major_version` -- The major version of the oxen protocol at this block height.
/// - `minor_version` -- The minor version of the oxen protocol at this block height.
/// - `timestamp` -- The unix time at which the block was recorded into the blockchain.
/// - `prev_hash` -- The hash of the block immediately preceding this block in the chain.
/// - `nonce` -- A cryptographic random one-time number used in mining a Loki block.
/// - `orphan_status` -- Usually `false`. If `true`, this block is not part of the longest
/// chain.
/// - `height` -- The number of blocks preceding this block on the blockchain.
/// - `depth` -- The number of blocks succeeding this block on the blockchain. A larger number
/// means an older block.
/// - `hash` -- The hash of this block.
/// - `difficulty` -- The strength of the Loki network based on mining power.
/// - `cumulative_difficulty` -- The cumulative strength of the Loki network based on mining
/// power.
/// - `reward` -- The amount of new OXEN (in atomic units) generated in this block and allocated
/// to service nodes and governance. As of Oxen 10 (HF 19) this is the *earned* amount, but
/// not the *paid* amount which occurs in batches.
/// - `coinbase_payouts` -- The amount of OXEN paid out in this block. As of Oxen 10 (HF 19),
/// this reflects the current batched amounts being paid from earnings batched over previous
/// blocks, not the amounts *earned* in the current block.
/// - `block_size` -- The block size in bytes.
/// - `block_weight` -- The block weight in bytes.
/// - `num_txes` -- Number of transactions in the block, not counting the coinbase tx.
/// - `pow_hash` -- The hash of the block's proof of work (requires `fill_pow_hash`)
/// - `long_term_weight` -- Long term weight of the block.
/// - `miner_tx_hash` -- The TX hash of the miner transaction
/// - `tx_hashes` -- The TX hashes of all non-coinbase transactions (requires `get_tx_hashes`)
/// - `service_node_winner` -- Service node that received a reward for this block
///
/// Example input:
/// ```json
/// {}
/// ```
///
/// Example-JSON-Fetch
struct GET_LAST_BLOCK_HEADER : PUBLIC
{
static constexpr auto names() { return NAMES("get_last_block_header", "getlastblockheader"); }
struct request_parameters
{
bool fill_pow_hash;
bool get_tx_hashes;
} request;
};
/// RPC: blockchain/get_block_header_by_hash
///
/// Block header information can be retrieved using either a block's hash or height. This method
/// includes a block's hash as an input parameter to retrieve basic information about the block.
///
/// Inputs:
/// - `hash` -- The block's hash.
/// - `hashes` -- Request multiple blocks via an array of hashes
/// - `fill_pow_hash` -- Tell the daemon if it should fill out pow_hash field.
/// - `get_tx_hashes` -- If true (default false) then include the hashes of non-coinbase
/// transactions
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `block_header` -- Block header information for the requested `hash` block
/// - `block_headers` -- Block header information for the requested `hashes` blocks
struct GET_BLOCK_HEADER_BY_HASH : PUBLIC
{
static constexpr auto names() { return NAMES("get_block_header_by_hash", "getblockheaderbyhash"); }
struct request_parameters
{
std::string hash;
std::vector<std::string> hashes;
bool fill_pow_hash;
bool get_tx_hashes;
} request;
};
/// RPC: blockchain/get_block_header_by_height
///
/// Similar to get_block_header_by_hash above, this method includes a block's height as an input
/// parameter to retrieve basic information about the block.
///
/// Inputs:
///
/// - `height` -- A block height to look up; returned in `block_header`
/// - `heights` -- Block heights to retrieve; returned in `block_headers`
/// - `fill_pow_hash` -- Tell the daemon if it should fill out pow_hash field.
/// - `get_tx_hashes` -- If true (default false) then include the hashes of non-coinbase
/// transactions
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `block_header` -- Block header information for the requested `height` block
/// - `block_headers` -- Block header information for the requested `heights` blocks
struct GET_BLOCK_HEADER_BY_HEIGHT : PUBLIC
{
static constexpr auto names() { return NAMES("get_block_header_by_height", "getblockheaderbyheight"); }
struct request_parameters
{
std::optional<uint64_t> height;
std::vector<uint64_t> heights;
bool fill_pow_hash;
bool get_tx_hashes;
} request;
};
/// RPC: blockchain/get_block
///
/// Full block information can be retrieved by either block height or hash, like with the above
/// block header calls. For full block information, both lookups use the same method, but with
/// different input parameters.
///
/// Inputs:
///
/// - `hash` -- The block's hash.
/// - `height` -- A block height to look up; returned in `block_header`
/// - `fill_pow_hash` -- Tell the daemon if it should fill out pow_hash field.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `block_header` -- Block header information for the requested `height` block
/// - `tx_hashes` -- List of hashes of non-coinbase transactions in the block. If there are no
/// other transactions, this will be an empty list.
/// - `blob` -- Hexadecimal blob of block information.
/// - `json` -- JSON formatted block details.
///
/// Example input:
///
/// ```json
/// { "height": 42 }
/// ```
///
/// Example-JSON-Fetch
struct GET_BLOCK : PUBLIC
{
static constexpr auto names() { return NAMES("get_block", "getblock"); }
struct request_parameters
{
std::string hash;
uint64_t height;
bool fill_pow_hash;
} request;
};
/// RPC: daemon/get_peer_list
///
/// Get the list of current network peers known to this node.
///
/// Inputs: none
///
/// Output:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `white_list` -- list of "whitelist" peers (see below), that is, peers that were recorded
/// reachable the last time this node connected to them. Peers that are unreachable or not
/// synchronized with the network are moved to the graylist.
/// - `gray_list` -- list of peers (see below) that this node knows of but has not (recently) tried
/// to connect to.
///
/// Each peer list is an array of dicts containing the following fields:
/// - `id` -- a unique integer locally identifying the peer
/// - `host` -- the peer's IP address (as a string)
/// - `port` -- the port on which the peer is reachable
/// - `last_seen` -- unix timestamp when this node last connected to the peer. Will be omitted if
/// never connected (e.g. for a peer we received from another node but haven't yet tried).
struct GET_PEER_LIST : LEGACY
{
static constexpr auto names() { return NAMES("get_peer_list"); }
struct request_parameters
{
bool public_only = false; // Hidden option: can be set to false to also include non-public-zone peers (Tor, I2P), but since Oxen currently only really exists in public zones, we don't put this in the RPC docs.
} request;
};
/// RPC: daemon/set_log_level
///
/// Set the daemon log level. By default, log level is set to `0`. For more fine-tuned logging
/// control set the set_log_categories command instead.
///
/// Inputs:
/// - `level` -- Daemon log level to set from `0` (less verbose) to `4` (most verbose)
///
/// Output:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
struct SET_LOG_LEVEL : LEGACY
{
static constexpr auto names() { return NAMES("set_log_level"); }
struct request_parameters
{
int8_t level;
} request;
};
/// RPC: daemon/set_log_categories
///
/// Set the daemon log categories for debugging purposes.
///
/// Categories are represented as a comma separated list of `<Category>:<level>`, where
/// `<Category>` is is one of the various internal debugging categories defined in the oxen source
/// code, or `*` to refer to all logging categories.
///
/// Level is one of the following: FATAL, ERROR, WARNING, INFO, DEBUG, TRACE.
///
/// You can append to the current the log level for updating just one or more categories while
/// leaving other log levels unchanged by specifying one or more "<category>:<level>" pairs
/// preceded by a "+", for example "+difficulty:DEBUG,net:WARNING".
///
/// Inputs:
///
/// - `categories` -- Optional, daemon log categores to enable
///
/// Output:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `categories` -- Daemon log enabled categories
struct SET_LOG_CATEGORIES : LEGACY
{
static constexpr auto names() { return NAMES("set_log_categories"); }
struct request_parameters
{
std::string categories;
} request;
};
/// RPC: blockchain/get_transaction_pool_hashes
///
/// Get hashes from transaction pool.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `tx_hashes` -- List of transaction hashes,
struct GET_TRANSACTION_POOL_HASHES : PUBLIC, LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("get_transaction_pool_hashes"); }
};
/// RPC: blockchain/get_transaction_pool_stats
///
/// Get the transaction pool statistics.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `pool_stats` -- Dict of pool statistics:
/// - `bytes_total` -- the total size (in bytes) of the transactions in the transaction pool.
/// - `bytes_min` -- the size of the smallest transaction in the tx pool.
/// - `bytes_max` -- the size of the largest transaction in the pool.
/// - `bytes_med` -- the median transaction size in the pool.
/// - `fee_total` -- the total fees of all transactions in the transaction pool.
/// - `txs_total` -- the total number of transactions in the transaction pool
/// - `num_failing` -- the number of failing transactions: that is, transactions that are in the
/// mempool but are not currently eligible to be added to the blockchain.
/// - `num_10m` -- the number of transactions received within the last ten minutes
/// - `num_not_relayed` -- the number of transactions which are not being relayed to the
/// network. Only included when the `include_unrelayed` request parameter is set to true.
/// - `num_double_spends` -- the number of transactions in the mempool that are marked as
/// double-spends of existing blockchain transactions.
/// - `oldest` -- the unix timestamp of the oldest transaction in the pool.
/// - `histo` -- pairs of [# txes, size of bytes] that form a histogram of transactions in the
/// mempool, if there are at least two transactions in the mempool (and omitted entirely
/// otherwise). When present, this field will contain 10 pairs:
/// - When `histo_max` is given then `histo` consists of 10 equally-spaced bins from
/// newest to oldest where the newest bin begins at age 0 and the oldest bin ends at age
/// `histo_max`. For example, bin `[3]` contains statistics for transactions with ages
/// between `3*histo_max/10` and `4*histo_max/10`.
/// - Otherwise `histo_98pc` will be present in which case `histo` contains 9 equally spaced
/// bins from newest to oldest where the newest bin begins at age 0 and the oldest bin ends
/// at age `histo_98pc`, and at least 98% of the mempool transactions will fall in these 9
/// bins. The 10th bin contains statistics for all transactions with ages greater than
/// `histo_98pc`.
/// - `histo_98pc` -- See `histo` for details.
/// - `histo_max` -- See `histo` for details.
struct GET_TRANSACTION_POOL_STATS : PUBLIC, LEGACY
{
static constexpr auto names() { return NAMES("get_transaction_pool_stats"); }
struct request_parameters {
/// Whether to include transactions marked "do not relay" in the returned statistics. False
/// by default: since they are not relayed, they do not form part of the global network
/// transaction pool.
bool include_unrelayed = false;
} request;
};
/// RPC: daemon/get_connections
///
/// Retrieve information about incoming and outgoing P2P connections to your node.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `connections` -- List of all connections and their info; each element is a dict containing:
/// - `incoming` -- bool of whether this connection was established by the remote to us (true) or
/// by us to the remove (false).
/// - `ip` -- address of the remote peer
/// - `port` -- the remote port of the peer connection
/// - `address_type` -- 1/2/3/4 for ipv4/ipv6/i2p/tor, respectively.
/// - `peer_id` -- a string that uniquely identifies a peer node
/// - `recv_count` -- number of bytes of data received from this peer
/// - `recv_idle_ms` -- number of milliseconds since we last received data from this peer
/// - `send_count` -- number of bytes of data send to this peer
/// - `send_idle_ms` -- number of milliseconds since we last sent data to this peer
/// - `state` -- returns the current state of the connection with this peer as a string, one of:
/// - `"before_handshake"` -- the connection is still being established/negotiated
/// - `"synchronizing"` -- we are synchronizing the blockchain with this peer
/// - `"standby"` -- the peer is available for synchronizing but we are not currently using it
/// - `"normal"` -- this is a regular, synchronized peer
/// - `live_ms` -- number of milliseconds since this connection was initiated
/// - `avg_download` -- the average download speed from this peer in bytes per second
/// - `current_download` -- the current (i.e. average over a very recent period) download speed
/// from this peer in bytes per second.
/// - `avg_upload` -- the average upload speed to this peer in bytes per second
/// - `current_upload` -- the current upload speed to this peer in bytes per second
/// - `connection_id` -- a unique random string identifying this connection
/// - `height` -- the height of the peer
/// - `host` -- the hostname for this peer; only included if not the same as `ip`
/// - `localhost` -- set to true if the peer is a localhost connection; omitted otherwise.
/// - `local_ip` -- set to true if the peer is a non-public, local network connection; omitted
/// otherwise.
///
/// Example output:
/// ```json
/// {
/// "connections": [
/// {
/// "address": "1.2.3.4:51890",
/// "address_type": 1,
/// "avg_download": 0,
/// "avg_upload": 2,
/// "connection_id": "abcdef0123456789abcdef0123456789",
/// "current_download": 0,
/// "current_upload": 0,
/// "height": 1088107,
/// "host": "1.2.3.4",
/// "incoming": true,
/// "ip": "1.2.3.4",
/// "live_time": 33,
/// "local_ip": false,
/// "localhost": false,
/// "peer_id": "fedcba9876543210",
/// "port": "51890",
/// "pruning_seed": 0,
/// "recv_count": 20628,
/// "recv_idle_time": 0,
/// "rpc_port": 0,
/// "send_count": 83253,
/// "send_idle_time": 0,
/// "state": "normal",
/// "support_flags": 1
/// },
/// {
/// "address": "5.6.7.8:22022",
/// "address_type": 1,
/// "avg_download": 1,
/// "avg_upload": 1,
/// "connection_id": "00112233445566778899aabbccddeeff",
/// "current_download": 0,
/// "current_upload": 0,
/// "height": 1088107,
/// "host": "5.6.7.8",
/// "incoming": false,
/// "ip": "5.6.7.8",
/// "live_time": 66,
/// "local_ip": false,
/// "localhost": false,
/// "peer_id": "ffddbb9977553311",
/// "port": "22022",
/// "pruning_seed": 0,
/// "recv_count": 95687,
/// "recv_idle_time": 0,
/// "rpc_port": 0,
/// "send_count": 85542,
/// "send_idle_time": 0,
/// "state": "normal",
/// "support_flags": 1
/// }
/// ],
/// "status": "OK"
/// }
/// ```
struct GET_CONNECTIONS : NO_ARGS
{
static constexpr auto names() { return NAMES("get_connections"); }
};
/// RPC: blockchain/get_block_headers_range
///
/// Similar to get_block_header_by_height above, but for a range of blocks.
/// This method includes a starting block height and an ending block height as
/// parameters to retrieve basic information about the range of blocks.
///
/// Inputs:
///
/// - `start_height` -- The starting block's height.
/// - `end_height` -- The ending block's height.
/// - `fill_pow_hash` -- Tell the daemon if it should fill out pow_hash field.
/// - `get_tx_hashes` -- If true (default false) then include the hashes of non-coinbase
/// transactions
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `headers` -- Array of block_header (a structure containing block header information. See
/// get_last_block_header).
///
/// Example input:
/// ```json
/// { "start_height": 1087845, "end_height": 1087847, "get_tx_hashes": true }
/// ```
///
/// Example-JSON-Fetch
struct GET_BLOCK_HEADERS_RANGE : PUBLIC
{
static constexpr auto names() { return NAMES("get_block_headers_range", "getblockheadersrange"); }
struct request_parameters
{
uint64_t start_height;
uint64_t end_height;
bool fill_pow_hash;
bool get_tx_hashes;
} request;
};
/// RPC: daemon/stop_daemon
///
/// Stop the daemon.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
struct STOP_DAEMON : LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("stop_daemon"); }
};
/// RPC: daemon/get_limit
///
/// Get daemon p2p bandwidth limits.
///
/// Inputs: none.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `limit_up` -- Upload limit in kiB/s
/// - `limit_down` -- Download limit in kiB/s
struct GET_LIMIT : LEGACY, NO_ARGS
{
static constexpr auto names() { return NAMES("get_limit"); }
};
/// RPC: daemon/set_limit
///
/// Set daemon p2p bandwidth limits.
///
/// Inputs:
///
/// - `limit_down` -- Download limit in kBytes per second. -1 means reset to default; 0 (or
/// omitted) means don't change the current limit
/// - `limit_up` -- Upload limit in kBytes per second. -1 means reset to default; 0 (or omitted)
/// means don't change the current limit
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `limit_up` -- The new (or existing, if unchanged) upload limit in kiB/s
/// - `limit_down` -- The new (or existing, if unchanged) download limit in kiB/s
struct SET_LIMIT : LEGACY
{
static constexpr auto names() { return NAMES("set_limit"); }
struct request_parameters {
int64_t limit_down = 0;
int64_t limit_up = 0;
} request;
};
/// RPC: daemon/out_peers
///
/// Limit number of Outgoing peers.
///
/// Inputs:
///
/// - `set` -- If true, set the number of outgoing peers, otherwise the response returns the current
/// limit of outgoing peers. (Defaults to true)
/// - `out_peers` -- Max number of outgoing peers
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `out_peers` -- The current limit set for outgoing peers.
struct OUT_PEERS : LEGACY
{
static constexpr auto names() { return NAMES("out_peers"); }
struct request_parameters
{
bool set;
uint32_t out_peers;
} request;
};
/// RPC: daemon/in_peers
///
/// Limit number of Incoming peers.
///
/// Inputs:
///
/// - `set` -- If true, set the number of incoming peers, otherwise the response returns the current
/// limit of incoming peers. (Defaults to true)
/// - `in_peers` -- Max number of incoming peers
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `in_peers` -- The current limit set for incoming peers.
struct IN_PEERS : LEGACY
{
static constexpr auto names() { return NAMES("in_peers"); }
struct request_parameters
{
bool set;
uint32_t in_peers;
} request;
};
/// RPC: network/hard_fork_info
///
/// Retrieves information about the current or a specific hard fork network rules.
///
/// Inputs:
///
/// - `version` -- If specified, this is the hard fork (i.e. major block) version for the fork.
/// Only one of `version` and `height` may be given; returns the current hard fork info if
/// neither is given.
/// - `height` -- Request hard fork info by querying a particular height. Only one of `version`
/// and `height` may be given.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `version` -- The major block version for the fork.
/// - `enabled` -- Indicates whether the hard fork is enforced on the blockchain (that is, whether
/// the blockchain height is at or above the requested hardfork).
/// - `earliest_height` -- Block height at which the hard fork will become enabled.
/// - `last_height` -- The last block height at which this hard fork will be active; will be
/// omitted if this oxend is not aware of any following hard fork.
///
/// Example input:
///
/// ```json
/// { "version": 19 }
/// ```
///
/// Example-JSON-Fetch
struct HARD_FORK_INFO : PUBLIC
{
static constexpr auto names() { return NAMES("hard_fork_info"); }
struct request_parameters {
uint8_t version = 0;
uint64_t height = 0;
} request;
};
/// RPC: daemon/get_bans
///
/// Get list of banned IPs.
///
/// Inputs: None
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `bans` -- List of banned nodes. Each element is a dict containing:
/// - `host` -- Banned host (IP in A.B.C.D form).
/// - `seconds` -- Unix timestamp when the ban expires
///
/// Example output:
/// ```json
/// {
/// "bans": [
/// {
/// "host": "1.2.3.4",
/// "ip": 67305985,
/// "seconds": 5504
/// },
/// {
/// "host": "8.8.8.8",
/// "ip": 134744072,
/// "seconds": 679104
/// }
/// ],
/// "status": "OK"
/// }
/// ```
struct GET_BANS : NO_ARGS
{
static constexpr auto names() { return NAMES("get_bans"); }
};
struct ban
{
std::string host;
uint32_t seconds;
};
inline void to_json(nlohmann::json& j, const ban& b) { j = nlohmann::json{{"host", b.host}, {"seconds", b.seconds} }; };
/// RPC: daemon/set_bans
///
/// Ban another node by IP.
///
/// Inputs:
/// - `host` -- Banned host (IP in A.B.C.D form).
/// - `seconds` -- Number of seconds to ban node
/// - `ban` -- Set true to ban, false to remove a ban.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
struct SET_BANS : RPC_COMMAND
{
static constexpr auto names() { return NAMES("set_bans"); }
struct request_parameters
{
std::string host;
uint32_t seconds;
bool ban;
} request;
};
/// RPC: daemon/banned
///
/// Determine whether a given IP address is banned
///
/// Inputs:
/// - `address` -- The IP address to check.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `banned` -- True if the given address is banned, false otherwise.
/// - `seconds` -- The number of seconds remaining in the ban.
///
/// Example input:
/// ```json
/// { "address": "1.2.3.4" }
/// ```
///
/// Example output:
/// ```json
/// {
/// "banned": true,
/// "seconds": 5710,
/// "status": "OK"
/// }
///
/// Example input:
/// ```json
/// { "addess": "4.3.2.1" }
/// ```
///
/// Example output:
/// ```json
/// {
/// "banned": false,
/// "seconds": 0,
/// "status": "OK"
/// }
/// ```
struct BANNED : RPC_COMMAND
{
static constexpr auto names() { return NAMES("banned"); }
struct request_parameters
{
std::string address;
} request;
};
/// RPC: daemon/flush_txpool
///
/// Flush tx ids from transaction pool..
///
/// Inputs:
/// - `txids` -- Optional, list of transactions IDs to flosh from pool (all tx ids flushed if empty)
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
struct FLUSH_TRANSACTION_POOL : RPC_COMMAND
{
static constexpr auto names() { return NAMES("flush_txpool"); }
struct request_parameters
{
std::vector<std::string> txids;
} request;
};
/// RPC: blockchain/get_output_histogram
///
/// Get a histogram of output amounts. For all amounts (possibly filtered by parameters),
/// gives the number of outputs on the chain for that amount. RingCT outputs counts as 0 amount.
///
/// Inputs:
///
/// - `amounts` -- list of amounts in Atomic Units.
/// - `min_count` -- The minimum amounts you are requesting.
/// - `max_count` -- The maximum amounts you are requesting.
/// - `unlocked` -- Look for locked only.
/// - `recent_cutoff`
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `histogram` -- List of histogram entries. Each element is structured as follows:
/// - `uint64_t` -- amount Output amount in atomic units.
/// - `uint64_t` -- total_instances
/// - `uint64_t` -- unlocked_instances
/// - `uint64_t` -- recent_instances
struct GET_OUTPUT_HISTOGRAM : PUBLIC
{
static constexpr auto names() { return NAMES("get_output_histogram"); }
struct request_parameters
{
std::vector<uint64_t> amounts;
uint64_t min_count;
uint64_t max_count;
bool unlocked;
uint64_t recent_cutoff;
} request;
struct entry
{
uint64_t amount;
uint64_t total_instances;
uint64_t unlocked_instances;
uint64_t recent_instances;
};
};
void to_json(nlohmann::json& j, const GET_OUTPUT_HISTOGRAM::entry& c);
void from_json(const nlohmann::json& j, GET_OUTPUT_HISTOGRAM::entry& c);
/// RPC: daemon/get_version
///
/// Get current RPC protocol version.
///
/// Inputs: None
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `version` -- RPC current version.
struct GET_VERSION : PUBLIC, NO_ARGS
{
static constexpr auto names() { return NAMES("get_version"); }
};
/// RPC: blockchain/get_coinbase_tx_sum
///
/// Get the coinbase amount and the fees amount for n last blocks starting at particular height.
///
/// Note that this call can be extremely slow the first time it is called, particularly when
/// requesting the values for the entire chain (by specifying `height=0`), as it has to scan the
/// full blockchain to calculate the result. As such this call is restricted to admin
/// connections. Future versions may lift this restriction.
///
/// Inputs:
///
/// - `height` -- Block height from which getting the amounts.
/// - `count` -- Number of blocks to include in the sum.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `emission_amount` -- Amount of coinbase reward in atomic units.
/// - `fee_amount` -- Amount of fees in atomic units.
/// - `burn_amount` -- Amount of burnt oxen.
///
/// Example input:
/// ```json
/// {"height": 0, "count":1000000000}
/// ```
///
/// Example output:
/// ```json
/// {
/// "burn_amount": 720279959424405,
/// "emission_amount": 59537648307402880,
/// "fee_amount": 80671056941541,
/// "status": "OK"
/// }
/// ```
struct GET_COINBASE_TX_SUM : RPC_COMMAND
{
static constexpr auto names() { return NAMES("get_coinbase_tx_sum"); }
struct request_parameters
{
uint64_t height;
uint64_t count;
} request;
};
/// RPC: network/get_fee_estimate
///
/// Gives an estimation of per-output + per-byte fees
///
/// Inputs:
///
/// - `grace_blocks` -- If specified, make sure that the fee is high enough to cover any fee
/// increases in the next `grace_blocks` blocks.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `emission_amount` -- Amount of coinbase reward in atomic units.
/// - `fee_amount` -- Amount of fees in atomic units.
/// - `burn_amount` -- Amount of burnt oxen.
/// - `fee_per_byte` -- Amount of fees estimated per byte in atomic units
/// - `fee_per_output` -- Amount of fees per output generated by the tx (adds to the `fee_per_byte`
/// per-byte value)
/// - `blink_fee_per_byte` -- Value for sending a blink. The portion of the overall blink fee above
/// the overall base fee is burned.
/// - `blink_fee_per_output` -- Value for sending a blink. The portion of the overall blink fee
/// above the overall base fee is burned.
/// - `blink_fee_fixed` -- Fixed blink fee in addition to the per-output and per-byte amounts. The
/// portion of the overall blink fee above the overall base fee is burned.
/// - `quantization_mask`
///
/// Example input:
///
/// ```json
/// {}
/// ```
///
/// Example-JSON-Fetch
struct GET_BASE_FEE_ESTIMATE : PUBLIC
{
static constexpr auto names() { return NAMES("get_fee_estimate"); }
struct request_parameters
{
uint64_t grace_blocks;
} request;
};
/// RPC: blockchain/get_alternative_chains
///
/// Display alternative chains seen by the node.
///
/// Inputs: None
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `chains` -- Array of Chains. Each element is contains the following keys:
/// - `block_hash` -- The block hash of the first diverging block of this alternative chain.
/// - `height` -- The block height of the first diverging block of this alternative chain.
/// - `length` -- The length in blocks of this alternative chain, after divergence.
/// - `difficulty` -- The cumulative difficulty of all blocks in the alternative chain.
/// - `block_hashes` -- List containing hex block hashes
/// - `main_chain_parent_block`
struct GET_ALTERNATE_CHAINS : NO_ARGS
{
static constexpr auto names() { return NAMES("get_alternative_chains"); }
struct chain_info
{
std::string block_hash;
uint64_t height;
uint64_t length;
uint64_t difficulty;
std::vector<std::string> block_hashes;
std::string main_chain_parent_block;
};
};
void to_json(nlohmann::json& j, const GET_ALTERNATE_CHAINS::chain_info& c);
void from_json(const nlohmann::json& j, GET_ALTERNATE_CHAINS::chain_info& c);
/// RPC: daemon/relay_tx
///
/// Relay a list of transaction IDs.
///
/// Inputs:
///
/// - `txids` -- List of transactions IDs to relay from pool.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
struct RELAY_TX : RPC_COMMAND
{
static constexpr auto names() { return NAMES("relay_tx"); }
struct request_parameters
{
std::vector<std::string> txids;
} request;
};
/// RPC: daemon/sync_info
///
/// Get node synchronisation information. This returns information on the node's syncing "spans"
/// which are block segments being downloaded from peers while syncing; spans are generally
/// downloaded out of order from multiple peers, and so these spans reflect in-progress downloaded
/// blocks that have not yet been added to the block chain: typically because the spans is not yet
/// complete, or because the span is for future blocks that are dependent on intermediate blocks
/// (likely in another span) being added to the chain first.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `height` -- Current block height
/// - `target_height` -- If the node is currently syncing then this is the target height the node
/// wants to reach. If fully synced then this field is omitted.
/// - `peers` -- dict of connection information about peers. The key is the peer connection_id; the
/// value is identical to the values of the `connections` field of the
/// [`get_connections`](#get_connections) endpoint.
/// - `span` -- array of span information of current in progress synchronization. Each element
/// contains:
/// - `start_block_height` -- Block height of the first block in the span
/// - `nblocks` -- the number of blocks in the span
/// - `connection_id` -- the connection_id of the connection from which we are downloading the
/// span
/// - `rate` -- the most recent connection speed measurement
/// - `speed` -- the average connection speed over recent downloaded blocks
/// - `size` -- total number of block and transaction data stored in the span
/// - `overview` -- a string containing a one-line ascii-art depiction of the current sync status
struct SYNC_INFO : NO_ARGS
{
static constexpr auto names() { return NAMES("sync_info"); }
};
struct output_distribution_data
{
std::vector<std::uint64_t> distribution;
std::uint64_t start_height;
std::uint64_t base;
};
/// RPC: blockchain/get_output_distribution
///
/// This endpoint returns the output distribution of the blockchain. Its primary use is for the
/// wallet to obtain the distribution of outputs on the blockchain so as to construct a feasible
/// decoy set.
///
/// Inputs:
///
/// - `amounts` -- Amounts to look for in atomic units.
/// - `from_height` -- starting height to check from. Optional (default is 0).
/// - `to_height` -- ending height to check up to; 0 (or omitted) means the current chain height.
/// - `cumulative` -- if true then results are cumulative output counts up to the given block; if
/// false (or omitted) then results are the number of outputs added in the given block.
/// - `binary` -- request the result in binary format (ignored for JSON requests)
/// - `compressed` -- (required `binary`) -- use varint encoding of the binary result
///
/// Outputs:
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `distributions` -- array of distribution data; each element is an object containing keys:
/// - `amount` -- the requested amount
/// - `start_height` -- the requested start height
/// - `base` -- the number of outputs at the start_height
/// - `binary` -- true if the result is binary. This will always be false for JSON-encoded
/// responses.
/// - `compressed` -- true if the result is binary and using varint encoding. Will always be
/// false for JSON-encoded responses.
/// - `distribution` -- the distribution of rct outputs in blocks beginning after
/// `start_height`. If `binary` and `compressed` are true then this is a binary value
/// consisting of varint-encoded values; if just `binary` is set then this is a raw dump of
/// unsigned 64-bit integer binary data of the values. When `binary` is unset (i.e. for a
/// JSON response) this is an array of integer values.
///
/// Example input:
/// ```json
/// { "amounts": [0], "from_height": 100002, "to_height": 100008, "cumulative": false }
/// ```
///
/// Example-JSON-Fetch
struct GET_OUTPUT_DISTRIBUTION : PUBLIC
{
static constexpr auto names() { return NAMES("get_output_distribution"); }
struct request
{
std::vector<uint64_t> amounts; // Amounts to look for in atomic units.
uint64_t from_height; // (optional, default is 0) starting height to check from.
uint64_t to_height; // (optional, default is 0) ending height to check up to.
bool cumulative; // (optional, default is false) States if the result should be cumulative (true) or not (false).
bool binary;
bool compress;
KV_MAP_SERIALIZABLE
};
struct distribution
{
rpc::output_distribution_data data;
uint64_t amount;
std::string compressed_data;
bool binary;
bool compress;
KV_MAP_SERIALIZABLE
};
struct response
{
std::string status; // General RPC error code. "OK" means everything looks good.
std::vector<distribution> distributions; //
KV_MAP_SERIALIZABLE
};
};
/// RPC: daemon/pop_blocks
///
/// Pop blocks off the main chain
///
/// Inputs:
///
/// - `nblocks` -- Number of blocks in that span.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `height` -- Height of the blockchain after blocks have been popped.
struct POP_BLOCKS : LEGACY
{
static constexpr auto names() { return NAMES("pop_blocks"); }
struct request_parameters
{
uint64_t nblocks;
} request;
};
/// RPC: daemon/prune_blockchain
///
/// Pruning is the process of removing non-critical blockchain information from local storage.
/// Full nodes keep an entire copy of everything that is stored on the blockchain, including data
/// that is not very useful anymore. Pruned nodes remove much of this less relevant information
/// to have a lighter footprint. Of course, running a full node is always better; however, pruned
/// nodes have most of the important information and can still support the network.
///
/// Inputs:
///
/// - `check` -- Instead of running check if the blockchain has already been pruned.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `pruned` -- Bool returning whether the blockchain was pruned or not.
/// - `pruning_seed` -- The seed that determined how the blockchain was to be pruned.
struct PRUNE_BLOCKCHAIN : RPC_COMMAND
{
static constexpr auto names() { return NAMES("prune_blockchain"); }
struct request_parameters
{
bool check;
} request;
};
/// RPC: network/get_quorum_state
///
/// Accesses the list of public keys of the nodes who are participating or being tested in a quorum.
///
/// Inputs:
///
/// - `start_height` -- (Optional): Start height, omit both start and end height to request the
/// latest quorum. Note that "latest" means different heights for different types of quorums as
/// not all quorums exist at every block heights.
/// - `end_height` -- (Optional): End height, omit both start and end height to request the latest
/// quorum
/// - `quorum_type` -- (Optional): Set value to request a specific quorum, 0 = Obligation, 1 =
/// Checkpointing, 2 = Blink, 3 = Pulse, 255 = all quorums, default is all quorums. For Pulse
/// quorums, requesting the blockchain height (or latest) returns the primary pulse quorum
/// responsible for the next block; for heights with blocks this returns the actual quorum,
/// which may be a backup quorum if the primary quorum did not produce in time.
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `quorums` -- An array of quorums associated with the requested height. Each element is
/// structured with the following keys:
/// - `service_node_pubkey` -- The public key of the Service Node, in hex (json) or binary (bt).
/// - `height` -- The height the quorums are relevant for
/// - `quorum_type` -- The quorum type
/// - `quorum` -- Quorum of Service Nodes. Each element is structured with the following keys:
/// - `validators` -- List of service node public keys in the quorum. For obligations quorums
/// these are the testing nodes; for checkpoint and blink these are the participating nodes
/// (there are no workers); for Pulse blink quorums these are the block signers. This is hex
/// encoded, even for bt-encoded requests.
/// - `workers` -- Public key of the quorum workers. For obligations quorums these are the
/// nodes being tested; for Pulse quorums this is the block producer. Checkpoint and Blink
/// quorums do not populate this field. This is hex encoded, even for bt-encoded requests.
///
/// Example input:
///
/// ```json
/// { "quorum_type": 3 }
/// ```
///
/// Example-JSON-Fetch
struct GET_QUORUM_STATE : PUBLIC
{
static constexpr auto names() { return NAMES("get_quorum_state"); }
static constexpr size_t MAX_COUNT = 256;
struct request_parameters
{
std::optional<uint64_t> start_height;
std::optional<uint64_t> end_height;
std::optional<uint8_t> quorum_type;
} request;
struct quorum_t
{
std::vector<std::string> validators;
std::vector<std::string> workers;
};
struct quorum_for_height
{
uint64_t height;
uint8_t quorum_type;
quorum_t quorum;
};
};
void to_json(nlohmann::json& j, const GET_QUORUM_STATE::quorum_t& q);
void to_json(nlohmann::json& j, const GET_QUORUM_STATE::quorum_for_height& q);
/// RPC: service_node/get_service_node_registration_cmd_raw
///
/// Generates a signed service node registration command for use in the operator's Oxen wallet.
/// This endpoint is primarily for internal use by the `oxend prepare_registration` command.
///
/// Inputs:
///
/// - `args` -- (Developer) The list of arguments used in raw registration, i.e. portions
/// - `make_friendly` -- Provide information about how to use the command in the result.
/// - `staking_requirement` -- The staking requirement to become a Service Node the registration
/// command will be generated upon
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `registration_cmd` -- The command to execute in the wallet CLI to register the queried
/// daemon as a Service Node.
struct GET_SERVICE_NODE_REGISTRATION_CMD_RAW : RPC_COMMAND
{
static constexpr auto names() { return NAMES("get_service_node_registration_cmd_raw"); }
struct request_parameters
{
std::vector<std::string> args;
bool make_friendly;
uint64_t staking_requirement;
} request;
};
OXEN_RPC_DOC_INTROSPECT
struct GET_SERVICE_NODE_REGISTRATION_CMD : RPC_COMMAND
{
static constexpr auto names() { return NAMES("get_service_node_registration_cmd"); }
struct contribution_t
{
std::string address; // The wallet address for the contributor
uint64_t amount; // The amount that the contributor will reserve in Loki atomic units towards the staking requirement
KV_MAP_SERIALIZABLE
};
struct request
{
std::string operator_cut; // The percentage of cut per reward the operator receives expressed as a string, i.e. "1.1%"
std::vector<contribution_t> contributions; // Array of contributors for this Service Node
uint64_t staking_requirement; // The staking requirement to become a Service Node the registration command will be generated upon
KV_MAP_SERIALIZABLE
};
struct response
{
std::string status; // Generic RPC error code. "OK" is the success value.
std::string registration_cmd; // The command to execute in the wallet CLI to register the queried daemon as a Service Node.
KV_MAP_SERIALIZABLE
};
};
/// RPC: service_node/get_service_keys
///
/// Get the service public keys of the queried daemon, encoded in hex. All three keys are used
/// when running as a service node; when running as a regular node only the x25519 key is regularly
/// used for some RPC and and node-to-SN communication requests.
///
/// Inputs: None
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `service_node_pubkey` -- The queried daemon's service node public key. Will be empty if not
/// running as a service node.
/// - `service_node_ed25519_pubkey` -- The daemon's ed25519 auxiliary public key.
/// - `service_node_x25519_pubkey` -- The daemon's x25519 auxiliary public key.
struct GET_SERVICE_KEYS : NO_ARGS
{
static constexpr auto names() { return NAMES("get_service_keys", "get_service_node_key"); }
};
/// RPC: service_node/get_service_privkeys
///
/// Get the service private keys of the queried daemon, encoded in hex. Do not ever share
/// these keys: they would allow someone to impersonate your service node. All three keys are used
/// when running as a service node; when running as a regular node only the x25519 key is regularly
/// used for some RPC and and node-to-SN communication requests.
///
/// Inputs: None
///
/// Outputs:
///
/// - `status` -- General RPC status string. `"OK"` means everything looks good.
/// - `service_node_privkey` -- The queried daemon's service node private key. Will be empty if
/// not running as a service node.
/// - `service_node_ed25519_privkey` -- The daemon's ed25519 private key (note that this is in
/// sodium's format, which consists of the private and public keys concatenated together)
/// - `service_node_x25519_privkey` -- The daemon's x25519 private key.
struct GET_SERVICE_PRIVKEYS : NO_ARGS
{
static constexpr auto names() { return NAMES("get_service_privkeys", "get_service_node_privkey"); }
};
/// RPC: service_node/get_service_nodes
///
/// Get information on some, all, or a random subset of Service Nodes.
///
/// Inputs:
/// - `fields` -- Set of fields to return; listed fields apply to both the top level (such as
/// `"height"` or `"block_hash"`) and to keys inside `service_node_states`. Fields should be
/// provided as a list of field names to include. For backwards compatibility when making a
/// json request field names can also be provided as a dictionary of `{"field_name": true}`
/// pairs, but this usage is deprecated (and not supported for bt-encoded requests).
///
/// The special field name `"all"` can be used to request all available fields; this is the
/// default when no fields key are provided at all. Be careful when requesting all fields:
/// the response can be very large.
///
/// When providing a list you may prefix a field name with a `-` (e.g. `"-funded"`) to remove
/// the field from the list; this is mainly useful when following `"all"` to remove some
/// fields from the returned results. (There is no equivalent mode when using the deprecated
/// dict value).
///
/// - `service_node_pubkeys` -- Array of public keys of registered service nodes to request
/// information about. Omit to query all service nodes. For a JSON request pubkeys must be
/// specified in hex; for a bt-encoded request pubkeys can be hex or bytes.
///
/// - `active_only` -- If true then only return active service nodes.
///
/// - `limit` -- If specified and non-zero then only return a random selection of this number of
/// service nodes (in random order) from the result. If negative then no limiting is performed
/// but the returned result is still shuffled.
///
/// - `poll_block_hash` -- If specified then only return results if the current top block hash is
/// different than the hash given here. This is intended to allow quick polling of results
/// without needing to do anything if the block (and thus SN registrations) have not changed
/// since the last request.
///
/// Outputs:
///
/// Output variables available are as follows (you can request which parameters are returned; see
/// the request parameters description). Note that OXEN values are returned in atomic OXEN units,
/// which are nano-OXEN (i.e. 1.000000000 OXEN will be returned as 1000000000).
///
/// - `height` -- the height of the current top block. (Note that this is one less than the
/// "blockchain height" as would be returned by the [`get_info`](#get_info) endpoint).
/// - `target_height` -- the target height of the blockchain; will be greater than height+1 if this
/// node is still syncing the chain.
/// - `block_hash` -- the hash of the most recent block
/// - `hardfork` -- the current hardfork version of the daemon
/// - `snode_revision` -- the current snode revision for non-hardfork, but mandatory, service node
/// updates.
/// - `status` -- generic RPC error code; "OK" means the request was successful.
/// - `unchanged` -- when using poll_block_hash, this value is set to true and results are omitted
/// if the current block hash has not changed from the requested polling block hash. If block
/// hash has changed this is set to false (and results included). When not polling this value
/// is omitted entirely.
/// - `service_node_states` -- list of information about all known service nodes; each element is a
/// dict containing the following keys (which fields are included/omitted can be controlled via
/// the "fields" input parameter):
/// - `service_node_pubkey` -- The public key of the Service Node, in hex (json) or binary (bt).
/// - `registration_height` -- The height at which the registration for the Service Node arrived
/// on the blockchain.
/// - `registration_hf_version` -- The current hard fork at which the registration for the Service
/// Node arrived on the blockchain.
/// - `requested_unlock_height` -- If an unlock has been requested for this SN, this field
/// contains the height at which the Service Node registration expires and contributions will
/// be released.
/// - `last_reward_block_height` -- The height that determines when this service node will next
/// receive a reward. This field is somewhat misnamed for historic reasons: it is updated
/// when receiving a reward, but is also updated when a SN is activated, recommissioned, or
/// has an IP change position reset, and so does not strictly indicate when a reward was
/// received.
/// - `last_reward_transaction_index` -- When multiple Service Nodes register (or become
/// active/reactivated) at the same height (i.e. have the same last_reward_block_height), this
/// field contains the activating transaction position in the block which is used to break
/// ties in determining which SN is next in the reward list.
/// - `active` -- True if fully funded and not currently decommissioned (and so `funded and not
/// active` implicitly defines decommissioned).
/// - `funded` -- True if the required stakes have been submitted to activate this Service Node.
/// - `state_height` -- Indicates the height at which the service node entered its current state:
/// - If `active` is true: this is the height at which the service node last became active
/// (i.e. became fully staked, or was last recommissioned);
/// - If decommissioned (i.e. `funded and not active`): the decommissioning height;
/// - If awaiting contributions (i.e. `not funded`): the height at which the last contribution
/// (or registration) was processed.
/// - `decommission_count` -- The number of times the Service Node has been decommissioned since
/// registration
/// - `last_decommission_reason_consensus_all` -- The reason for the last decommission as voted by
/// the testing quorum SNs that decommissioned the node. This is a numeric bitfield made up
/// of the sum of given reasons (multiple reasons may be given for a decommission). Values
/// are included here if *all* quorum members agreed on the reasons:
/// - `0x01` - Missing uptime proofs
/// - `0x02` - Missed too many checkpoint votes
/// - `0x04` - Missed too many pulse blocks
/// - `0x08` - Storage server unreachable
/// - `0x10` - oxend quorumnet unreachable for timesync checks
/// - `0x20` - oxend system clock is too far off
/// - `0x40` - Lokinet unreachable
/// - other bit values are reserved for future use.
/// - `last_decommission_reason_consensus_any` -- The reason for the last decommission as voted
/// by *any* SNs. Reasons are set here if *any* quorum member gave a reason, even if not all
/// quorum members agreed. Bit values are the same as
/// `last_decommission_reason_consensus_all`.
/// - `decomm_reasons` -- a gentler version of the last_decommission_reason_consensus_all/_any
/// values: this is returned as a dict with two keys, `"all"` and `"some"`, containing a list
/// of short string identifiers of the reasons. `"all"` contains reasons that are agreed upon
/// by all voting nodes; `"some"` contains reasons that were provided by some but not all
/// nodes (and is included only if there are at least one such value). Note that,
/// unlike `last_decommission_reason_consensus_any`, the `"some"` field only includes reasons
/// that are *not* included in `"all"`. Returned values in the lists are:
/// - `"uptime"`
/// - `"checkpoints"`
/// - `"pulse"`
/// - `"storage"`
/// - `"timecheck"`
/// - `"timesync"`
/// - `"lokinet"`
/// - other values are reserved for future use.
/// - `earned_downtime_blocks` -- The number of blocks earned towards decommissioning (if
/// currently active), or the number of blocks remaining until the service node is eligible
/// for deregistration (if currently decommissioned).
/// - `service_node_version` -- The three-element numeric version of the Service Node (as received
/// in the last uptime proof). Omitted if we have never received a proof.
/// - `lokinet_version` -- The major, minor, patch version of the Service Node's lokinet router
/// (as received in the last uptime proof). Omitted if we have never received a proof.
/// - `storage_server_version` -- The major, minor, patch version of the Service Node's storage
/// server (as received in the last uptime proof). Omitted if we have never received a proof.
/// - `contributors` -- Array of contributors, contributing to this Service Node. Each element is
/// a dict containing:
/// - `amount` -- The total amount of OXEN staked by this contributor into
/// this Service Node.
/// - `reserved` -- The amount of OXEN reserved by this contributor for this Service Node; this
/// field will be included only if the contributor has unfilled, reserved space in the
/// service node.
/// - `address` -- The wallet address of this contributor to which rewards are sent and from
/// which contributions were made.
/// - `locked_contributions` -- Array of contributions from this contributor; this field
/// (unlike the other fields inside `contributors`) is controlled by the `fields` input
/// parameter. Each element contains:
/// - `key_image` -- The contribution's key image which is locked on the network.
/// - `key_image_pub_key` -- The contribution's key image, public key component.
/// - `amount` -- The amount of OXEN that is locked in this contribution.
/// - `total_contributed` -- The total amount of OXEN contributed to this Service Node.
/// - `total_reserved` -- The total amount of OXEN contributed or reserved for this Service Node.
/// Only included in the response if there are still unfilled reservations (i.e. if it is
/// greater than total_contributed).
/// - `staking_requirement` -- The total OXEN staking requirement in that is/was required to be
/// contributed for this Service Node.
/// - `portions_for_operator` -- The operator fee to take from the service node reward, as a
/// fraction of 18446744073709551612 (2^64 - 4) (that is, this number corresponds to 100%).
/// Note that some JSON parsers may silently change this value while parsing as typical values
/// do not fit into a double without loss of precision.
/// - `operator_fee` -- The operator fee expressed in millionths (and rounded to the nearest
/// integer value). That is, 1000000 corresponds to a 100% fee, 34567 corresponds to a
/// 3.4567% fee. Note that this number is for human consumption; the actual value that
/// matters for the blockchain is the precise `portions_for_operator` value.
/// - `swarm_id` -- The numeric identifier of the Service Node's current swarm. Note that
/// returned values can exceed the precision available in a double value, which can result in
/// (changed) incorrect values by some JSON parsers. Consider using `swarm` instead if you
/// are not sure your JSON parser supports 64-bit values.
/// - `swarm` -- The swarm id, expressed in hexadecimal, such as `"f4ffffffffffffff"`.
/// - `operator_address` -- The wallet address of the Service Node operator.
/// - `public_ip` -- The public ip address of the service node; omitted if we have not yet
/// received a network proof containing this information from the service node.
/// - `storage_port` -- The port number associated with the storage server; omitted if we have no
/// uptime proof yet.
/// - `storage_lmq_port` -- The port number associated with the storage server (oxenmq interface);
/// omitted if we have no uptime proof yet.
/// - `quorumnet_port` -- The port for direct SN-to-SN oxend communication (oxenmq interface).
/// Omitted if we have no uptime proof yet.
/// - `pubkey_ed25519` -- The service node's ed25519 public key for auxiliary services. Omitted if
/// we have no uptime proof yet. Note that for newer registrations this will be the same as
/// the `service_node_pubkey`.
/// - `pubkey_x25519` -- The service node's x25519 public key for auxiliary services (mainly
/// used for `quorumnet_port` and the `storage_lmq_port` OxenMQ encrypted connections).
/// - `last_uptime_proof` -- The last time we received an uptime proof for this service node from
/// the network, in unix epoch time. 0 if we have never received one.
/// - `storage_server_reachable` -- True if this storage server is currently passing tests for the
/// purposes of SN node testing: true if the last test passed, or if it has been unreachable
/// for less than an hour; false if it has been failing tests for more than an hour (and thus
/// is considered unreachable). This field is omitted if the queried oxend is not a service
/// node.
/// - `storage_server_first_unreachable` -- If the last test we received was a failure, this field
/// contains the timestamp when failures started. Will be 0 if the last result was a success,
/// and will be omitted if the node has not yet been tested since this oxend last restarted.
/// - `storage_server_last_unreachable` -- The last time this service node's storage server failed
/// a ping test (regardless of whether or not it is currently failing). Will be omitted if it
/// has never failed a test since startup.
/// - `storage_server_last_reachable` -- The last time we received a successful ping response for
/// this storage server (whether or not it is currently failing). Will be omitted if we have
/// never received a successful ping response since startup.
/// - `lokinet_reachable` -- Same as `storage_server_reachable`, but for lokinet router testing.
/// - `lokinet_first_unreachable` -- Same as `storage_server_first_unreachable`, but for lokinet
/// router testing.
/// - `lokinet_last_unreachable` -- Same as `storage_server_last_unreachable`, but for lokinet
/// router testing.
/// - `lokinet_last_reachable` -- Same as `storage_server_last_reachable`, but for lokinet router
/// testing.
/// - `checkpoint_votes` -- dict containing recent received checkpoint voting information for this
/// service node. Service node tests will fail if too many recent pulse blocks are missed.
/// Contains keys:
/// - `voted` -- list of blocks heights at which a required vote was received from this
/// service node
/// - `missed` -- list of block heights at which a vote from this service node was required
/// but not received.
/// - `pulse_votes` -- dict containing recent pulse blocks in which this service node was supposed
/// to have participated. Service node testing will fail if too many recent pulse blocks are
/// missed. Contains keys:
/// - `voted` -- list of `[<HEIGHT>, <ROUND>]` pairs in which an expected pulse participation
/// was recorded for this node. `<ROUND>` starts at `0` and increments for backup pulse
/// quorums if a previous round does not broadcast a pulse block for the given height in
/// time.
/// - `missed` -- list of `[<HEIGHT>, <ROUND>]` pairs in which pulse participation by this
/// service node was expected but did not occur.
/// - `quorumnet_tests` -- array containing the results of recent attempts to connect to the
/// remote node's quorumnet port (while conducting timesync checks). The array contains two
/// values: `[<SUCCESSES>, <FAILURES>]`, where `<SUCCESSES>` is the number of recent
/// successful connections and FAILURES is the number of recent connection and/or request
/// timeouts. If there are two many failures then the service node will fail testing.
/// - `timesync_tests` -- array containing the results of recent time synchronization checks of
/// this service node. Contains `[<SUCCESSES>, <FAILURES>]` counts where `<SUCCESSES>` is the
/// number of recent checks where the system clock was relatively close and FAILURES is the
/// number of recent checks where we received a significantly out-of-sync timestamp response
/// from the service node. A service node fails tests if there are too many recent
/// out-of-sync responses.
///
/// Example input:
/// ```json
/// { "limit": 1 }
/// ```
///
/// Example-JSON-Fetch
struct GET_SERVICE_NODES : PUBLIC
{
static constexpr auto names() { return NAMES("get_service_nodes", "get_n_service_nodes", "get_all_service_nodes"); }
struct request_parameters {
std::unordered_set<std::string> fields;
std::vector<crypto::public_key> service_node_pubkeys;
bool active_only = false;
int limit = 0;
crypto::hash poll_block_hash{};
} request;
};
/// RPC: service_node/get_service_node_status
///
/// Retrieves information on the current daemon's Service Node state. The returned information is
/// the same as what would be returned by "get_service_nodes" when passed this service node's
/// public key.
///
/// Inputs: none.
///
/// Outputs:
/// - `service_node_state` -- if this is a registered service node then all available fields for
/// this service node. See [`get_service_nodes`](#get_service_nodes) for the list of fields.
/// Note that some fields (such as remote testing results) will not be available (through this
/// call or [`get_service_nodes`](#get_service_nodes)) because a service node is incapable of
/// testing itself for remote connectivity. If this daemon is running in service node mode but
/// not registered then only SN pubkey, ip, and port fields are returned.
/// - `height` -- current top block height at the time of the request (note that this is generally
/// one less than the "blockchain height").
/// - `block_hash` -- current top block hash at the time of the request
/// - `status` -- generic RPC error code; "OK" means the request was successful.
struct GET_SERVICE_NODE_STATUS : NO_ARGS
{
static constexpr auto names() { return NAMES("get_service_node_status"); }
};
/// RPC: blockchain/get_accrued_batched_earnings
///
/// Retrieve the current "balance" of accrued service node rewards for the given addresses.
///
/// Inputs:
/// - `addresses` -- a set of addresses about which to query. If omitted/empty then all addresses
/// with balances are returned.
///
/// Outputs:
/// - `balances` -- a dict where keys are the wallet addresses and values are the balance (in
/// atomic OXEN units).
struct GET_ACCRUED_BATCHED_EARNINGS : PUBLIC
{
static constexpr auto names() { return NAMES("get_accrued_batched_earnings"); }
struct request_parameters
{
std::vector<std::string> addresses;
} request;
};
/// Dev-RPC: service_node/storage_server_ping
///
/// Endpoint to receive an uptime ping from the connected storage server. This is used
/// to record whether the storage server is ready before the service node starts
/// sending uptime proofs. This is usually called internally from the storage server
/// and this endpoint is mostly available for testing purposes.
///
/// Inputs:
///
/// - `version` -- Storage server version (as an array of three integers).
/// - `https_port` -- Storage server https port to include in uptime proofs.
/// - `omq_port` -- Storage server oxenmq port to include in uptime proofs.
/// - `ed25519_pubkey` -- Service node Ed25519 pubkey for verifying that storage server is running
/// with the correct service node keys.
/// - `error` -- If given and non-empty then this is an error message telling oxend to *not*
/// submit an uptime proof and to report this error in the logs instead. Oxend won't send
/// proofs until it gets another ping (without an error).
///
/// Outputs:
///
/// - `status` -- generic RPC error code; "OK" means the request was successful.
struct STORAGE_SERVER_PING : RPC_COMMAND
{
static constexpr auto names() { return NAMES("storage_server_ping"); }
struct request_parameters
{
std::array<uint16_t, 3> version;
uint16_t https_port;
uint16_t omq_port;
std::string ed25519_pubkey;
std::string error;
} request;
};
/// Dev-RPC: service_node/lokinet_ping
///
/// Endpoint to receive an uptime ping from the connected lokinet server. This is used
/// to record whether lokinet is ready before the service node starts sending uptime proofs.
/// This is usually called internally from Lokinet and this endpoint is mostly
/// available for testing purposes.
///
/// Inputs:
///
/// - `version` -- Lokinet version (as an array of three integers).
/// - `ed25519_pubkey` -- Service node Ed25519 pubkey for verifying that lokinet is running with
/// the correct service node keys.
/// - `error` -- If given and non-empty then this is an error message telling oxend to *not*
/// submit an uptime proof and to report this error in the logs instead. Oxend won't send
/// proofs until it gets another ping (without an error).
///
/// Outputs:
///
/// - `status` -- generic RPC error code; "OK" means the request was successful.
struct LOKINET_PING : RPC_COMMAND
{
static constexpr auto names() { return NAMES("lokinet_ping"); }
struct request_parameters
{
std::array<uint16_t, 3> version;
std::string ed25519_pubkey;
std::string error;
} request;
};
/// RPC: service_node/get_staking_requirement
///
/// Get the required amount of Oxen to become a Service Node at the queried height.
/// For devnet and testnet values, ensure the daemon is started with the
/// `--devnet` or `--testnet` flags respectively.
///
/// Inputs:
///
/// - `height` -- The height to query the staking requirement for. 0 (or omitting) means current
/// height.
///
/// Outputs:
///
/// - `status` -- generic RPC error code; "OK" means the request was successful.
/// - `staking_requirement` -- The staking requirement in Oxen, in atomic units.
/// - `height` -- The height requested (or current height if 0 was requested)
struct GET_STAKING_REQUIREMENT : PUBLIC
{
static constexpr auto names() { return NAMES("get_staking_requirement"); }
struct request_parameters
{
uint64_t height;
} request;
};
/// RPC: blockchain/get_service_node_blacklisted_key_images
///
/// Get information on blacklisted Service Node key images.
///
/// Inputs: None
///
/// Outputs:
///
/// - `status` -- generic RPC error code; "OK" means the request was successful.
/// - `blacklist` -- Array of blacklisted key images, i.e. unspendable transactions. Each entry
/// contains:
/// - `key_image` -- The key image of the transaction that is blacklisted on the network.
/// - `unlock_height` -- The height at which the key image is removed from the blacklist and
/// becomes spendable.
/// - `amount` -- The total amount of locked Loki in atomic units in this blacklisted stake.
struct GET_SERVICE_NODE_BLACKLISTED_KEY_IMAGES : PUBLIC, NO_ARGS
{
static constexpr auto names() { return NAMES("get_service_node_blacklisted_key_images"); }
};
/// RPC: blockchain/get_checkpoints
///
/// Query hardcoded/service node checkpoints stored for the blockchain. Omit all arguments to
/// retrieve the latest "count" checkpoints.
///
/// Inputs:
///
/// - `start_height` -- Optional: Get the first count checkpoints starting from this height.
/// Specify both start and end to get the checkpoints inbetween.
/// - `end_height` -- Optional: Get the first count checkpoints before end height. Specify both
/// start and end to get the checkpoints inbetween.
/// - `count` -- Optional: Number of checkpoints to query.
///
/// Outputs:
///
/// - `status` -- generic RPC error code; "OK" means the request was successful.
/// - `checkpoints` -- Array of requested checkpoints
///
/// Example input:
/// ```json
/// { "count": 2 }
/// ```
///
/// Example-JSON-Fetch
struct GET_CHECKPOINTS : PUBLIC
{
static constexpr auto names() { return NAMES("get_checkpoints"); }
static constexpr uint32_t MAX_COUNT = 256;
static constexpr uint32_t NUM_CHECKPOINTS_TO_QUERY_BY_DEFAULT = 60;
struct request_parameters
{
std::optional<uint64_t> start_height;
std::optional<uint64_t> end_height;
std::optional<uint32_t> count;
} request;
};
/// RPC: blockchain/get_service_nodes_state_changes
///
/// Query the number of service node state change transactions contained in a range of blocks.
///
/// Inputs:
///
/// - `start_height` -- The starting block's height.
/// - `end_height` -- The ending block's height.
///
/// Outputs:
///
/// - `status` -- Generic RPC error code. "OK" is the success value.
/// - `total_deregister` -- the total number of service node deregistrations
/// - `total_ip_change_penalty` -- the total number of IP change penalties
/// - `total_decommission` -- the total number of service node decommissions
/// - `total_recommission` -- the total number of service node recommissions
/// - `total_unlock` -- the total number of service node unlock requests
/// - `start_height` -- the start height of the given statistics
/// - `end_height` -- the end height of the given statistics
///
/// Example input:
/// ```json
/// { "start_height": 1085000, "end_height": 1085191 }
/// ```
///
/// Example-JSON-Fetch
struct GET_SN_STATE_CHANGES : RPC_COMMAND
{
static constexpr auto names() { return NAMES("get_service_nodes_state_changes"); }
struct request_parameters
{
uint64_t start_height;
std::optional<uint64_t> end_height;
} request;
};
/// Dev-RPC: service_node/report_peer_status
///
/// Reports service node peer status (success/fail) from lokinet and storage server.
///
/// Inputs:
///
/// - `type` -- test type; currently supported are: "storage" and "lokinet" for storage server and
/// lokinet tests, respectively.
/// - `pubkey` -- service node pubkey
/// - `passed` -- whether node is passing the test
///
/// Outputs:
///
/// - `status` -- Generic RPC error code. "OK" is the success value.
struct REPORT_PEER_STATUS : RPC_COMMAND
{
// TODO: remove the `report_peer_storage_server_status` once we require a storage server version
// that stops using the old name.
static constexpr auto names() { return NAMES("report_peer_status", "report_peer_storage_server_status"); }
struct request_parameters
{
std::string type;
std::string pubkey;
bool passed;
} request;
};
/// Dev-RPC: daemon/test_trigger_p2p_resync
///
/// Deliberately undocumented; this RPC call is really only useful for testing purposes to reset
/// the resync idle timer (which normally fires every 60s) for the test suite.
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- Generic RPC error code. "OK" is the success value.
struct TEST_TRIGGER_P2P_RESYNC : NO_ARGS
{
static constexpr auto names() { return NAMES("test_trigger_p2p_resync"); }
};
/// Dev-RPC: service_node/test_trigger_uptime_proof
///
/// Deliberately undocumented; this RPC call is really only useful for testing purposes to
/// force send an uptime proof. NOT available on mainnet
///
/// Inputs: none
///
/// Outputs:
///
/// - `status` -- Generic RPC error code. "OK" is the success value.
struct TEST_TRIGGER_UPTIME_PROOF : NO_ARGS
{
static constexpr auto names() { return NAMES("test_trigger_uptime_proof"); }
};
OXEN_RPC_DOC_INTROSPECT
// Get the name mapping for a Loki Name Service entry. Loki currently supports mappings
// for Session and Lokinet.
struct ONS_NAMES_TO_OWNERS : PUBLIC
{
static constexpr auto names() { return NAMES("ons_names_to_owners", "lns_names_to_owners"); }
static constexpr size_t MAX_REQUEST_ENTRIES = 256;
static constexpr size_t MAX_TYPE_REQUEST_ENTRIES = 8;
struct request_entry
{
std::string name_hash; // The 32-byte BLAKE2b hash of the name to resolve to a public key via Loki Name Service. The value must be provided either in hex (64 hex digits) or base64 (44 characters with padding, or 43 characters without).
std::vector<uint16_t> types; // If empty, query all types. Currently supported types are 0 (session) and 2 (lokinet). In future updates more mapping types will be available.
KV_MAP_SERIALIZABLE
};
struct request
{
std::vector<request_entry> entries; // Entries to look up
bool include_expired; // Optional: if provided and true, include entries in the results even if they are expired
KV_MAP_SERIALIZABLE
};
struct response_entry
{
uint64_t entry_index; // The index in request_entry's `entries` array that was resolved via Loki Name Service.
ons::mapping_type type; // The type of Loki Name Service entry that the owner owns: currently supported values are 0 (session), 1 (wallet) and 2 (lokinet)
std::string name_hash; // The hash of the name that was queried, in base64
std::string owner; // The public key that purchased the Loki Name Service entry.
std::optional<std::string> backup_owner; // The backup public key that the owner specified when purchasing the Loki Name Service entry. Omitted if no backup owner.
std::string encrypted_value; // The encrypted value that the name maps to. See the `ONS_RESOLVE` description for information on how this value can be decrypted.
uint64_t update_height; // The last height that this Loki Name Service entry was updated on the Blockchain.
std::optional<uint64_t> expiration_height; // For records that expire, this will be set to the expiration block height.
std::string txid; // The txid of the mapping's most recent update or purchase.
KV_MAP_SERIALIZABLE
};
struct response
{
std::vector<response_entry> entries;
std::string status; // Generic RPC error code. "OK" is the success value.
KV_MAP_SERIALIZABLE
};
};
/// RPC: ons/ons_owners_to_names
///
/// Get all the name mappings for the queried owner. The owner can be either a ed25519 public key
/// or Monero style public key; by default purchases are owned by the spend public key of the
/// purchasing wallet.
///
/// Inputs:
///
/// - `entries` -- List of owner's public keys to find all Oxen Name Service entries for.
/// - `include_expired` -- Optional: if provided and true, include entries in the results even if
/// they are expired
///
/// Outputs:
///
/// - `status` -- Generic RPC error code. "OK" is the success value.
/// - `entries` -- List of ONS names. Each element is structured as follows:
/// - `request_index` -- (Deprecated) The index in request's `entries` array that was resolved
/// via Loki Name Service.
/// - `type` -- The category the Loki Name Service entry belongs to; currently 0 for Session, 1
/// for Wallet and 2 for Lokinet.
/// - `name_hash` -- The hash of the name that the owner purchased via Loki Name Service in
/// base64
/// - `owner` -- The backup public key specified by the owner that purchased the Loki Name
/// Service entry.
/// - `backup_owner` -- The backup public key specified by the owner that purchased the Loki
/// Name Service entry. Omitted if no backup owner.
/// - `encrypted_value` -- The encrypted value that the name maps to, in hex. This value is
/// encrypted using the name (not the hash) as the secret.
/// - `update_height` -- The last height that this Loki Name Service entry was updated on the
/// Blockchain.
/// - `expiration_height` -- For records that expire, this will be set to the expiration block
/// height.
/// - `txid` -- The txid of the mapping's most recent update or purchase.
struct ONS_OWNERS_TO_NAMES : PUBLIC
{
static constexpr auto names() { return NAMES("ons_owners_to_names", "lns_owners_to_names"); }
static constexpr size_t MAX_REQUEST_ENTRIES = 256;
struct request_parameters
{
std::vector<std::string> entries;
bool include_expired;
} request;
struct response_entry
{
uint64_t request_index;
ons::mapping_type type;
std::string name_hash;
std::string owner;
std::optional<std::string> backup_owner;
std::string encrypted_value;
uint64_t update_height;
std::optional<uint64_t> expiration_height;
std::string txid;
};
};
void to_json(nlohmann::json& j, const ONS_OWNERS_TO_NAMES::response_entry& r);
/// RPC: ons/ons_resolve
///
/// Performs a simple ONS lookup of a BLAKE2b-hashed name. This RPC method is meant for simple,
/// single-value resolutions that do not care about registration details, etc.; if you need more
/// information use ONS_NAMES_TO_OWNERS instead.
///
/// Inputs:
///
/// - `type` -- The ONS type (mandatory); currently support values are: `0` for Session, `1` for
/// wallet, and `2` for Lokinet.
/// - `name_hash` -- The 32-byte BLAKE2b hash of the name to look up, encoded as 64 hex digits or
/// 44/43 base64 characters (with/without padding). For bt-encoded requests this can also be
/// the raw 32 bytes.
///
/// Outputs:
///
/// - `encrypted_value` -- The encrypted ONS value, in hex. Will be omitted from the response if
/// the given name_hash is not registered.
/// - `nonce` -- The nonce value used for encryption, in hex. Will be omitted if the given name is
/// not registered.
///
/// Technical details: the returned value is encrypted using the name itself so that neither this
/// oxend responding to the RPC request nor any other blockchain observers can (easily) obtain the
/// name of registered addresses or the registration details. Thus, from a client's point of
/// view, resolving an ONS record involves:
///
/// 1. Lower-case the name.
/// 2. Calculate the name hash as a null-key, 32-byte BLAKE2b hash of the lower-case name.
/// 3. Obtain the encrypted value and the nonce from this RPC call (or ONS_NAMES_TO_OWNERS); when
/// using json encode the name hash using either hex or base64.
/// 4. Calculate the decryption key as a 32-byte BLAKE2b *keyed* hash of the name using the
/// (unkeyed) name hash calculated above (in step 2) as the hash key.
/// 5. Decrypt (and verify) using XChaCha20-Poly1305 (for example libsodium's
/// crypto_aead_xchacha20poly1305_ietf_decrypt) using the above decryption key and using the
/// first 24 bytes of the name hash as the public nonce.
///
/// Example input:
///
/// To look up the lokinet address for blocks.loki, we first need to get the name hash. Using
/// Python, for example:
///
/// ```python
/// >>> import hashlib
/// >>> import base64
/// >>> name_hash = hashlib.blake2b(b'blocks.loki', digest_size=32).digest()
/// >>> base64.b64encode(name_hash)
/// b'IeynFEjyxigd0Lcmo5FWYaGp/uVXsa5grK8Jml0ai3o='
/// ```
///
/// Which then allows the RPC lookup:
///
/// ```json
/// { "type": 2, "name_hash": "IeynFEjyxigd0Lcmo5FWYaGp/uVXsa5grK8Jml0ai3o=" }
/// ```
///
/// Example output:
///
/// ```json
/// {
/// "encrypted_value": "b52c088ae51171a9e2e44cc98c10006547e2981d4cbe196525c948fa2fa48a11e8712eccd0ba20e4b93fb3989361df8a",
/// "nonce": "6e3e80c7927108612475a0eeddf472af6177c9776d6943ed"
/// }
/// ```
///
/// To decrypt, again using Python for an example:
///
/// ```python
/// >>> import hashlib
/// >>> import base64
/// >>> import nacl.bindings
/// >>> import oxenc
/// >>> data = bytes.fromhex("b52c088ae51171a9e2e44cc98c10006547e2981d4cbe196525c948fa2fa48a11e8712eccd0ba20e4b93fb3989361df8a")
/// >>> nonce = bytes.fromhex("6e3e80c7927108612475a0eeddf472af6177c9776d6943ed")
/// >>> name_hash = hashlib.blake2b(b'blocks.loki', digest_size=32).digest()
/// >>> key = hashlib.blake2b(b'blocks.loki', key=name_hash, digest_size=32).digest()
/// >>> val = nacl.bindings.crypto_aead_xchacha20poly1305_ietf_decrypt(ciphertext=data, nonce=nonce, aad=b'', key=key)
/// >>> oxenc.to_base32z(val) + ".loki"
/// 'kcpyawm9se7trdbzncimdi5t7st4p5mh9i1mg7gkpuubi4k4ku1y.loki'
/// ```
///
/// which is the full lokinet address of the blocks.loki.
///
/// Example input:
///
/// For a Session lookup you follow exactly the same steps as the above example, but using the
/// session ID instead of `blocks.loki`. For example for the Session ONS `jagerman` you would get
/// the name_hash and then request:
///
/// ```json
/// { "type": 0, "name_hash": "yB7mbm2q1MaczqNZCYguH+71z5jooEMeXA0sncfni+g=" }
/// ```
///
/// Example output:
///
/// ```json
/// {
/// "encrypted_value": "d9bca6752665f2254ec7522f98aa5f2dfb13c9fa1ad1e39cd3d7a89a0df04719e348da537bc310a53e3b59ca24639b9b42",
/// "nonce": "73e8243f3fadd471be36c6df3d62f863f9bb3a9d1cc696c0"
/// }
/// ```
///
/// Decryption here is exactly the same as the above example except for the last step:
///
/// ```python
/// >>> import hashlib
/// >>> import base64
/// >>> import nacl.bindings
/// >>> data = bytes.fromhex("d9bca6752665f2254ec7522f98aa5f2dfb13c9fa1ad1e39cd3d7a89a0df04719e348da537bc310a53e3b59ca24639b9b42")
/// >>> nonce = bytes.fromhex("73e8243f3fadd471be36c6df3d62f863f9bb3a9d1cc696c0")
/// >>> name_hash = hashlib.blake2b(b'jagerman', digest_size=32).digest()
/// >>> key = hashlib.blake2b(b'jagerman', key=name_hash, digest_size=32).digest()
/// >>> val = nacl.bindings.crypto_aead_xchacha20poly1305_ietf_decrypt(ciphertext=data, nonce=nonce, aad=b'', key=key)
/// >>> '05' + val.hex()
/// '0505fb466d312e1666ad1c84c4ee55b7e034151c0e366a313d95d11436a5f36e1e75'
/// ```
///
/// which is jagerman's full Session ID.
struct ONS_RESOLVE : PUBLIC
{
static constexpr auto names() { return NAMES("ons_resolve", "lns_resolve"); }
struct request_parameters {
/// The ONS type (mandatory); currently supported values are: 0 = session, 1 = wallet, 2 =
/// lokinet.
int type = -1;
std::string name_hash;
} request;
};
/// RPC: daemon/flush_cache
///
/// Clear TXs from the daemon cache, currently only the cache storing TX hashes that were
/// previously verified bad by the daemon.
///
/// Inputs:
///
/// - `bad_txs` -- Clear the cache storing TXs that failed verification.
/// - `bad_blocks` -- Clear the cache storing blocks that failed verfication.
///
/// Outputs:
///
/// - `status` -- Generic RPC error code. "OK" is the success value.
struct FLUSH_CACHE : RPC_COMMAND
{
static constexpr auto names() { return NAMES("flush_cache"); }
struct request_parameter
{
bool bad_txs;
bool bad_blocks;
} request;
};
// List of all supported rpc command structs to allow compile-time enumeration of all supported
// RPC types. Every type added above that has an RPC endpoint needs to be added here, and needs
// a core_rpc_server::invoke() overload that takes a <TYPE>::request and returns a
// <TYPE>::response. The <TYPE>::request has to be unique (for overload resolution);
// <TYPE>::response does not.
using core_rpc_types = tools::type_list<
BANNED,
FLUSH_CACHE,
FLUSH_TRANSACTION_POOL,
GET_ACCRUED_BATCHED_EARNINGS,
GET_ALTERNATE_CHAINS,
GET_BANS,
GET_BASE_FEE_ESTIMATE,
GET_BLOCK,
GET_BLOCK_COUNT,
GET_BLOCK_HASH,
GET_BLOCK_HEADERS_RANGE,
GET_BLOCK_HEADER_BY_HASH,
GET_BLOCK_HEADER_BY_HEIGHT,
GET_CHECKPOINTS,
GET_COINBASE_TX_SUM,
GET_CONNECTIONS,
GET_HEIGHT,
GET_INFO,
GET_LAST_BLOCK_HEADER,
GET_LIMIT,
GET_NET_STATS,
GET_OUTPUTS,
GET_OUTPUT_HISTOGRAM,
GET_PEER_LIST,
GET_QUORUM_STATE,
GET_SERVICE_KEYS,
GET_SERVICE_NODES,
GET_SERVICE_NODE_BLACKLISTED_KEY_IMAGES,
GET_SERVICE_NODE_REGISTRATION_CMD_RAW,
GET_SERVICE_NODE_STATUS,
GET_SERVICE_PRIVKEYS,
GET_SN_STATE_CHANGES,
GET_STAKING_REQUIREMENT,
GET_TRANSACTIONS,
GET_TRANSACTION_POOL,
GET_TRANSACTION_POOL_HASHES,
GET_TRANSACTION_POOL_STATS,
GET_VERSION,
HARD_FORK_INFO,
IN_PEERS,
IS_KEY_IMAGE_SPENT,
LOKINET_PING,
MINING_STATUS,
ONS_OWNERS_TO_NAMES,
ONS_RESOLVE,
OUT_PEERS,
POP_BLOCKS,
PRUNE_BLOCKCHAIN,
REPORT_PEER_STATUS,
SAVE_BC,
SET_BANS,
SET_LIMIT,
SET_LOG_CATEGORIES,
SET_LOG_LEVEL,
START_MINING,
STOP_DAEMON,
STOP_MINING,
STORAGE_SERVER_PING,
SUBMIT_TRANSACTION,
SYNC_INFO,
TEST_TRIGGER_P2P_RESYNC,
TEST_TRIGGER_UPTIME_PROOF
>;
using FIXME_old_rpc_types = tools::type_list<
RELAY_TX,
GET_OUTPUT_DISTRIBUTION,
GET_SERVICE_NODE_REGISTRATION_CMD,
ONS_NAMES_TO_OWNERS
>;
} // namespace cryptonote::rpc