Skip to content

Commit

Permalink
feat: add new esmeralda pre-mine for test (tari-project#6460)
Browse files Browse the repository at this point in the history
Description
---
- Added new esmeralda pre-mine for test.
- Added a new console wallet command to get the spending status of all
pre-mine outputs in the genesis block.

Motivation and Context
---
Getting ready for mainnet

How Has This Been Tested?
---
Unit tests
System-level testing for the new console wallet command

What process can a PR reviewer use to test or verify this change?
---
Code review
System-level testing for the new console wallet command

<!-- Checklist -->
<!-- 1. Is the title of your PR in the form that would make nice release
notes? The title, excluding the conventional commit
tag, will be included exactly as is in the CHANGELOG, so please think
about it carefully. -->


Breaking Changes
---

- [x] None
- [ ] Requires data directory on base node to be deleted
- [ ] Requires hard fork
- [ ] Other - Please specify

<!-- Does this include a breaking change? If so, include this line as a
footer -->
<!-- BREAKING CHANGE: Description what the user should do, e.g. delete a
database, resync the chain -->
  • Loading branch information
hansieodendaal authored Aug 8, 2024
1 parent c8f0896 commit 310a470
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 195 deletions.
122 changes: 96 additions & 26 deletions applications/minotari_console_wallet/src/automation/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use std::{
};

use chrono::{DateTime, Utc};
use digest::{crypto_common::rand_core::OsRng, Digest};
use digest::Digest;
use futures::FutureExt;
use log::*;
use minotari_app_grpc::tls::certs::{generate_self_signed_certs, print_warning, write_cert_to_disk};
Expand Down Expand Up @@ -70,6 +70,7 @@ use tari_comms::{
};
use tari_comms_dht::{envelope::NodeDestination, DhtDiscoveryRequester};
use tari_core::{
blocks::pre_mine::get_pre_mine_items,
covenants::Covenant,
transactions::{
key_manager::TransactionKeyManagerInterface,
Expand All @@ -87,13 +88,10 @@ use tari_core::{
},
},
};
use tari_crypto::{
keys::SecretKey,
ristretto::{pedersen::PedersenCommitment, RistrettoSecretKey},
};
use tari_crypto::ristretto::{pedersen::PedersenCommitment, RistrettoSecretKey};
use tari_key_manager::key_manager_service::{KeyId, KeyManagerInterface};
use tari_script::{script, CheckSigSchnorrSignature};
use tari_utilities::{encoding::Base58, hex::Hex, ByteArray};
use tari_utilities::{hex::Hex, ByteArray};
use tokio::{
sync::{broadcast, mpsc},
time::{sleep, timeout},
Expand All @@ -103,6 +101,7 @@ use super::error::CommandError;
use crate::{
automation::{
utils::{
create_pre_mine_output_dir,
get_file_name,
move_session_file_to_session_dir,
out_dir,
Expand Down Expand Up @@ -765,6 +764,65 @@ pub async fn command_runner(
Err(e) => eprintln!("BurnMinotari error! {}", e),
}
},
PreMineSpendGetOutputStatus => {
let pre_mine_outputs = get_all_embedded_pre_mine_outputs()?;
let output_hashes: Vec<HashOutput> = pre_mine_outputs.iter().map(|v| v.hash()).collect();
let unspent_outputs = transaction_service.fetch_unspent_outputs(output_hashes).await?;

let pre_mine_items = match get_pre_mine_items(Network::get_current_or_user_setting_or_default()).await {
Ok(items) => items,
Err(e) => {
eprintln!("\nError: {}\n", e);
return Ok(());
},
};

let (session_id, out_dir) = match create_pre_mine_output_dir(Some("pre_mine_status")) {
Ok(values) => values,
Err(e) => {
eprintln!("\nError: {}\n", e);
return Ok(());
},
};
let csv_file_name = "pre_mine_items_with_status.csv";
let csv_out_file = out_dir.join(csv_file_name);
let mut file_stream =
File::create(&csv_out_file).expect("Could not create 'pre_mine_items_with_status.csv'");
if let Err(e) =
file_stream.write_all("index,value,maturity,fail_safe_height,beneficiary,spent_status\n".as_bytes())
{
eprintln!("\nError: Could not write pre-mine header ({})\n", e);
return Ok(());
}

for (index, item) in pre_mine_items.iter().enumerate() {
let unspent = unspent_outputs
.iter()
.any(|u| u.commitment() == &pre_mine_outputs[index].commitment);
if let Err(e) = file_stream.write_all(
format!(
"{},{},{},{},{},{}\n",
index,
item.value,
item.maturity,
item.maturity + item.fail_safe_height,
item.beneficiary,
if unspent { "unspent" } else { "spent" },
)
.as_bytes(),
) {
eprintln!("\nError: Could not write pre-mine item ({})\n", e);
return Ok(());
}
}

println!();
println!("Concluded step 0 'pre-mine-spend-get-output-status'");
println!("Your session ID is: '{}'", session_id);
println!("Your session's output directory is: '{}'", out_dir.display());
println!("Pre-mine output spent status saved to: '{}'", csv_file_name);
println!();
},
PreMineSpendSessionInfo(args) => {
match key_manager_service.get_wallet_type().await {
WalletType::Ledger(_) => {},
Expand Down Expand Up @@ -803,8 +861,13 @@ pub async fn command_runner(
}
}

let mut session_id = PrivateKey::random(&mut OsRng).to_base58();
session_id.truncate(16);
let (session_id, out_dir) = match create_pre_mine_output_dir(None) {
Ok(values) => values,
Err(e) => {
eprintln!("\nError: {}\n", e);
return Ok(());
},
};
let session_info = PreMineSpendStep1SessionInfo {
session_id: session_id.clone(),
commitment_to_spend: commitment.to_hex(),
Expand All @@ -813,11 +876,11 @@ pub async fn command_runner(
fee_per_gram: args.fee_per_gram,
output_index: args.output_index,
};
let out_dir = out_dir(&session_info.session_id)?;

let out_file = out_dir.join(get_file_name(SPEND_SESSION_INFO, None));
write_to_json_file(&out_file, true, session_info)?;
println!();
println!("Concluded step 1 'pre-mine-generate-session-info'");
println!("Concluded step 1 'pre-mine-spend-session-info'");
println!("Your session ID is: '{}'", session_id);
println!("Your session's output directory is: '{}'", out_dir.display());
println!("Session info saved to: '{}'", out_file.display());
Expand Down Expand Up @@ -857,6 +920,7 @@ pub async fn command_runner(
{
Ok(tx_id) => {
println!();
println!("Concluded 'pre-mine-spend-backup-utxo'");
println!("Spend utxo: {} with tx_id: {}", commitment.to_hex(), tx_id);
println!();
},
Expand Down Expand Up @@ -978,7 +1042,7 @@ pub async fn command_runner(
write_json_object_to_file_as_line(&out_file_self, false, step_2_outputs_for_self)?;

println!();
println!("Concluded step 2 'pre-mine-create-party-details'");
println!("Concluded step 2 'pre-mine-spend-party-details'");
println!("Your session's output directory is '{}'", out_dir.display());
move_session_file_to_session_dir(&session_info.session_id, &args.input_file)?;
println!(
Expand Down Expand Up @@ -1071,7 +1135,7 @@ pub async fn command_runner(
write_json_object_to_file_as_line(&out_file, false, step_3_outputs_for_parties)?;

println!();
println!("Concluded step 3 'pre-mine-encumber-aggregate-utxo'");
println!("Concluded step 3 'pre-mine-spend-encumber-aggregate-utxo'");
println!(
"Send '{}' to parties for step 4",
get_file_name(SPEND_STEP_3_PARTIES, None)
Expand Down Expand Up @@ -1185,7 +1249,7 @@ pub async fn command_runner(
write_json_object_to_file_as_line(&out_file, false, step_4_outputs_for_leader)?;

println!();
println!("Concluded step 4 'pre-mine-create-input-output-sigs'");
println!("Concluded step 4 'pre-mine-spend-input-output-sigs'");
println!(
"Send '{}' to leader for step 5",
get_file_name(SPEND_STEP_4_LEADER, Some(party_info.alias))
Expand Down Expand Up @@ -1238,7 +1302,7 @@ pub async fn command_runner(
{
Ok(_v) => {
println!();
println!("Concluded step 5 'pre-mine-spend-aggregate-utxo'");
println!("Concluded step 5 'pre-mine-spend-aggregate-transaction'");
println!();
},
Err(e) => println!("\nError: Error completing transaction! {}\n", e),
Expand Down Expand Up @@ -1794,6 +1858,23 @@ pub async fn command_runner(
}

fn get_embedded_pre_mine_outputs(output_indexes: Vec<usize>) -> Result<Vec<TransactionOutput>, CommandError> {
let utxos = get_all_embedded_pre_mine_outputs()?;

let mut fetched_outputs = Vec::with_capacity(output_indexes.len());
for index in output_indexes {
if index >= utxos.len() {
return Err(CommandError::PreMine(format!(
"Error: Invalid 'output_index' {} provided pre-mine outputs only number {}!",
index,
utxos.len()
)));
}
fetched_outputs.push(utxos[index].clone());
}
Ok(fetched_outputs)
}

fn get_all_embedded_pre_mine_outputs() -> Result<Vec<TransactionOutput>, CommandError> {
let pre_mine_contents = match Network::get_current_or_user_setting_or_default() {
Network::MainNet => {
include_str!("../../../../base_layer/core/src/blocks/pre_mine/mainnet_pre_mine.json")
Expand Down Expand Up @@ -1828,18 +1909,7 @@ fn get_embedded_pre_mine_outputs(output_indexes: Vec<usize>) -> Result<Vec<Trans
counter += 1;
}

let mut fetched_outputs = Vec::with_capacity(output_indexes.len());
for index in output_indexes {
if index >= utxos.len() {
return Err(CommandError::PreMine(format!(
"Error: Invalid 'output_index' {} provided pre-mine outputs only number {}!",
index,
utxos.len()
)));
}
fetched_outputs.push(utxos[index].clone());
}
Ok(fetched_outputs)
Ok(utxos)
}

fn write_utxos_to_csv_file(
Expand Down
18 changes: 18 additions & 0 deletions applications/minotari_console_wallet/src/automation/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ use std::{
path::{Path, PathBuf},
};

use digest::crypto_common::rand_core::OsRng;
use serde::{de::DeserializeOwned, Serialize};
use tari_common_types::types::PrivateKey;
use tari_crypto::keys::SecretKey;
use tari_utilities::encoding::Base58;

use crate::automation::{
commands::{FILE_EXTENSION, SPEND_SESSION_INFO},
Expand Down Expand Up @@ -127,6 +131,20 @@ fn append_to_json_file<P: AsRef<Path>, T: Serialize>(file: P, data: T) -> Result
Ok(())
}

/// Create a unique session-based output directory
pub(crate) fn create_pre_mine_output_dir(alias: Option<&str>) -> Result<(String, PathBuf), CommandError> {
let mut session_id = PrivateKey::random(&mut OsRng).to_base58();
session_id.truncate(if alias.is_some() { 8 } else { 16 });
if let Some(alias) = alias {
session_id.push('_');
session_id.push_str(alias);
}
let out_dir = out_dir(&session_id)?;
fs::create_dir_all(out_dir.clone())
.map_err(|e| CommandError::JsonFile(format!("{} ({})", e, out_dir.display())))?;
Ok((session_id, out_dir))
}

/// Return the output directory for the session
pub(crate) fn out_dir(session_id: &str) -> Result<PathBuf, CommandError> {
let base_dir = dirs_next::document_dir().ok_or(CommandError::InvalidArgument(
Expand Down
1 change: 1 addition & 0 deletions applications/minotari_console_wallet/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ pub enum CliCommands {
GetBalance,
SendMinotari(SendMinotariArgs),
BurnMinotari(BurnMinotariArgs),
PreMineSpendGetOutputStatus,
PreMineSpendSessionInfo(PreMineSpendSessionInfoArgs),
PreMineSpendPartyDetails(PreMineSpendPartyDetailsArgs),
PreMineSpendEncumberAggregateUtxo(PreMineSpendEncumberAggregateUtxoArgs),
Expand Down
8 changes: 7 additions & 1 deletion applications/minotari_console_wallet/src/wallet_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ fn force_exit_for_pre_mine_commands(command: &CliCommands) -> (bool, bool) {
(
matches!(
command,
CliCommands::PreMineSpendSessionInfo(_) |
CliCommands::PreMineSpendGetOutputStatus |
CliCommands::PreMineSpendSessionInfo(_) |
CliCommands::PreMineSpendEncumberAggregateUtxo(_) |
CliCommands::PreMineSpendPartyDetails(_) |
CliCommands::PreMineSpendInputOutputSigs(_) |
Expand Down Expand Up @@ -549,6 +550,8 @@ mod test {
burn-minotari --message Ups_these_funds_will_be_burned! 100T
pre-mine-spend-get-output-status
pre-mine-spend-session-info --fee-per-gram 2 --output-index 123 --recipient-address \
f4LR9f6WwwcPiKJjK5ciTkU1ocNhANa3FPw1wkyVUwbuKpgiihawCXy6PFszunUWQ4Te8KVFnyWVHHwsk9x5Cg7ZQiA \
--verify-unspent-outputs
Expand Down Expand Up @@ -584,6 +587,7 @@ mod test {
let mut get_balance = false;
let mut send_tari = false;
let mut burn_tari = false;
let mut pre_mine_spend_get_output_status = false;
let mut pre_mine_spend_session_info = false;
let mut pre_mine_spend_encumber_aggregate_utxo = false;
let mut pre_mine_spend_aggregate_transaction = false;
Expand All @@ -600,6 +604,7 @@ mod test {
CliCommands::GetBalance => get_balance = true,
CliCommands::SendMinotari(_) => send_tari = true,
CliCommands::BurnMinotari(_) => burn_tari = true,
CliCommands::PreMineSpendGetOutputStatus => pre_mine_spend_get_output_status = true,
CliCommands::PreMineSpendSessionInfo(_) => pre_mine_spend_session_info = true,
CliCommands::PreMineSpendPartyDetails(_) => pre_mine_spend_party_details = true,
CliCommands::PreMineSpendEncumberAggregateUtxo(_) => pre_mine_spend_encumber_aggregate_utxo = true,
Expand Down Expand Up @@ -641,6 +646,7 @@ mod test {
get_balance &&
send_tari &&
burn_tari &&
pre_mine_spend_get_output_status &&
pre_mine_spend_session_info &&
pre_mine_spend_encumber_aggregate_utxo &&
pre_mine_spend_aggregate_transaction &&
Expand Down
6 changes: 3 additions & 3 deletions base_layer/core/src/blocks/genesis_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,9 @@ pub fn get_esmeralda_genesis_block() -> ChainBlock {

// Hardcode the Merkle roots once they've been computed above
block.header.kernel_mr =
FixedHash::from_hex("c3b93616d0e6289e8faff111d9d7b009fc45a04f3a5c31a5ad22610bc37f9dd7").unwrap();
FixedHash::from_hex("7db4197b169ee6c2ec3ffb04481c41ef6e900e41cbd96b35c4c0a77badfe4fbe").unwrap();
block.header.output_mr =
FixedHash::from_hex("002a2ca5084105b8f0a165a40b6e707fd6cbae5ae14ca590735e21dd14ddb00a").unwrap();
FixedHash::from_hex("d75c2b76fb3da80bacb1b00f75a0fa4ea4002e79a2691085f4edb18f2de79ae0").unwrap();
block.header.validator_node_mr =
FixedHash::from_hex("277da65c40b2cf99db86baedb903a3f0a38540f3a94d40c826eecac7e27d5dfc").unwrap();
}
Expand All @@ -347,7 +347,7 @@ pub fn get_esmeralda_genesis_block() -> ChainBlock {

fn get_esmeralda_genesis_block_raw() -> Block {
// Set genesis timestamp
let genesis_timestamp = DateTime::parse_from_rfc2822("06 Aug 2024 08:00:00 +0200").expect("parse may not fail");
let genesis_timestamp = DateTime::parse_from_rfc2822("08 Aug 2024 08:00:00 +0200").expect("parse may not fail");
// Let us add a "not before" proof to the genesis block
let not_before_proof =
b"as I sip my drink, thoughts of esmeralda consume my mind, like a refreshing nourishing draught \
Expand Down
Loading

0 comments on commit 310a470

Please sign in to comment.