Skip to content

Commit

Permalink
feat: jsonrpc add stake
Browse files Browse the repository at this point in the history
  • Loading branch information
Tommytrg committed Nov 21, 2023
1 parent a9b660b commit 05b9b3f
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 14 deletions.
86 changes: 77 additions & 9 deletions node/src/actors/chain_manager/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ use std::{
use actix::{prelude::*, ActorFutureExt, WrapFuture};
use futures::future::Either;

use witnet_config::defaults::PSEUDO_CONSENSUS_CONSTANTS_WIP0027_COLLATERAL_AGE;
use witnet_config::defaults::{
PSEUDO_CONSENSUS_CONSTANTS_POS_MAX_STAKE_BLOCK_WEIGHT,
PSEUDO_CONSENSUS_CONSTANTS_WIP0027_COLLATERAL_AGE,
};
use witnet_data_structures::{
chain::{
tapi::ActiveWips, Block, ChainState, CheckpointBeacon, DataRequestInfo, Epoch, Hash,
Hashable, NodeStats, PublicKeyHash, SuperBlockVote, SupplyInfo,
},
error::{ChainInfoError, TransactionError::DataRequestNotFound},
transaction::{DRTransaction, Transaction, VTTransaction},
transaction::{DRTransaction, StakeTransaction, Transaction, VTTransaction},
transaction_factory::{self, NodeBalance},
types::LastBeacon,
utxo_pool::{get_utxo_info, UtxoInfo},
Expand All @@ -29,13 +32,14 @@ use crate::{
chain_manager::{handlers::BlockBatches::*, BlockCandidate},
messages::{
AddBlocks, AddCandidates, AddCommitReveal, AddSuperBlock, AddSuperBlockVote,
AddTransaction, Broadcast, BuildDrt, BuildVtt, EpochNotification, EstimatePriority,
GetBalance, GetBalanceTarget, GetBlocksEpochRange, GetDataRequestInfo,
GetHighestCheckpointBeacon, GetMemoryTransaction, GetMempool, GetMempoolResult,
GetNodeStats, GetReputation, GetReputationResult, GetSignalingInfo, GetState,
GetSuperBlockVotes, GetSupplyInfo, GetUtxoInfo, IsConfirmedBlock, PeersBeacons,
ReputationStats, Rewind, SendLastBeacon, SessionUnitResult, SetLastBeacon,
SetPeersLimits, SignalingInfo, SnapshotExport, SnapshotImport, TryMineBlock,
AddTransaction, Broadcast, BuildDrt, BuildStake, BuildVtt, EpochNotification,
EstimatePriority, GetBalance, GetBalanceTarget, GetBlocksEpochRange,
GetDataRequestInfo, GetHighestCheckpointBeacon, GetMemoryTransaction, GetMempool,
GetMempoolResult, GetNodeStats, GetReputation, GetReputationResult, GetSignalingInfo,
GetState, GetSuperBlockVotes, GetSupplyInfo, GetUtxoInfo, IsConfirmedBlock,
PeersBeacons, ReputationStats, Rewind, SendLastBeacon, SessionUnitResult,
SetLastBeacon, SetPeersLimits, SignalingInfo, SnapshotExport, SnapshotImport,
TryMineBlock,
},
sessions_manager::SessionsManager,
},
Expand Down Expand Up @@ -1288,6 +1292,70 @@ impl Handler<BuildVtt> for ChainManager {
}
}

impl Handler<BuildStake> for ChainManager {
type Result = ResponseActFuture<Self, <BuildStake as Message>::Result>;

fn handle(&mut self, msg: BuildStake, _ctx: &mut Self::Context) -> Self::Result {
if self.sm_state != StateMachine::Synced {
return Box::pin(actix::fut::err(
ChainManagerError::NotSynced {
current_state: self.sm_state,
}
.into(),
));
}
let timestamp = u64::try_from(get_timestamp()).unwrap();
match transaction_factory::build_st(
msg.stake_output,
msg.fee,
&mut self.chain_state.own_utxos,
self.own_pkh.unwrap(),
&self.chain_state.unspent_outputs_pool,
timestamp,
self.tx_pending_timeout,
&msg.utxo_strategy,
PSEUDO_CONSENSUS_CONSTANTS_POS_MAX_STAKE_BLOCK_WEIGHT,
msg.dry_run,
) {
Err(e) => {
log::error!("Error when building stake transaction: {}", e);
Box::pin(actix::fut::err(e.into()))
}
Ok(st) => {
let fut = signature_mngr::sign_transaction(&st, st.inputs.len())
.into_actor(self)
.then(move |s, act, _ctx| match s {
Ok(signatures) => {
let st = StakeTransaction::new(st, signatures);

if msg.dry_run {
Either::Right(actix::fut::result(Ok(st)))
} else {
let transaction = Transaction::Stake(st.clone());
Either::Left(
act.add_transaction(
AddTransaction {
transaction,
broadcast_flag: true,
},
get_timestamp(),
)
.map_ok(move |_, _, _| st),
)
}
}
Err(e) => {
log::error!("Failed to sign stake transaction: {}", e);
Either::Right(actix::fut::result(Err(e)))
}
});

Box::pin(fut)
}
}
}
}

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

Expand Down
42 changes: 40 additions & 2 deletions node/src/actors/json_rpc/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ use crate::{
inventory_manager::{InventoryManager, InventoryManagerError},
json_rpc::Subscriptions,
messages::{
AddCandidates, AddPeers, AddTransaction, BuildDrt, BuildVtt, ClearPeers, DropAllPeers,
EstimatePriority, GetBalance, GetBalanceTarget, GetBlocksEpochRange,
AddCandidates, AddPeers, AddTransaction, BuildDrt, BuildStake, BuildVtt, ClearPeers,
DropAllPeers, EstimatePriority, GetBalance, GetBalanceTarget, GetBlocksEpochRange,
GetConsolidatedPeers, GetDataRequestInfo, GetEpoch, GetHighestCheckpointBeacon,
GetItemBlock, GetItemSuperblock, GetItemTransaction, GetKnownPeers,
GetMemoryTransaction, GetMempool, GetNodeStats, GetReputation, GetSignalingInfo,
Expand Down Expand Up @@ -266,6 +266,14 @@ pub fn attach_sensitive_methods<H>(
|params| snapshot_import(params.parse()),
))
});
server.add_actix_method(system, "stake", move |params| {
Box::pin(if_authorized(
enable_sensitive_methods,
"stake",
params,
|params| stake(params.parse()),
))
});
}

