mirror of https://github.com/oxen-io/oxen-core.git
Adds RPC endpoint for accrued batching balances
This allows a user to query the daemon and ask for the accrued balance of oxen rewards that have been batched but not yet paid out. The endpoint takes in an array of addresses (Strings) and returns an array of atomic oxen amounts (integers) that reflect the current database balances for those requested addresses. For example an address has accrued 2x batch payments of 16.5 oxen but has not yet been paid out will show 33000000000 being the atomic amount in the database.
This commit is contained in:
parent
3ac7e55056
commit
f45d0588ae
|
@ -224,6 +224,41 @@ namespace cryptonote {
|
|||
return payments;
|
||||
}
|
||||
|
||||
uint64_t BlockchainSQLite::get_accrued_earnings(const std::string& address) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
SQLite::Statement select_earnings {
|
||||
db,
|
||||
"SELECT amount FROM batched_payments_accrued WHERE address = ?;"
|
||||
};
|
||||
select_earnings.bind(1, address);
|
||||
|
||||
uint64_t amount{};
|
||||
while (select_earnings.executeStep()) {
|
||||
amount = static_cast<uint64_t>(select_earnings.getColumn(0).getInt64() / 1000);
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::string>, std::vector<uint64_t>> BlockchainSQLite::get_all_accrued_earnings() {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
SQLite::Statement select_earnings {
|
||||
db,
|
||||
"SELECT address, amount FROM batched_payments_accrued;"
|
||||
};
|
||||
|
||||
std::vector<uint64_t> amounts;
|
||||
std::vector<std::string> addresses;
|
||||
while (select_earnings.executeStep()) {
|
||||
addresses.emplace_back(select_earnings.getColumn(0).getString());
|
||||
amounts.emplace_back(static_cast<uint64_t>(select_earnings.getColumn(1).getInt64() / 1000));
|
||||
}
|
||||
|
||||
return std::make_pair(addresses, amounts);
|
||||
}
|
||||
|
||||
std::vector<cryptonote::batch_sn_payment> BlockchainSQLite::calculate_rewards(uint8_t hf_version, uint64_t distribution_amount, service_nodes::service_node_info sn_info) {
|
||||
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
|
||||
|
||||
|
|
|
@ -66,6 +66,13 @@ public:
|
|||
// get_payments -> passing a block height will return an array of payments that should be created in a coinbase transaction on that block given the current batching DB state.
|
||||
std::optional<std::vector<cryptonote::batch_sn_payment>> get_sn_payments(uint64_t block_height);
|
||||
|
||||
// get_accrued_earnings -> queries the database for the amount that has been accrued to `service_node_address` will return the atomic value in oxen that
|
||||
// the service node is owed.
|
||||
uint64_t get_accrued_earnings(const std::string& address);
|
||||
// get_all_accrued_earnings -> queries the database for all the amount that has been accrued to service nodes will return
|
||||
// 2 vectors corresponding to the addresses and the atomic value in oxen that the service nodes are owed.
|
||||
std::pair<std::vector<std::string>, std::vector<uint64_t>> get_all_accrued_earnings();
|
||||
|
||||
// calculate_rewards -> takes the list of contributors from sn_info with their SN contribution amounts and will calculate how much of the block rewards should be the allocated to the contributors. The function will return a list suitable for passing to add_sn_payments
|
||||
std::vector<cryptonote::batch_sn_payment> calculate_rewards(uint8_t hf_version, uint64_t distribution_amount, service_nodes::service_node_info sn_info);
|
||||
|
||||
|
|
|
@ -2774,6 +2774,44 @@ namespace cryptonote { namespace rpc {
|
|||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
GET_ACCRUED_BATCHED_EARNINGS::response core_rpc_server::invoke(GET_ACCRUED_BATCHED_EARNINGS::request&& req, rpc_context context)
|
||||
{
|
||||
GET_ACCRUED_BATCHED_EARNINGS::response res{};
|
||||
|
||||
PERF_TIMER(on_get_accrued_batched_earnings);
|
||||
|
||||
auto& blockchain = m_core.get_blockchain_storage();
|
||||
bool at_least_one_succeeded = false;
|
||||
|
||||
if (req.addresses.size() > 0)
|
||||
{
|
||||
for (const auto& address : req.addresses)
|
||||
{
|
||||
res.addresses.emplace_back(address);
|
||||
if (cryptonote::is_valid_address(address, nettype()))
|
||||
{
|
||||
uint64_t amount = blockchain.sqlite_db()->get_accrued_earnings(address);
|
||||
res.amounts.emplace_back(amount);
|
||||
at_least_one_succeeded = true;
|
||||
} else {
|
||||
res.amounts.emplace_back(0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto [addresses, amounts] = blockchain.sqlite_db()->get_all_accrued_earnings();
|
||||
res.addresses = std::move(addresses);
|
||||
res.amounts = std::move(amounts);
|
||||
at_least_one_succeeded = true;
|
||||
}
|
||||
|
||||
if (!at_least_one_succeeded)
|
||||
throw rpc_error{ERROR_WRONG_PARAM, "Failed to query any service nodes batched amounts at all"};
|
||||
|
||||
res.status = STATUS_OK;
|
||||
return res;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
GET_QUORUM_STATE::response core_rpc_server::invoke(GET_QUORUM_STATE::request&& req, rpc_context context)
|
||||
{
|
||||
GET_QUORUM_STATE::response res{};
|
||||
|
|
|
@ -248,6 +248,7 @@ namespace cryptonote::rpc {
|
|||
PRUNE_BLOCKCHAIN::response invoke(PRUNE_BLOCKCHAIN::request&& req, rpc_context context);
|
||||
GET_OUTPUT_BLACKLIST::response invoke(GET_OUTPUT_BLACKLIST::request&& req, rpc_context context);
|
||||
GET_QUORUM_STATE::response invoke(GET_QUORUM_STATE::request&& req, rpc_context context);
|
||||
GET_ACCRUED_BATCHED_EARNINGS::response invoke(GET_ACCRUED_BATCHED_EARNINGS::request&& req, rpc_context context);
|
||||
GET_SERVICE_NODE_REGISTRATION_CMD_RAW::response invoke(GET_SERVICE_NODE_REGISTRATION_CMD_RAW::request&& req, rpc_context context);
|
||||
GET_SERVICE_NODE_REGISTRATION_CMD::response invoke(GET_SERVICE_NODE_REGISTRATION_CMD::request&& req, rpc_context context);
|
||||
GET_SERVICE_NODE_BLACKLISTED_KEY_IMAGES::response invoke(GET_SERVICE_NODE_BLACKLISTED_KEY_IMAGES::request&& req, rpc_context context);
|
||||
|
|
|
@ -92,6 +92,15 @@ KV_SERIALIZE_MAP_CODE_BEGIN(GET_TRANSACTIONS::request)
|
|||
KV_SERIALIZE(stake_info)
|
||||
KV_SERIALIZE_MAP_CODE_END()
|
||||
|
||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_ACCRUED_BATCHED_EARNINGS::request)
|
||||
KV_SERIALIZE(addresses)
|
||||
KV_SERIALIZE_MAP_CODE_END()
|
||||
|
||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_ACCRUED_BATCHED_EARNINGS::response)
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(addresses)
|
||||
KV_SERIALIZE(amounts)
|
||||
KV_SERIALIZE_MAP_CODE_END()
|
||||
|
||||
KV_SERIALIZE_MAP_CODE_BEGIN(GET_TRANSACTIONS::extra_entry::sn_reg_info::contribution)
|
||||
KV_SERIALIZE(wallet)
|
||||
|
|
|
@ -1964,6 +1964,29 @@ namespace rpc {
|
|||
};
|
||||
};
|
||||
|
||||
OXEN_RPC_DOC_INTROSPECT
|
||||
// Accesses the amounts accrued to addresses in the batching database
|
||||
struct GET_ACCRUED_BATCHED_EARNINGS: PUBLIC
|
||||
{
|
||||
static constexpr auto names() { return NAMES("get_accrued_batched_earnings"); }
|
||||
|
||||
struct request
|
||||
{
|
||||
std::vector<std::string> addresses; // Array of addresses to query the batching database about.
|
||||
|
||||
KV_MAP_SERIALIZABLE
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status; // Generic RPC error code. "OK" is the success value.
|
||||
std::vector<std::string> addresses; // Array of addresses to query the batching database about.
|
||||
std::vector<uint64_t> amounts; // An array of amounts according to the provided addressses
|
||||
|
||||
KV_MAP_SERIALIZABLE
|
||||
};
|
||||
};
|
||||
|
||||
OXEN_RPC_DOC_INTROSPECT
|
||||
// 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
|
||||
|
@ -2658,7 +2681,8 @@ namespace rpc {
|
|||
ONS_NAMES_TO_OWNERS,
|
||||
ONS_OWNERS_TO_NAMES,
|
||||
ONS_RESOLVE,
|
||||
FLUSH_CACHE
|
||||
FLUSH_CACHE,
|
||||
GET_ACCRUED_BATCHED_EARNINGS
|
||||
>;
|
||||
|
||||
} } // namespace cryptonote::rpc
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
sys.path.append('../testdata')
|
||||
import config
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
|
||||
def instruct_daemon(method, params):
|
||||
payload = json.dumps({"method": method, "params": params}, skipkeys=False)
|
||||
print(payload)
|
||||
headers = {'content-type': "application/json"}
|
||||
try:
|
||||
response = requests.request("POST", "http://"+config.listen_ip+":"+config.listen_port+"/json_rpc", data=payload, headers=headers)
|
||||
return json.loads(response.text)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(e)
|
||||
except:
|
||||
print('No response from daemon, check daemon is running on this machine')
|
||||
|
||||
# answer = instruct_daemon('get_accrued_batched_earnings', {"addresses": [config.wallet_address]})
|
||||
answer = instruct_daemon('get_accrued_batched_earnings', {"addresses": []})
|
||||
print(json.dumps(answer, indent=4, sort_keys=True))
|
||||
|
||||
|
Loading…
Reference in New Issue