Skip to content

Commit

Permalink
feat(audit): collect payment forward statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
maqi committed May 13, 2024
1 parent dfa136d commit d01b121
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 22 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/memcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
run: |
mkdir -p $BOOTSTRAP_NODE_DATA_PATH
./target/release/safenode --first \
--root-dir $BOOTSTRAP_NODE_DATA_PATH --log-output-dest $BOOTSTRAP_NODE_DATA_PATH --local --owner=maidsafe_test &
--root-dir $BOOTSTRAP_NODE_DATA_PATH --log-output-dest $BOOTSTRAP_NODE_DATA_PATH --local --owner=bootstrap &
sleep 10
env:
SN_LOG: "all"
Expand All @@ -65,7 +65,7 @@ jobs:
run: |
mkdir -p $RESTART_TEST_NODE_DATA_PATH
./target/release/safenode \
--root-dir $RESTART_TEST_NODE_DATA_PATH --log-output-dest $RESTART_TEST_NODE_DATA_PATH --local --owner=maidsafe_test &
--root-dir $RESTART_TEST_NODE_DATA_PATH --log-output-dest $RESTART_TEST_NODE_DATA_PATH --local --owner=restart &
sleep 10
env:
SN_LOG: "all"
Expand Down Expand Up @@ -165,7 +165,7 @@ jobs:
- name: Start the restart node again
run: |
./target/release/safenode \
--root-dir $RESTART_TEST_NODE_DATA_PATH --log-output-dest $RESTART_TEST_NODE_DATA_PATH --local --owner=maidsafe_test &
--root-dir $RESTART_TEST_NODE_DATA_PATH --log-output-dest $RESTART_TEST_NODE_DATA_PATH --local --owner=restarted &
sleep 10
env:
SN_LOG: "all"
Expand Down
4 changes: 4 additions & 0 deletions sn_cli/src/bin/subcommands/wallet/audit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ pub async fn audit(client: &Client, to_dot: bool, royalties: bool, root_dir: &Pa
"======================= spends purpose statistics =========================="
);
println!("{}", dag.dump_creation_reasons_statistics());
println!(
"======================= payment forward statistics =========================="
);
println!("{}", dag.dump_payment_forward_statistics());
} else if royalties {
let dag = gather_spend_dag(client, root_dir).await?;
let royalties = dag.all_royalties()?;
Expand Down
24 changes: 24 additions & 0 deletions sn_client/src/audit/spend_dag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,30 @@ impl SpendDag {
content
}

pub fn dump_payment_forward_statistics(&self) -> String {
let mut statistics: BTreeMap<String, Vec<NanoTokens>> = Default::default();

for spend_dag_entry in self.spends.values() {
if let DagEntry::Spend(signed_spend, _) = spend_dag_entry {
if let Some(sender_hash) = signed_spend.spend.reason.get_sender_hash() {
let sender = format!("{sender_hash:?}");
let holders = statistics.entry(sender).or_default();
holders.push(signed_spend.spend.amount);
}
}
}

let mut content = "Sender, Times, Amount".to_string();
for (sender, payments) in statistics.iter() {
let total_amount: u64 = payments
.iter()
.map(|nano_tokens| nano_tokens.as_nano())
.sum();
content = format!("{content}\n{sender}, {}, {total_amount}", payments.len());
}
content
}

/// Merges the given dag into ours
pub fn merge(&mut self, sub_dag: SpendDag) -> Result<(), DagError> {
let source = self.source();
Expand Down
27 changes: 8 additions & 19 deletions sn_node_manager/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,26 +296,15 @@ pub async fn run_node(
launcher: &dyn Launcher,
rpc_client: &dyn RpcActions,
) -> Result<NodeServiceData> {
let user = match get_username() {
Ok(user_name) => {
println!("parsed env set user_name is {user_name:?}");
if user_name.is_empty() {
println!(
"Env set user_name is empty, using owner ({:?}) passed via cli.",
run_options.owner
);
run_options.owner.clone()
} else {
user_name
}
}
Err(_err) => {
println!(
"cannot parse user_name from env, using owner ({:?}) passed via cli.",
run_options.owner
);
run_options.owner.clone()
// We shall use the input or env parsed username,
// as long as they are not default ones for tests.
// Input user_name is prioritized than parsed env.
let user = match (get_username(), run_options.owner == *"maidsafe_test") {
(Ok(user), true) if user == *"runner" => {
format!("node_{}", run_options.number)
}
(_, false) | (Err(_), true) => run_options.owner.clone(),
(Ok(user), _) => user,
};

println!("Launching node {}...", run_options.number);
Expand Down
23 changes: 23 additions & 0 deletions sn_transfers/src/cashnotes/spend_reason.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use crate::GENESIS_CASHNOTE_SK;
use bls::{Ciphertext, PublicKey, SecretKey};
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -46,6 +47,28 @@ impl SpendReason {
input_str, input_pk,
)?))
}

pub fn get_sender_hash(&self) -> Option<Hash> {
match self {
Self::BetaRewardTracking(cypher) => {
let sk = match SecretKey::from_hex(GENESIS_CASHNOTE_SK) {
Ok(sk) => sk,
Err(err) => {
error!("Failed to get GENESIS sk {err:?}");
return None;
}
};

if let Ok(hash) = cypher.decrypt_to_username_hash(&sk) {
Some(hash)
} else {
error!("Failed to decrypt BetaRewardTracking");
None
}
}
_ => None,
}
}
}

lazy_static! {
Expand Down

0 comments on commit d01b121

Please sign in to comment.