Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Json rpc/non sensitive stakes ranks utxos #2570

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion data_structures/src/capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use serde::{Deserialize, Serialize};

#[repr(u8)]
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Capability {
/// The base block mining and superblock voting capability
#[default]
Mining = 0,
/// The universal HTTP GET / HTTP POST / WIP-0019 RNG capability
Witnessing = 1,
Expand Down
26 changes: 19 additions & 7 deletions node/src/actors/chain_manager/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ use crate::{
GetDataRequestInfo, GetHighestCheckpointBeacon, GetMemoryTransaction, GetMempool,
GetMempoolResult, GetNodeStats, GetProtocolInfo, GetReputation, GetReputationResult,
GetSignalingInfo, GetState, GetSuperBlockVotes, GetSupplyInfo, GetUtxoInfo,
IsConfirmedBlock, PeersBeacons, QueryStake, ReputationStats, Rewind, SendLastBeacon,
SendProtocolVersions, SessionUnitResult, SetEpochConstants, SetLastBeacon,
SetPeersLimits, SignalingInfo, SnapshotExport, SnapshotImport, TryMineBlock,
IsConfirmedBlock, PeersBeacons, QueryStakePowers, QueryStakes, ReputationStats, Rewind,
SendLastBeacon, SendProtocolVersions, SessionUnitResult, SetEpochConstants,
SetLastBeacon, SetPeersLimits, SignalingInfo, SnapshotExport, SnapshotImport,
TryMineBlock,
},
sessions_manager::SessionsManager,
},
Expand Down Expand Up @@ -1453,17 +1454,28 @@ impl Handler<BuildUnstake> for ChainManager {
}
}

