mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
use AsRef in cut_through for flexibility (#3411)
and use fold() to get len of inputs, outputs, kernels
This commit is contained in:
parent
04c8713d83
commit
880f9adcd3
1 changed files with 34 additions and 28 deletions
|
@ -1290,26 +1290,33 @@ impl Transaction {
|
||||||
/// eliminating any input/output pairs with input spending output.
|
/// eliminating any input/output pairs with input spending output.
|
||||||
/// Returns new slices with cut-through elements removed.
|
/// Returns new slices with cut-through elements removed.
|
||||||
/// Also returns slices of the cut-through elements themselves.
|
/// Also returns slices of the cut-through elements themselves.
|
||||||
|
/// Note: Takes slices of _anything_ that is AsRef<Commitment> for greater flexibility.
|
||||||
|
/// So we can cut_through inputs and outputs but we can also cut_through inputs and output identifiers.
|
||||||
|
/// Or we can get crazy and cut_through inputs with other inputs to identify intersection and difference etc.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// Inputs: [A, B, C]
|
/// Inputs: [A, B, C]
|
||||||
/// Outputs: [C, D, E]
|
/// Outputs: [C, D, E]
|
||||||
/// Returns: ([A, B], [D, E], [C], [C]) # element C is cut-through
|
/// Returns: ([A, B], [D, E], [C], [C]) # element C is cut-through
|
||||||
pub fn cut_through<'a>(
|
pub fn cut_through<'a, 'b, T, U>(
|
||||||
inputs: &'a mut [Input],
|
inputs: &'a mut [T],
|
||||||
outputs: &'a mut [Output],
|
outputs: &'b mut [U],
|
||||||
) -> Result<(&'a [Input], &'a [Output], &'a [Input], &'a [Output]), Error> {
|
) -> Result<(&'a [T], &'b [U], &'a [T], &'b [U]), Error>
|
||||||
// Make sure inputs and outputs are sorted consistently by commitment.
|
where
|
||||||
inputs.sort_unstable_by_key(|x| x.commitment());
|
T: AsRef<Commitment> + Ord,
|
||||||
outputs.sort_unstable_by_key(|x| x.commitment());
|
U: AsRef<Commitment> + Ord,
|
||||||
|
{
|
||||||
|
// Make sure inputs and outputs are sorted consistently as we will iterate over both.
|
||||||
|
inputs.sort_unstable_by_key(|x| *x.as_ref());
|
||||||
|
outputs.sort_unstable_by_key(|x| *x.as_ref());
|
||||||
|
|
||||||
let mut inputs_idx = 0;
|
let mut inputs_idx = 0;
|
||||||
let mut outputs_idx = 0;
|
let mut outputs_idx = 0;
|
||||||
let mut ncut = 0;
|
let mut ncut = 0;
|
||||||
while inputs_idx < inputs.len() && outputs_idx < outputs.len() {
|
while inputs_idx < inputs.len() && outputs_idx < outputs.len() {
|
||||||
match inputs[inputs_idx]
|
match inputs[inputs_idx]
|
||||||
.partial_cmp(&outputs[outputs_idx])
|
.as_ref()
|
||||||
.expect("compare input to output")
|
.cmp(&outputs[outputs_idx].as_ref())
|
||||||
{
|
{
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
inputs.swap(inputs_idx - ncut, inputs_idx);
|
inputs.swap(inputs_idx - ncut, inputs_idx);
|
||||||
|
@ -1370,15 +1377,16 @@ pub fn aggregate(txs: &[Transaction]) -> Result<Transaction, Error> {
|
||||||
} else if txs.len() == 1 {
|
} else if txs.len() == 1 {
|
||||||
return Ok(txs[0].clone());
|
return Ok(txs[0].clone());
|
||||||
}
|
}
|
||||||
let mut n_inputs = 0;
|
|
||||||
let mut n_outputs = 0;
|
|
||||||
let mut n_kernels = 0;
|
|
||||||
for tx in txs.iter() {
|
|
||||||
n_inputs += tx.inputs().len();
|
|
||||||
n_outputs += tx.outputs().len();
|
|
||||||
n_kernels += tx.kernels().len();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let (n_inputs, n_outputs, n_kernels) =
|
||||||
|
txs.iter()
|
||||||
|
.fold((0, 0, 0), |(inputs, outputs, kernels), tx| {
|
||||||
|
(
|
||||||
|
inputs + tx.inputs().len(),
|
||||||
|
outputs + tx.outputs().len(),
|
||||||
|
kernels + tx.kernels().len(),
|
||||||
|
)
|
||||||
|
});
|
||||||
let mut inputs: Vec<Input> = Vec::with_capacity(n_inputs);
|
let mut inputs: Vec<Input> = Vec::with_capacity(n_inputs);
|
||||||
let mut outputs: Vec<Output> = Vec::with_capacity(n_outputs);
|
let mut outputs: Vec<Output> = Vec::with_capacity(n_outputs);
|
||||||
let mut kernels: Vec<TxKernel> = Vec::with_capacity(n_kernels);
|
let mut kernels: Vec<TxKernel> = Vec::with_capacity(n_kernels);
|
||||||
|
@ -1498,17 +1506,9 @@ pub struct Input {
|
||||||
impl DefaultHashable for Input {}
|
impl DefaultHashable for Input {}
|
||||||
hashable_ord!(Input);
|
hashable_ord!(Input);
|
||||||
|
|
||||||
// Inputs can be compared to outputs.
|
impl AsRef<Commitment> for Input {
|
||||||
impl PartialEq<Output> for Input {
|
fn as_ref(&self) -> &Commitment {
|
||||||
fn eq(&self, other: &Output) -> bool {
|
&self.commit
|
||||||
self.commitment() == other.commitment()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inputs can be compared to outputs.
|
|
||||||
impl PartialOrd<Output> for Input {
|
|
||||||
fn partial_cmp(&self, other: &Output) -> Option<Ordering> {
|
|
||||||
Some(self.commitment().cmp(&other.commitment()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1714,6 +1714,12 @@ pub struct Output {
|
||||||
impl DefaultHashable for Output {}
|
impl DefaultHashable for Output {}
|
||||||
hashable_ord!(Output);
|
hashable_ord!(Output);
|
||||||
|
|
||||||
|
impl AsRef<Commitment> for Output {
|
||||||
|
fn as_ref(&self) -> &Commitment {
|
||||||
|
&self.commit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ::std::hash::Hash for Output {
|
impl ::std::hash::Hash for Output {
|
||||||
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
|
||||||
let mut vec = Vec::new();
|
let mut vec = Vec::new();
|
||||||
|
|
Loading…
Reference in a new issue