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

feat: update pre-mine specification and allow multiple spends #6590

Merged
Merged
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
1,037 changes: 750 additions & 287 deletions applications/minotari_console_wallet/src/automation/commands.rs

Large diffs are not rendered by default.

45 changes: 41 additions & 4 deletions applications/minotari_console_wallet/src/automation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ use tari_script::{CheckSigSchnorrSignature, ExecutionStack, TariScript};
struct PreMineSpendStep1SessionInfo {
session_id: String,
fee_per_gram: MicroMinotari,
commitment_to_spend: String,
output_hash: String,
recipient_info: Vec<RecipientInfo>,
use_pre_mine_input_file: bool,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct RecipientInfo {
output_to_be_spend: usize,
recipient_address: TariAddress,
output_index: usize,
}

impl SessionId for PreMineSpendStep1SessionInfo {
Expand All @@ -59,8 +63,14 @@ impl SessionId for PreMineSpendStep1SessionInfo {
// Step 2 outputs for self with `PreMineSpendPartyDetails`
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct PreMineSpendStep2OutputsForSelf {
outputs_for_self: Vec<Step2OutputsForSelf>,
alias: String,
wallet_spend_key_id: TariKeyId,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct Step2OutputsForSelf {
output_index: usize,
recipient_address: TariAddress,
script_nonce_key_id: TariKeyId,
sender_offset_key_id: TariKeyId,
sender_offset_nonce_key_id: TariKeyId,
Expand All @@ -70,6 +80,14 @@ struct PreMineSpendStep2OutputsForSelf {
// Step 2 outputs for leader with `PreMineSpendPartyDetails`
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct PreMineSpendStep2OutputsForLeader {
outputs_for_leader: Vec<Step2OutputsForLeader>,
alias: String,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct Step2OutputsForLeader {
output_index: usize,
recipient_address: TariAddress,
script_input_signature: CheckSigSchnorrSignature,
public_script_nonce_key: PublicKey,
public_sender_offset_key: PublicKey,
Expand All @@ -81,12 +99,24 @@ struct PreMineSpendStep2OutputsForLeader {
// Step 3 outputs for self with `PreMineSpendEncumberAggregateUtxo`
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct PreMineSpendStep3OutputsForSelf {
outputs_for_self: Vec<Step3OutputsForSelf>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct Step3OutputsForSelf {
output_index: usize,
tx_id: TxId,
}

// Step 3 outputs for parties with `PreMineSpendEncumberAggregateUtxo`
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct PreMineSpendStep3OutputsForParties {
outputs_for_parties: Vec<Step3OutputsForParties>,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct Step3OutputsForParties {
output_index: usize,
input_stack: ExecutionStack,
input_script: TariScript,
total_script_key: PublicKey,
Expand All @@ -103,6 +133,13 @@ struct PreMineSpendStep3OutputsForParties {
// Step 4 outputs for leader with `PreMineSpendInputOutputSigs`
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct PreMineSpendStep4OutputsForLeader {
outputs_for_leader: Vec<Step4OutputsForLeader>,
alias: String,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
struct Step4OutputsForLeader {
output_index: usize,
script_signature: Signature,
metadata_signature: Signature,
script_offset: PrivateKey,
Expand Down
66 changes: 62 additions & 4 deletions applications/minotari_console_wallet/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use std::{
fmt::{Debug, Display, Formatter},
path::PathBuf,
str::FromStr,
time::Duration,
};

Expand Down Expand Up @@ -190,19 +191,68 @@ pub struct PreMineSpendSessionInfoArgs {
#[clap(long)]
pub fee_per_gram: MicroMinotari,
#[clap(long)]
pub output_index: usize,
#[clap(long)]
pub recipient_address: TariAddress,
pub recipient_info: Vec<CliRecipientInfo>,
#[clap(long)]
pub verify_unspent_outputs: bool,
#[clap(long)]
pub use_pre_mine_input_file: bool,
}

#[derive(Debug, Args, Clone)]
pub struct CliRecipientInfo {
pub output_indexes: Vec<usize>,
pub recipient_address: TariAddress,
}

impl FromStr for CliRecipientInfo {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
// Parse 'RecipientInfo' from "[<v1>,<v2>,<v3>]:<recipient_address>"
if !s.contains(':') {
return Err("Invalid 'recipient-info', could not find address separator ':'".to_string());
}
let parts: Vec<&str> = s.split(':').collect();
if parts.len() != 2 {
return Err(format!(
"Invalid 'recipient-info', needs exactly 2 parts, found {}",
parts.len()
));
}

// Parse output indexes
if !parts[0].starts_with('[') && !parts[0].ends_with(']') {
return Err("Invalid 'recipient-info' part 1; array bounds must be indicated with '[' and ']'".to_string());
}
let binding = parts[0].replace("[", "").replace("]", "");
let parts_0 = binding.split(',').collect::<Vec<&str>>();
let output_indexes = parts_0
.iter()
.map(|v| {
v.parse()
.map_err(|e| format!("'recipient_info' - invalid output_index: {}", e))
})
.collect::<Result<Vec<usize>, String>>()?;

// Parse recipient address
let recipient_address = TariAddress::from_base58(parts[1])
.map_err(|e| format!("'recipient_info' - invalid recipient address: {}", e))?;

Ok(CliRecipientInfo {
output_indexes,
recipient_address,
})
}
}

#[derive(Debug, Args, Clone)]
pub struct PreMineSpendPartyDetailsArgs {
#[clap(long)]
pub input_file: PathBuf,
#[clap(long)]
pub output_index: usize,
pub pre_mine_file_path: Option<PathBuf>,
#[clap(long)]
pub recipient_info: Vec<CliRecipientInfo>,
#[clap(long)]
pub alias: String,
}
Expand All @@ -213,12 +263,16 @@ pub struct PreMineSpendEncumberAggregateUtxoArgs {
pub session_id: String,
#[clap(long)]
pub input_file_names: Vec<String>,
#[clap(long)]
pub pre_mine_file_path: Option<PathBuf>,
}

#[derive(Debug, Args, Clone)]
pub struct PreMineSpendInputOutputSigArgs {
#[clap(long)]
pub session_id: String,
#[clap(long)]
pub pre_mine_file_path: Option<PathBuf>,
}

#[derive(Debug, Args, Clone)]
Expand All @@ -227,6 +281,10 @@ pub struct PreMineSpendAggregateTransactionArgs {
pub session_id: String,
#[clap(long)]
pub input_file_names: Vec<String>,
#[clap(long)]
pub save_to_file: bool,
#[clap(long)]
pub print_to_console: bool,
}

#[derive(Debug, Args, Clone)]
Expand Down
10 changes: 7 additions & 3 deletions applications/minotari_console_wallet/src/wallet_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,11 +543,15 @@ mod test {

pre-mine-spend-get-output-status

pre-mine-spend-session-info --fee-per-gram 2 --output-index 123 --recipient-address \
pre-mine-spend-session-info --fee-per-gram 2 \
--recipient-info=[1,123,313]:\
f4LR9f6WwwcPiKJjK5ciTkU1ocNhANa3FPw1wkyVUwbuKpgiihawCXy6PFszunUWQ4Te8KVFnyWVHHwsk9x5Cg7ZQiA \
--verify-unspent-outputs
--verify-unspent-outputs --use-pre-mine-input-file

pre-mine-spend-party-details --input-file ./step_1_session_info.txt --output-index 123 --alias alice
pre-mine-spend-party-details --input-file ./step_1_session_info.txt --alias alice \
--recipient-info=[1,123,313]:\
f4LR9f6WwwcPiKJjK5ciTkU1ocNhANa3FPw1wkyVUwbuKpgiihawCXy6PFszunUWQ4Te8KVFnyWVHHwsk9x5Cg7ZQiA \
--pre-mine-file-path ./pre_mine_file.txt

pre-mine-spend-encumber-aggregate-utxo --session-id ee1643655c \
--input-file-names=step_2_for_leader_from_alice.txt --input-file-names=step_2_for_leader_from_bob.txt \
Expand Down
17 changes: 9 additions & 8 deletions base_layer/core/src/blocks/genesis_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ use tari_utilities::ByteArray;
use crate::{
blocks::{block::Block, BlockHeader, BlockHeaderAccumulatedData, ChainBlock},
proof_of_work::{AccumulatedDifficulty, Difficulty, PowAlgorithm, PowData, ProofOfWork},
transactions::{aggregated_body::AggregateBody, transaction_components::TransactionOutput},
transactions::{
aggregated_body::AggregateBody,
transaction_components::{TransactionKernel, TransactionOutput},
},
OutputSmt,
};

Expand All @@ -51,17 +54,15 @@ pub fn get_genesis_block(network: Network) -> ChainBlock {

fn add_pre_mine_utxos_to_genesis_block(file: &str, block: &mut Block) {
let mut utxos = Vec::new();
let mut counter = 1;
let lines_count = file.lines().count();
for line in file.lines() {
if counter < lines_count {
let utxo: TransactionOutput = serde_json::from_str(line).unwrap();
if let Ok(utxo) = serde_json::from_str::<TransactionOutput>(line) {
utxos.push(utxo);
} else {
block.body.add_kernel(serde_json::from_str(line).unwrap());
} else if let Ok(kernel) = serde_json::from_str::<TransactionKernel>(line) {
block.body.add_kernel(kernel);
block.header.kernel_mmr_size += 1;
} else {
panic!("Error: Could not deserialize line: {} in file: {}", line, file);
}
counter += 1;
}
block.header.output_smt_size += utxos.len() as u64;
block.body.add_outputs(utxos);
Expand Down
Loading
Loading