Order block elements when block is built

This commit is contained in:
Ignotus Peverell 2017-11-01 22:18:51 -04:00
parent 5b462ee2fc
commit dbaba8aed5
No known key found for this signature in database
GPG key ID: 99CD25F39F8F8211
2 changed files with 45 additions and 11 deletions

View file

@ -293,7 +293,7 @@ impl Block {
// build vectors with all inputs and all outputs, ordering them by hash
// needs to be a fold so we don't end up with a vector of vectors and we
// want to fully own the refs (not just a pointer like flat_map).
let inputs = txs.iter().fold(vec![], |mut acc, ref tx| {
let mut inputs = txs.iter().fold(vec![], |mut acc, ref tx| {
let mut inputs = tx.inputs.clone();
acc.append(&mut inputs);
acc
@ -305,6 +305,10 @@ impl Block {
});
outputs.push(reward_out);
inputs.sort();
outputs.sort();
kernels.sort();
// calculate the overall Merkle tree and fees
Ok(

View file

@ -16,11 +16,13 @@
use byteorder::{BigEndian, ByteOrder};
use blake2::blake2b::blake2b;
use util::secp::{self, Secp256k1, Message, Signature};
use util::secp::pedersen::{RangeProof, Commitment};
use util::secp::{self, Message, Secp256k1, Signature};
use util::secp::pedersen::{Commitment, RangeProof};
use std::cmp::Ordering;
use std::ops;
use core::Committed;
use core::hash::Hashed;
use core::pmmr::Summable;
use keychain::{Identifier, Keychain};
use ser::{self, read_and_verify_sorted, Readable, Reader, Writeable, WriteableSorted, Writer};
@ -39,6 +41,29 @@ bitflags! {
}
}
// don't seem to be able to define an Ord implementation for Hash due to
// Ord being defined on all pointers, resorting to a macro instead
macro_rules! hashable_ord {
($hashable: ident) => {
impl Ord for $hashable {
fn cmp(&self, other: &$hashable) -> Ordering {
self.hash().cmp(&other.hash())
}
}
impl PartialOrd for $hashable {
fn partial_cmp(&self, other: &$hashable) -> Option<Ordering> {
Some(self.hash().cmp(&other.hash()))
}
}
impl PartialEq for $hashable {
fn eq(&self, other: &$hashable) -> bool {
self.hash() == other.hash()
}
}
impl Eq for $hashable {}
}
}
/// Errors thrown by Block validation
#[derive(Debug, PartialEq)]
pub enum Error {
@ -68,7 +93,7 @@ pub fn kernel_sig_msg(fee: u64, lock_height: u64) -> [u8; 32] {
/// amount to zero.
/// The signature signs the fee and the lock_height, which are retained for
/// signature validation.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub struct TxKernel {
/// Options for a kernel's structure or use
pub features: KernelFeatures,
@ -86,6 +111,8 @@ pub struct TxKernel {
pub excess_sig: Vec<u8>,
}
hashable_ord!(TxKernel);
impl Writeable for TxKernel {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
ser_multiwrite!(
@ -169,7 +196,6 @@ impl Writeable for Transaction {
}
}
/// Implementation of Readable for a transaction, defines how to read a full
/// transaction from a binary stream.
impl Readable for Transaction {
@ -327,9 +353,11 @@ impl Transaction {
/// A transaction input, mostly a reference to an output being spent by the
/// transaction.
#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone)]
pub struct Input(pub Commitment);
hashable_ord!(Input);
/// Implementation of Writeable for a transaction Input, defines how to write
/// an Input as binary.
impl Writeable for Input {
@ -423,7 +451,7 @@ impl SwitchCommitHash {
/// The hash of an output only covers its features, lock_height, commitment,
/// and switch commitment. The range proof is expected to have its own hash
/// and is stored and committed to separately.
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Output {
/// Options for an output's structure or use
pub features: OutputFeatures,
@ -435,6 +463,8 @@ pub struct Output {
pub proof: RangeProof,
}
hashable_ord!(Output);
/// Implementation of Writeable for a transaction Output, defines how to write
/// an Output as binary.
impl Writeable for Output {
@ -672,8 +702,8 @@ mod test {
}
#[test]
fn commit_consistency(){
let keychain = Keychain::from_seed(&[0;32]).unwrap();
fn commit_consistency() {
let keychain = Keychain::from_seed(&[0; 32]).unwrap();
let key_id = keychain.derive_key_id(1).unwrap();
let commit = keychain.commit(1003, &key_id).unwrap();
@ -687,7 +717,7 @@ mod test {
println!("Switch commit 2: {:?}", switch_commit_2);
println!("commit2 : {:?}", commit_2);
assert!(commit==commit_2);
assert!(switch_commit==switch_commit_2);
assert!(commit == commit_2);
assert!(switch_commit == switch_commit_2);
}
}