Skip to content

Commit

Permalink
Merge pull request #61 from nazar-pc/show-balance
Browse files Browse the repository at this point in the history
Show balance of the reward address and farmed coins since last start
  • Loading branch information
nazar-pc authored Dec 21, 2023
2 parents e141fd8 + 2730924 commit 1d6ccf1
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 65 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dirs = "5.0.1"
duct = "0.13.6"
event-listener-primitives = "2.0.1"
file-rotate = "0.7.5"
frame-system = { git = "https://github.com/subspace/polkadot-sdk", rev = "c63a8b28a9fd26d42116b0dcef1f2a5cefb9cd1c", default-features = false }
futures = "0.3.29"
gtk = { version = "0.7.3", package = "gtk4" }
hex = "0.4.3"
Expand All @@ -48,6 +49,8 @@ libp2p-identity-substate = { version = "0.1.3", package = "libp2p-identity" }
lru = "0.11.0"
mimalloc = "0.1.39"
names = "0.14.0"
pallet-balances = { git = "https://github.com/subspace/polkadot-sdk", rev = "c63a8b28a9fd26d42116b0dcef1f2a5cefb9cd1c", default-features = false }
parity-scale-codec = "3.6.9"
parking_lot = "0.12.1"
relm4 = { version = "0.7.0-beta.2", git = "https://github.com/Relm4/Relm4", rev = "f216c7f5ba1324413cb16e45c37e0b9297473ec2" }
relm4-icons = { version = "0.7.0-alpha.2", features = ["checkmark", "cross", "menu-large", "size-horizontally", "ssd", "wallet2"] }
Expand All @@ -74,6 +77,7 @@ subspace-networking = { git = "https://github.com/subspace/subspace", rev = "1b8
subspace-proof-of-space = { git = "https://github.com/subspace/subspace", rev = "1b8b5f310685a9cc0ef8192042257435ace285af" }
subspace-rpc-primitives = { git = "https://github.com/subspace/subspace", rev = "1b8b5f310685a9cc0ef8192042257435ace285af" }
subspace-runtime = { git = "https://github.com/subspace/subspace", rev = "1b8b5f310685a9cc0ef8192042257435ace285af" }
subspace-runtime-primitives = { git = "https://github.com/subspace/subspace", rev = "1b8b5f310685a9cc0ef8192042257435ace285af" }
subspace-service = { git = "https://github.com/subspace/subspace", rev = "1b8b5f310685a9cc0ef8192042257435ace285af" }
supports-color = "2.0.0"
thiserror = "1.0.50"
Expand Down
16 changes: 10 additions & 6 deletions src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::backend::farmer::maybe_node_client::MaybeNodeRpcClient;
use crate::backend::farmer::{DiskFarm, Farmer, FarmerOptions, PlottingState};
use crate::backend::networking::{create_network, NetworkOptions};
use crate::backend::node::{
dsn_bootstrap_nodes, ChainSpec, ConsensusNode, SyncState, GENESIS_HASH, RPC_PORT,
dsn_bootstrap_nodes, BlockImported, ChainSpec, ConsensusNode, SyncState, GENESIS_HASH, RPC_PORT,
};
use future::FutureExt;
use futures::channel::mpsc;
Expand All @@ -27,6 +27,7 @@ use subspace_farmer::utils::run_future_in_dedicated_thread;
use subspace_farmer::NodeRpcClient;
use subspace_networking::libp2p::identity::ed25519::{Keypair, SecretKey};
use subspace_networking::{Node, NodeRunner};
use subspace_runtime_primitives::Balance;
use tokio::fs;
use tokio::fs::OpenOptions;
use tokio::io::AsyncWriteExt;
Expand Down Expand Up @@ -64,7 +65,7 @@ pub enum LoadingStep {
#[derive(Debug, Clone)]
pub enum NodeNotification {
SyncStateUpdate(SyncState),
BlockImported { number: BlockNumber },
BlockImported(BlockImported),
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -101,6 +102,7 @@ pub enum BackendNotification {
config: Config,
raw_config: RawConfig,
best_block_number: BlockNumber,
reward_address_balance: Balance,
initial_plotting_states: Vec<PlottingState>,
},
Node(NodeNotification),
Expand Down Expand Up @@ -306,9 +308,10 @@ async fn run(

notifications_sender
.send(BackendNotification::Running {
config,
config: config.clone(),
raw_config,
best_block_number: consensus_node.best_block_number(),
reward_address_balance: consensus_node.account_balance(&config.reward_address),
initial_plotting_states: farmer.initial_plotting_states().to_vec(),
})
.await?;
Expand All @@ -335,9 +338,10 @@ async fn run(
});
let _on_imported_block_handler_id = consensus_node.on_block_imported({
let notifications_sender = notifications_sender.clone();
// let reward_address_storage_key = account_storage_key(&config.reward_address);

Arc::new(move |&number| {
let notification = NodeNotification::BlockImported { number };
Arc::new(move |&block_imported| {
let notification = NodeNotification::BlockImported(block_imported);

let mut notifications_sender = notifications_sender.clone();

Expand Down Expand Up @@ -398,7 +402,7 @@ async fn run(
});

let networking_fut = pin!(networking_fut);
let consensus_node_fut = pin!(consensus_node.run());
let consensus_node_fut = pin!(consensus_node.run(&config.reward_address));
let farmer_fut = pin!(farmer.run());
let process_backend_actions_fut = pin!({
let mut notifications_sender = notifications_sender.clone();
Expand Down
109 changes: 89 additions & 20 deletions src/backend/node.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
mod utils;

use crate::backend::node::utils::account_storage_key;
use crate::backend::utils::{Handler, HandlerFn};
use crate::PosTable;
use atomic::Atomic;
use event_listener_primitives::HandlerId;
use frame_system::AccountInfo;
use futures::{select, FutureExt, StreamExt};
use names::{Generator, Name};
use pallet_balances::AccountData;
use parity_scale_codec::Decode;
use sc_client_api::client::BlockchainEvents;
use sc_client_api::HeaderBackend;
use sc_client_api::{HeaderBackend, StorageProvider};
use sc_client_db::{DatabaseSource, PruningMode};
use sc_consensus_slots::SlotProportion;
use sc_informant::OutputFormat;
Expand All @@ -15,20 +21,24 @@ use sc_service::{BasePath, BlocksPruning, Configuration, Role, RpcMethods};
use sc_storage_monitor::{StorageMonitorParams, StorageMonitorService};
use sc_subspace_chain_specs::ConsensusChainSpec;
use sp_core::crypto::Ss58AddressFormat;
use sp_core::storage::StorageKey;
use sp_core::H256;
use sp_runtime::traits::Header;
use std::fmt;
use std::path::Path;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::Duration;
use subspace_core_primitives::BlockNumber;
use subspace_core_primitives::{BlockNumber, PublicKey};
use subspace_networking::libp2p::identity::ed25519::Keypair;
use subspace_networking::libp2p::Multiaddr;
use subspace_networking::Node;
use subspace_runtime::{ExecutorDispatch, RuntimeApi, RuntimeGenesisConfig};
use subspace_runtime_primitives::{Balance, Nonce};
use subspace_service::{FullClient, NewFull, SubspaceConfiguration, SubspaceNetworking};
use tokio::runtime::Handle;
use tokio::time::MissedTickBehavior;
use tracing::error;

pub(super) const GENESIS_HASH: &str =
"418040fc282f5e5ddd432c46d05297636f6f75ce68d66499ff4cbda69ccd180b";
Expand Down Expand Up @@ -65,10 +75,16 @@ pub enum SyncState {
Idle,
}

#[derive(Debug, Copy, Clone)]
pub struct BlockImported {
pub number: BlockNumber,
pub reward_address_balance: Balance,
}

#[derive(Default, Debug)]
struct Handlers {
sync_state_change: Handler<SyncState>,
block_imported: Handler<BlockNumber>,
block_imported: Handler<BlockImported>,
}

pub(super) struct ConsensusNode {
Expand All @@ -95,22 +111,38 @@ impl ConsensusNode {
}
}

pub(super) async fn run(mut self) -> Result<(), sc_service::Error> {
pub(super) async fn run(mut self, reward_address: &PublicKey) -> Result<(), sc_service::Error> {
self.full_node.network_starter.start_network();

let task_manager = self.full_node.task_manager.future();
let block_import_notifications_fut = async {
let mut block_import_stream = self.full_node.client.every_import_notification_stream();

while let Some(block_import) = block_import_stream.next().await {
// Nothing else to do
if block_import.is_new_best {
self.handlers
.block_imported
.call_simple(block_import.header.number());
let spawn_essential_handle = self.full_node.task_manager.spawn_essential_handle();
spawn_essential_handle.spawn_blocking(
"block-import-notifications",
Some("space-acres-node"),
{
let client = self.full_node.client.clone();
let reward_address_storage_key = account_storage_key(reward_address);

async move {
let mut block_import_stream = client.every_import_notification_stream();

while let Some(block_import) = block_import_stream.next().await {
if block_import.is_new_best {
self.handlers.block_imported.call_simple(&BlockImported {
number: *block_import.header.number(),
// TODO: This is not pretty that we do it here, but not clear what would be a
// nicer API
reward_address_balance: get_total_account_balance(
&client,
block_import.header.hash(),
&reward_address_storage_key,
)
.unwrap_or_default(),
});
}
}
}
}
};
},
);
let sync_status_notifications_fut = async {
let mut sync_status_interval = tokio::time::interval(SYNC_STATUS_EVENT_INTERVAL);
sync_status_interval.set_missed_tick_behavior(MissedTickBehavior::Skip);
Expand Down Expand Up @@ -152,13 +184,12 @@ impl ConsensusNode {
}
};

let task_manager = self.full_node.task_manager.future();

select! {
result = task_manager.fuse() => {
result?;
}
_ = block_import_notifications_fut.fuse() => {
// Nothing else to do
}
_ = sync_status_notifications_fut.fuse() => {
// Nothing else to do
}
Expand All @@ -171,15 +202,53 @@ impl ConsensusNode {
self.full_node.client.info().best_number
}

pub(super) fn account_balance(&self, account: &PublicKey) -> Balance {
let reward_address_storage_key = account_storage_key(account);

get_total_account_balance(
&self.full_node.client,
self.full_node.client.info().best_hash,
&reward_address_storage_key,
)
.unwrap_or_default()
}

pub(super) fn on_sync_state_change(&self, callback: HandlerFn<SyncState>) -> HandlerId {
self.handlers.sync_state_change.add(callback)
}

pub(super) fn on_block_imported(&self, callback: HandlerFn<BlockNumber>) -> HandlerId {
pub(super) fn on_block_imported(&self, callback: HandlerFn<BlockImported>) -> HandlerId {
self.handlers.block_imported.add(callback)
}
}

fn get_total_account_balance(
client: &FullClient<RuntimeApi, ExecutorDispatch>,
block_hash: H256,
address_storage_key: &StorageKey,
) -> Option<Balance> {
let encoded_account_info = match client.storage(block_hash, address_storage_key) {
Ok(maybe_encoded_account_info) => maybe_encoded_account_info?,
Err(error) => {
error!(%error, "Failed to query account balance");
return None;
}
};

let account_info = match AccountInfo::<Nonce, AccountData<Balance>>::decode(
&mut encoded_account_info.0.as_slice(),
) {
Ok(account_info) => account_info,
Err(error) => {
error!(%error, "Failed to decode account info");
return None;
}
};

let account_data = account_info.data;
Some(account_data.free + account_data.reserved + account_data.frozen)
}

pub(super) fn load_chain_specification(chain_spec: &'static [u8]) -> Result<ChainSpec, String> {
ConsensusChainSpec::from_json_bytes(chain_spec).map(ChainSpec)
}
Expand Down
15 changes: 15 additions & 0 deletions src/backend/node/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use sp_core::storage::StorageKey;
use sp_core::{blake2_128, twox_128};
use subspace_core_primitives::PublicKey;

pub(super) fn account_storage_key(public_key: &PublicKey) -> StorageKey {
let mut storage_key = Vec::new();

storage_key.extend_from_slice(&twox_128(b"System"));
storage_key.extend_from_slice(&twox_128(b"Account"));
// Next two lines are "blake2_128_concat"
storage_key.extend_from_slice(&blake2_128(public_key.as_ref()));
storage_key.extend_from_slice(public_key.as_ref());

StorageKey(storage_key)
}
Loading

0 comments on commit 1d6ccf1

Please sign in to comment.