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

Draft
wants to merge 1 commit into
base: development
Choose a base branch
from
Draft
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
935 changes: 652 additions & 283 deletions applications/minotari_console_wallet/src/automation/commands.rs

Large diffs are not rendered by default.

44 changes: 40 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,13 @@ 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>,
}

#[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 +62,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 +79,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 +98,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 +132,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
58 changes: 54 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,64 @@ 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,
}

#[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 recipient_info: Vec<CliRecipientInfo>,
#[clap(long)]
pub alias: String,
}
Expand All @@ -227,6 +273,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
7 changes: 5 additions & 2 deletions applications/minotari_console_wallet/src/wallet_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,11 +543,14 @@ 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

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-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
Loading
Loading