From a3d17030fd1be96ff6ba66e17af9eb83de58e374 Mon Sep 17 00:00:00 2001 From: wiesche Date: Sun, 13 Sep 2026 08:42:16 +0200 Subject: [PATCH] share slate conversion code --- libwallet/src/slate.rs | 169 ++++++++++++++--------------------------- 1 file changed, 59 insertions(+), 110 deletions(-) diff --git a/libwallet/src/slate.rs b/libwallet/src/slate.rs index bd72d44..3cd6255 100644 --- a/libwallet/src/slate.rs +++ b/libwallet/src/slate.rs @@ -25,7 +25,7 @@ use crate::grin_core::libtx::{aggsig, build, proof::ProofBuild, tx_fee}; use crate::grin_core::map_vec; use crate::grin_keychain::{BlindSum, BlindingFactor, Keychain, SwitchCommitmentType}; use crate::grin_util::secp::key::{PublicKey, SecretKey}; -use crate::grin_util::secp::pedersen::Commitment; +use crate::grin_util::secp::pedersen::{Commitment, RangeProof}; use crate::grin_util::secp::Signature; use crate::grin_util::{secp, static_secp_instance}; use crate::payment_proof::{check_proof_type, EarlyPaymentProof}; @@ -1034,25 +1034,28 @@ impl From<&Slate> for SlateV5 { impl From<&Slate> for Option> { fn from(slate: &Slate) -> Self { - match slate.tx { - None => None, - Some(ref tx) => { - let mut ret_vec = vec![]; - match tx.inputs() { - Inputs::CommitOnly(_) => panic!("commit only inputs unsupported"), - Inputs::FeaturesAndCommit(ref inputs) => { - for input in inputs { - ret_vec.push(input.into()); - } - } - } - for output in tx.outputs() { - ret_vec.push(output.into()); - } - Some(ret_vec) + slate_commitments(slate) + } +} + +fn slate_commitments(slate: &Slate) -> Option> +where + C: for<'a> From<&'a Input> + for<'a> From<&'a Output>, +{ + let tx = slate.tx.as_ref()?; + let mut commitments = vec![]; + match tx.inputs() { + Inputs::CommitOnly(_) => panic!("commit only inputs unsupported"), + Inputs::FeaturesAndCommit(ref inputs) => { + for input in inputs { + commitments.push(input.into()); } } } + for output in tx.outputs() { + commitments.push(output.into()); + } + Some(commitments) } impl From<&ParticipantData> for ParticipantDataV5 { @@ -1197,23 +1200,32 @@ impl From for Slate { } pub fn tx_from_slate_v5(slate: &SlateV5) -> Option { - let coms = match slate.coms.as_ref() { - Some(c) => c, - None => return None, - }; + let coms = slate.coms.as_ref()?; + transaction_from_parts( + slate.fee, + slate.feat, + slate.feat_args.as_ref().map(KernelFeaturesArgs::from), + slate.sigs.iter().map(ParticipantData::from), + coms.iter().map(|c| (c.f.into(), c.c, c.p.as_ref())), + &slate.off, + ) +} + +fn transaction_from_parts<'a>( + fee: FeeFields, + features: u8, + feature_args: Option, + participants: impl Iterator, + commitments: impl Iterator)>, + offset: &BlindingFactor, +) -> Option { let secp = static_secp_instance(); let secp = secp.lock(); let mut calc_slate = Slate::blank(2, false); - calc_slate.fee_fields = slate.fee; - calc_slate.kernel_features = slate.feat; - calc_slate.kernel_features_args = slate.feat_args.as_ref().map(KernelFeaturesArgs::from); - for d in slate.sigs.iter() { - calc_slate.participant_data.push(ParticipantData { - public_blind_excess: d.xs, - public_nonce: d.nonce, - part_sig: d.part, - }); - } + calc_slate.fee_fields = fee; + calc_slate.kernel_features = features; + calc_slate.kernel_features_args = feature_args; + calc_slate.participant_data.extend(participants); let excess = match calc_slate.calc_excess(&secp) { Ok(e) => e, Err(_) => Commitment::from_vec(vec![0]), @@ -1232,15 +1244,15 @@ pub fn tx_from_slate_v5(slate: &SlateV5) -> Option { let mut outputs = vec![]; let mut inputs = vec![]; - for c in coms.iter() { - match &c.p { + for (features, commitment, proof) in commitments { + match proof { Some(p) => { - outputs.push(Output::new(c.f.into(), c.c, p.clone())); + outputs.push(Output::new(features, commitment, *p)); } None => { inputs.push(Input { - features: c.f.into(), - commit: c.c, + features, + commit: commitment, }); } } @@ -1250,7 +1262,7 @@ pub fn tx_from_slate_v5(slate: &SlateV5) -> Option { .body .replace_inputs(inputs.as_slice().into()) .replace_outputs(outputs.as_slice()); - tx.offset = slate.off.clone(); + tx.offset = offset.clone(); Some(tx) } @@ -1418,24 +1430,7 @@ impl TryFrom<&Slate> for SlateV4 { impl From<&Slate> for Option> { fn from(slate: &Slate) -> Self { - match slate.tx { - None => None, - Some(ref tx) => { - let mut ret_vec = vec![]; - match tx.inputs() { - Inputs::CommitOnly(_) => panic!("commit only inputs unsupported"), - Inputs::FeaturesAndCommit(ref inputs) => { - for input in inputs { - ret_vec.push(input.into()); - } - } - } - for output in tx.outputs() { - ret_vec.push(output.into()); - } - Some(ret_vec) - } - } + slate_commitments(slate) } } @@ -1576,61 +1571,15 @@ impl From for Slate { } pub fn tx_from_slate_v4(slate: &SlateV4) -> Option { - let coms = match slate.coms.as_ref() { - Some(c) => c, - None => return None, - }; - let secp = static_secp_instance(); - let secp = secp.lock(); - let mut calc_slate = Slate::blank(2, false); - calc_slate.fee_fields = slate.fee; - calc_slate.kernel_features = slate.feat; - calc_slate.kernel_features_args = slate.feat_args.as_ref().map(KernelFeaturesArgs::from); - for d in slate.sigs.iter() { - calc_slate.participant_data.push(ParticipantData { - public_blind_excess: d.xs, - public_nonce: d.nonce, - part_sig: d.part, - }); - } - let excess = match calc_slate.calc_excess(&secp) { - Ok(e) => e, - Err(_) => Commitment::from_vec(vec![0]), - }; - let excess_sig = match calc_slate.finalize_signature(&secp) { - Ok(s) => s, - Err(_) => Signature::from_raw_data(&[0; 64]).unwrap(), - }; - let kernel = TxKernel { - features: calc_slate.kernel_features().ok()?, - excess, - excess_sig, - }; - let mut tx = Slate::empty_transaction().with_kernel(kernel); - - let mut outputs = vec![]; - let mut inputs = vec![]; - - for c in coms.iter() { - match &c.p { - Some(p) => { - outputs.push(Output::new(c.f.into(), c.c, p.clone())); - } - None => { - inputs.push(Input { - features: c.f.into(), - commit: c.c, - }); - } - } - } - - tx.body = tx - .body - .replace_inputs(inputs.as_slice().into()) - .replace_outputs(outputs.as_slice()); - tx.offset = slate.off.clone(); - Some(tx) + let coms = slate.coms.as_ref()?; + transaction_from_parts( + slate.fee, + slate.feat, + slate.feat_args.as_ref().map(KernelFeaturesArgs::from), + slate.sigs.iter().map(ParticipantData::from), + coms.iter().map(|c| (c.f.into(), c.c, c.p.as_ref())), + &slate.off, + ) } // Node's Transaction object and lock height to SlateV4 `coms`