diff --git a/src/blind.rs b/src/blind.rs index 340e62c5..424a4e7d 100644 --- a/src/blind.rs +++ b/src/blind.rs @@ -916,17 +916,30 @@ impl TxIn { } } -/// Data structure for Unifying inputs and pseudo-inputs. +/// Inputs or pseudo-inputs. #[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)] -pub enum TxInType { +pub enum CtLocationType { /// Regular input - Input(usize), - /// Issuance Pseudo-input - Issuance(usize), - /// Re-issuance pseudo-input - ReIssuance(usize), + Input, + + /// Issuance pseudo-input + Issuance, + + /// Reissuance pseudo-input + Reissuance, } +/// Data structure for Unifying inputs and pseudo-inputs. +#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub struct CtLocation { + /// Input index + pub input_index: usize, + + /// Input or pseudo-input type + pub ty: CtLocationType, +} + + impl Transaction { /// Verify that the transaction has correctly calculated blinding /// factors and they CT verification equation holds. @@ -1078,7 +1091,7 @@ impl Transaction { secp: &Secp256k1, spent_utxo_secrets: &[TxOutSecrets], blind_issuances: bool, - ) -> Result, BlindError> + ) -> Result, BlindError> where R: RngCore + CryptoRng, C: Signing, @@ -1090,13 +1103,13 @@ impl Transaction { let (iss_vbf, iss_sk, tkn_vbf, tkn_sk) = txin.blind_issuances(secp, rng)?; if txin.asset_issuance.amount.is_confidential() { blinds.insert( - TxInType::Issuance(i), + CtLocation{ input_index: i, ty: CtLocationType::Issuance }, (AssetBlindingFactor::zero(), iss_vbf, iss_sk), ); } if txin.asset_issuance.inflation_keys.is_confidential() { blinds.insert( - TxInType::ReIssuance(i), + CtLocation{ input_index: i, ty: CtLocationType::Reissuance }, (AssetBlindingFactor::zero(), tkn_vbf, tkn_sk), ); } @@ -1144,7 +1157,8 @@ impl Transaction { spent_utxo_secrets, )?; - blinds.insert(TxInType::Input(i), (abf, vbf, ephemeral_sk)); + let location = CtLocation { input_index: i, ty: CtLocationType::Input}; + blinds.insert(location, (abf, vbf, ephemeral_sk)); out_secrets.push(TxOutSecrets::new( out.asset.explicit().unwrap(), abf, @@ -1184,7 +1198,8 @@ impl Transaction { &out_secrets, )?; - blinds.insert(TxInType::Input(last_index), (abf, vbf, ephemeral_sk)); + let location = CtLocation{ input_index: last_index, ty: CtLocationType::Input }; + blinds.insert(location, (abf, vbf, ephemeral_sk)); self.output[last_index] = conf_out; Ok(blinds) } diff --git a/src/lib.rs b/src/lib.rs index b54fc1f5..f90057ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,7 +78,7 @@ pub use bitcoin::hashes; pub use crate::address::{Address, AddressError, AddressParams}; pub use crate::blind::{ BlindAssetProofs, BlindError, BlindValueProofs, ConfidentialTxOutError, RangeProofMessage, - SurjectionInput, TxOutError, TxOutSecrets, UnblindError, VerificationError, + SurjectionInput, TxOutError, TxOutSecrets, UnblindError, VerificationError, CtLocation, CtLocationType, }; pub use crate::block::ExtData as BlockExtData; pub use crate::block::{Block, BlockHeader}; diff --git a/src/pset/mod.rs b/src/pset/mod.rs index 532826ec..34106095 100644 --- a/src/pset/mod.rs +++ b/src/pset/mod.rs @@ -20,7 +20,7 @@ //! Extension for PSET is based on PSET defined in BIP370. //! -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::{cmp, io}; mod error; @@ -46,7 +46,10 @@ use crate::{ confidential::{AssetBlindingFactor, ValueBlindingFactor}, TxOutSecrets, }; -use crate::{OutPoint, LockTime, Sequence, SurjectionInput, Transaction, TxIn, TxInWitness, TxOut, TxOutWitness, Txid}; +use crate::{ + LockTime, OutPoint, Sequence, SurjectionInput, Transaction, TxIn, + TxInWitness, TxOut, TxOutWitness, Txid, CtLocation, CtLocationType, +}; use secp256k1_zkp::rand::{CryptoRng, RngCore}; use secp256k1_zkp::{self, RangeProof, SecretKey, SurjectionProof}; @@ -478,20 +481,20 @@ impl PartiallySignedTransaction { rng: &mut R, secp: &secp256k1_zkp::Secp256k1, inp_txout_sec: &HashMap, - ) -> Result, PsetBlindError> { + ) -> Result, PsetBlindError> { let (inp_secrets, outs_to_blind) = self.blind_checks(inp_txout_sec)?; + let mut ret = BTreeMap::new(); // return all the random values used if outs_to_blind.is_empty() { // Return empty values if no outputs are marked for blinding - return Ok(Vec::new()); + return Ok(ret); } // Blind each output as non-last and save the secrets let surject_inputs = self.surjection_inputs(inp_txout_sec)?; let mut out_secrets = vec![]; - let mut ret = vec![]; // return all the random values used for i in outs_to_blind { let txout = self.outputs[i].to_txout(); - let (txout, abf, vbf, _) = txout + let (txout, abf, vbf, ephemeral_sk) = txout .to_non_last_confidential( rng, secp, @@ -538,7 +541,8 @@ impl PartiallySignedTransaction { )); } // return blinding factors used - ret.push((abf, vbf)); + let location = CtLocation{ input_index: i, ty: CtLocationType::Input}; + ret.insert(location, (abf, vbf, ephemeral_sk)); } // safe to unwrap because we have checked that there is atleast one output to blind @@ -579,9 +583,10 @@ impl PartiallySignedTransaction { rng: &mut R, secp: &secp256k1_zkp::Secp256k1, inp_txout_sec: &HashMap, - ) -> Result<(), PsetBlindError> { + ) -> Result, PsetBlindError> { let (mut inp_secrets, mut outs_to_blind) = self.blind_checks(inp_txout_sec)?; + let mut ret = BTreeMap::new(); if outs_to_blind.is_empty() { // Atleast one output must be marked for blinding for pset blind_last return Err(PsetBlindError::AtleastOneOutputBlind); @@ -594,7 +599,7 @@ impl PartiallySignedTransaction { let ind = self.outputs[last_out_index].blinder_index; self.outputs[last_out_index].blinder_index = None; // Blind normally without the last index - self.blind_non_last(rng, secp, inp_txout_sec)?; + ret = self.blind_non_last(rng, secp, inp_txout_sec)?; // Restore who blinded the last output self.outputs[last_out_index].blinder_index = ind; // inp_secrets contributed to self.global.scalars, unset it so we don't count them @@ -657,6 +662,8 @@ impl PartiallySignedTransaction { ); let (value_commitment, nonce, rangeproof) = blind_res.map_err(|e| PsetBlindError::ConfidentialTxOutError(last_out_index, e))?; + let location = CtLocation{ input_index: last_out_index, ty: CtLocationType::Input}; + ret.insert(location, (out_abf, final_vbf, ephemeral_sk)); // mutate the pset { @@ -690,7 +697,7 @@ impl PartiallySignedTransaction { self.global.scalars.clear(); } - Ok(()) + Ok(ret) } }