fn extract_topic_and_params(params: Params) -> Result<(String, Value), Error> {
Expand Down Expand Up @@ -1921,6 +1929,36 @@ pub async fn snapshot_import(params: Result<SnapshotImportParams, Error>) -> Jso
// Write the response back (the path to the snapshot file)
serde_json::to_value(response).map_err(internal_error_s)
}
/// Build a stake transaction
pub async fn stake(params: Result<BuildStake, Error>) -> JsonRpcResult {
log::debug!("Creating stake transaction from JSON-RPC.");

match params {
Ok(msg) => {
ChainManager::from_registry()
.send(msg)
.map(|res| match res {
Ok(Ok(hash)) => match serde_json::to_value(hash) {
Ok(x) => Ok(x),
Err(e) => {
let err = internal_error_s(e);
Err(err)
}
},
Ok(Err(e)) => {
let err = internal_error_s(e);
Err(err)
}
Err(e) => {
let err = internal_error_s(e);
Err(err)
}
})
.await
}
Err(err) => Err(err),
}
}

#[cfg(test)]
mod mock_actix {
Expand Down
27 changes: 24 additions & 3 deletions node/src/actors/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ use witnet_data_structures::{
tapi::{ActiveWips, BitVotesCounter},
Block, CheckpointBeacon, DataRequestInfo, DataRequestOutput, Epoch, EpochConstants, Hash,
InventoryEntry, InventoryItem, NodeStats, PointerToBlock, PublicKeyHash,
PublicKeyHashParseError, RADRequest, RADTally, Reputation, StateMachine, SuperBlock,
SuperBlockVote, SupplyInfo, ValueTransferOutput,
PublicKeyHashParseError, RADRequest, RADTally, Reputation, StakeOutput, StateMachine,
SuperBlock, SuperBlockVote, SupplyInfo, ValueTransferOutput,
},
fee::{deserialize_fee_backwards_compatible, Fee},
radon_report::RadonReport,
transaction::{
CommitTransaction, DRTransaction, RevealTransaction, Transaction, VTTransaction,
CommitTransaction, DRTransaction, RevealTransaction, StakeTransaction, Transaction,
VTTransaction,
},
transaction_factory::NodeBalance,
types::LastBeacon,
Expand Down Expand Up @@ -220,6 +221,26 @@ impl Message for BuildVtt {
type Result = Result<VTTransaction, failure::Error>;
}

/// Builds a `StakeTransaction` from a list of `ValueTransferOutput`s
#[derive(Clone, Debug, Default, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct BuildStake {
/// List of `ValueTransferOutput`s
pub stake_output: StakeOutput,
/// Fee
#[serde(default)]
pub fee: Fee,
/// Strategy to sort the unspent outputs pool
#[serde(default)]
pub utxo_strategy: UtxoSelectionStrategy,
/// Construct the transaction but do not broadcast it
#[serde(default)]
pub dry_run: bool,
}

impl Message for BuildStake {
type Result = Result<StakeTransaction, failure::Error>;
}

/// Builds a `DataRequestTransaction` from a `DataRequestOutput`
#[derive(Clone, Debug, Default, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct BuildDrt {
Expand Down

0 comments on commit 05b9b3f

Please sign in to comment.