impl Handler<QueryStake> for ChainManager {
type Result = <QueryStake as Message>::Result;
impl Handler<QueryStakes> for ChainManager {
type Result = <QueryStakes as Message>::Result;

fn handle(&mut self, msg: QueryStake, _ctx: &mut Self::Context) -> Self::Result {
fn handle(&mut self, msg: QueryStakes, _ctx: &mut Self::Context) -> Self::Result {
// build address from public key hash
let stakes = self.chain_state.stakes.query_stakes(msg.key);
let stakes = self.chain_state.stakes.query_stakes(msg.filter);

stakes.map_err(StakesError::from).map_err(Into::into)
}
}

impl Handler<QueryStakePowers> for ChainManager {
type Result = <QueryStakePowers as Message>::Result;

fn handle(&mut self, msg: QueryStakePowers, _ctx: &mut Self::Context) -> Self::Result {
self.chain_state
.stakes
.by_rank(msg.capability, self.current_epoch.unwrap())
.collect()
}
}

impl Handler<BuildDrt> for ChainManager {
type Result = ResponseActFuture<Self, Result<DRTransaction, failure::Error>>;

Expand Down
76 changes: 57 additions & 19 deletions node/src/actors/json_rpc/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ use crate::{
GetHighestCheckpointBeacon, GetItemBlock, GetItemSuperblock, GetItemTransaction,
GetKnownPeers, GetMemoryTransaction, GetMempool, GetNodeStats, GetProtocolInfo,
GetReputation, GetSignalingInfo, GetState, GetSupplyInfo, GetUtxoInfo, InitializePeers,
IsConfirmedBlock, QueryStake, QueryStakesParams, Rewind, SnapshotExport,
SnapshotImport, StakeAuthorization,
IsConfirmedBlock, QueryStakePowers, QueryStakes, QueryStakesFilter, Rewind,
SnapshotExport, SnapshotImport, StakeAuthorization,
},
peers_manager::PeersManager,
sessions_manager::SessionsManager,
Expand Down Expand Up @@ -145,6 +145,12 @@ pub fn attach_regular_methods<H>(
server.add_actix_method(system, "queryStakes", |params: Params| {
Box::pin(query_stakes(params.parse()))
});
server.add_actix_method(system, "ranks", |params: Params| {
Box::pin(query_ranks(params.parse()))
});
server.add_actix_method(system, "getUtxoInfo", move |params: Params| {
Box::pin(get_utxo_info(params.parse()))
});
}

/// Attach the sensitive JSON-RPC methods to a multi-transport server.
Expand Down Expand Up @@ -195,14 +201,6 @@ pub fn attach_sensitive_methods<H>(
|_params| get_pkh(),
))
});
server.add_actix_method(system, "getUtxoInfo", move |params| {
Box::pin(if_authorized(
enable_sensitive_methods,
"getUtxoInfo",
params,
|params| get_utxo_info(params.parse()),
))
});
server.add_actix_method(system, "sign", move |params| {
Box::pin(if_authorized(
enable_sensitive_methods,
Expand Down Expand Up @@ -2184,7 +2182,7 @@ pub async fn authorize_stake(params: Result<AuthorizeStake, Error>) -> JsonRpcRe
/// Param for query_stakes
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum QueryStakesArgument {
pub enum QueryStakesParams {
/// To query by stake validator
Validator(String),
/// To query by stake withdrawer
Expand All @@ -2196,22 +2194,22 @@ pub enum QueryStakesArgument {
}

/// Query the amount of nanowits staked by an address.
pub async fn query_stakes(params: Result<Option<QueryStakesArgument>, Error>) -> JsonRpcResult {
pub async fn query_stakes(params: Result<Option<QueryStakesParams>, Error>) -> JsonRpcResult {
// Short-circuit if parameters are wrong
let params = params?;
// If a withdrawer address is not specified, default to local node address
let key: QueryStakesParams = if let Some(address) = params {
let filter: QueryStakesFilter = if let Some(address) = params {
match address {
QueryStakesArgument::All(_) => QueryStakesParams::All,
QueryStakesArgument::Validator(validator) => QueryStakesParams::Validator(
QueryStakesParams::All(_) => QueryStakesFilter::All,
QueryStakesParams::Validator(validator) => QueryStakesFilter::Validator(
PublicKeyHash::from_bech32(get_environment(), &validator)
.map_err(internal_error)?,
),
QueryStakesArgument::Withdrawer(withdrawer) => QueryStakesParams::Withdrawer(
QueryStakesParams::Withdrawer(withdrawer) => QueryStakesFilter::Withdrawer(
PublicKeyHash::from_bech32(get_environment(), &withdrawer)
.map_err(internal_error)?,
),
QueryStakesArgument::Key((validator, withdrawer)) => QueryStakesParams::Key((
QueryStakesParams::Key((validator, withdrawer)) => QueryStakesFilter::Key((
PublicKeyHash::from_bech32(get_environment(), &validator)
.map_err(internal_error)?,
PublicKeyHash::from_bech32(get_environment(), &withdrawer)
Expand All @@ -2221,10 +2219,10 @@ pub async fn query_stakes(params: Result<Option<QueryStakesArgument>, Error>) ->
} else {
let pk = signature_mngr::public_key().await.map_err(internal_error)?;

QueryStakesParams::Validator(PublicKeyHash::from_public_key(&pk))
QueryStakesFilter::Validator(PublicKeyHash::from_public_key(&pk))
};
ChainManager::from_registry()
.send(QueryStake { key })
.send(QueryStakes { filter })
.map(|res| match res {
Ok(Ok(stakes)) => serde_json::to_value(stakes).map_err(internal_error),
Ok(Err(e)) => {
Expand All @@ -2239,6 +2237,46 @@ pub async fn query_stakes(params: Result<Option<QueryStakesArgument>, Error>) ->
.await
}

/// Format of the output of getTransaction
#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct QueryRanksRecord {
/// Current power
pub power: u64,
/// Validator's stringified pkh
pub validator: String,
/// Withdrawer's stringified pkh
pub withdrawer: String,
}

/// Query the amount of nanowits staked by an address.
pub async fn query_ranks(params: Result<(Capability,), Error>) -> JsonRpcResult {
let capability = match params {
Ok(x) => x.0,
Err(_) => Capability::Mining,
};
ChainManager::from_registry()
.send(QueryStakePowers { capability })
.map(|res| match res {
Ok(candidates) => {
let candidates: Vec<QueryRanksRecord> = candidates
.iter()
.map(|(key, power)| QueryRanksRecord {
power: *power,
validator: key.validator.to_string(),
withdrawer: key.withdrawer.to_string(),
})
.collect();
let candidates = serde_json::to_value(candidates);
candidates.map_err(internal_error)
}
Err(e) => {
let err = internal_error_s(e);
Err(err)
}
})
.await
}

#[cfg(test)]
mod mock_actix {
use actix::{MailboxError, Message};
Expand Down
35 changes: 23 additions & 12 deletions node/src/actors/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,20 @@ impl Message for StakeAuthorization {
type Result = Result<String, failure::Error>;
}

/// Message for querying stakes
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct QueryStakePowers {
/// capability being searched for
pub capability: Capability,
}

impl Message for QueryStakePowers {
type Result = Vec<(StakeKey<PublicKeyHash>, Power)>;
}

/// Stake key for quering stakes
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum QueryStakesParams {
pub enum QueryStakesFilter {
/// To search by the validator public key hash
Validator(PublicKeyHash),
/// To search by the withdrawer public key hash
Expand All @@ -357,39 +368,39 @@ pub enum QueryStakesParams {
All,
}

impl Default for QueryStakesParams {
impl Default for QueryStakesFilter {
fn default() -> Self {
QueryStakesParams::Validator(PublicKeyHash::default())
QueryStakesFilter::Validator(PublicKeyHash::default())
}
}

/// Message for querying stakes
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct QueryStake {
pub struct QueryStakes {
/// stake key used to search the stake
pub key: QueryStakesParams,
pub filter: QueryStakesFilter,
}

impl Message for QueryStake {
impl Message for QueryStakes {
type Result = Result<
Vec<StakeEntry<WIT_DECIMAL_PLACES, PublicKeyHash, Wit, Epoch, u64, u64>>,
failure::Error,
>;
}

impl<Address> From<QueryStakesParams> for QueryStakesKey<Address>
impl<Address> From<QueryStakesFilter> for QueryStakesKey<Address>
where
Address: Default + Ord + From<PublicKeyHash>,
{
fn from(query: QueryStakesParams) -> Self {
fn from(query: QueryStakesFilter) -> Self {
match query {
QueryStakesParams::Key(key) => QueryStakesKey::Key(StakeKey {
QueryStakesFilter::Key(key) => QueryStakesKey::Key(StakeKey {
validator: key.0.into(),
withdrawer: key.1.into(),
}),
QueryStakesParams::Validator(v) => QueryStakesKey::Validator(v.into()),
QueryStakesParams::Withdrawer(w) => QueryStakesKey::Withdrawer(w.into()),
QueryStakesParams::All => QueryStakesKey::All,
QueryStakesFilter::Validator(v) => QueryStakesKey::Validator(v.into()),
QueryStakesFilter::Withdrawer(w) => QueryStakesKey::Withdrawer(w.into()),
QueryStakesFilter::All => QueryStakesKey::All,
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/cli/node/json_rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use witnet_data_structures::{
use witnet_node::actors::{
chain_manager::run_dr_locally,
json_rpc::api::{
AddrType, GetBlockChainParams, GetTransactionOutput, PeersResult, QueryStakesArgument,
AddrType, GetBlockChainParams, GetTransactionOutput, PeersResult, QueryStakesParams,
},
messages::{
AuthorizeStake, BuildDrt, BuildStakeParams, BuildStakeResponse, BuildUnstakeParams,
Expand Down Expand Up @@ -1936,14 +1936,14 @@ pub fn query_stakes(
) -> Result<(), failure::Error> {
let mut stream = start_client(addr)?;
let params = if all {
Some(QueryStakesArgument::All(true))
Some(QueryStakesParams::All(true))
} else {
match (validator, withdrawer) {
(Some(validator), Some(withdrawer)) => {
Some(QueryStakesArgument::Key((validator, withdrawer)))
Some(QueryStakesParams::Key((validator, withdrawer)))
}
(Some(validator), _) => Some(QueryStakesArgument::Validator(validator)),
(_, Some(withdrawer)) => Some(QueryStakesArgument::Withdrawer(withdrawer)),
(Some(validator), _) => Some(QueryStakesParams::Validator(validator)),
(_, Some(withdrawer)) => Some(QueryStakesParams::Withdrawer(withdrawer)),
(None, None) => None,
}
};
Expand Down
Loading