Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "elements"
version = "0.10.0"
version = "0.10.1"
authors = ["Andrew Poelstra <apoelstra@blockstream.com>"]
description = "Library with support for de/serialization, parsing and executing on data structures and network messages related to Elements"
license = "CC0-1.0"
Expand Down
83 changes: 74 additions & 9 deletions src/dynafed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,26 @@ impl Params {
}
}

/// Calculate the root of this [Params].
pub fn calculate_root(&self) -> sha256::Midstate {
/// Get the elided_root. Is [None] for non-[Compact] params.
pub fn elided_root(&self) -> Option<&sha256::Midstate> {
match *self {
Params::Null => None,
Params::Compact { ref elided_root, ..} => Some(elided_root),
Params::Full { .. } => None,
}
}

/// Return the `extra root` of this params.
/// The extra root commits to the consensus parameters unrelated to
/// blocksigning: `fedpeg_program`, `fedpegscript` and `extension_space`.
fn extra_root(&self) -> sha256::Midstate {
fn serialize_hash<E: Encodable>(obj: &E) -> sha256d::Hash {
let mut engine = sha256d::Hash::engine();
obj.consensus_encode(&mut engine).expect("engines don't error");
sha256d::Hash::from_engine(engine)
}

if self.is_null() {
return sha256::Midstate::from_inner([0u8; 32]);
}

let extra_root = match *self {
match *self {
Params::Null => return sha256::Midstate::from_inner([0u8; 32]),
Params::Compact { ref elided_root, .. } => *elided_root,
Params::Full { ref fedpeg_program, ref fedpegscript, ref extension_space, .. } => {
Expand All @@ -152,7 +159,21 @@ impl Params {
];
::fast_merkle_root::fast_merkle_root(&leaves[..])
},
};
}
}

/// Calculate the root of this [Params].
pub fn calculate_root(&self) -> sha256::Midstate {
fn serialize_hash<E: Encodable>(obj: &E) -> sha256d::Hash {
let mut engine = sha256d::Hash::engine();
obj.consensus_encode(&mut engine).expect("engines don't error");
sha256d::Hash::from_engine(engine)
}

if self.is_null() {
return sha256::Midstate::from_inner([0u8; 32]);
}

let leaves = [
serialize_hash(self.signblockscript().unwrap()).into_inner(),
serialize_hash(&self.signblock_witness_limit().unwrap()).into_inner(),
Expand All @@ -161,10 +182,38 @@ impl Params {

let leaves = [
compact_root.into_inner(),
extra_root.into_inner(),
self.extra_root().into_inner(),
];
::fast_merkle_root::fast_merkle_root(&leaves[..])
}

/// Turns paramers into compact parameters.
/// This returns self for compact params and [None] for null ones.
pub fn into_compact(self) -> Option<Params> {
// Avoid calcualting when it's not needed.
let mut extra_root = None;
if self.is_full() {
extra_root = Some(self.extra_root());
}

match self {
Params::Null => None,
Params::Compact { signblockscript, signblock_witness_limit, elided_root } => {
Some(Params::Compact {
signblockscript: signblockscript,
signblock_witness_limit,
elided_root: elided_root,
})
}
Params::Full { signblockscript, signblock_witness_limit, ..} => {
Some(Params::Compact {
signblockscript: signblockscript,
signblock_witness_limit,
elided_root: extra_root.unwrap(),
})
}
}
}
}

#[cfg(feature = "serde")]
Expand Down Expand Up @@ -480,4 +529,20 @@ mod tests {
"113160f76dc17fe367a2def79aefe06feeea9c795310c9e88aeedc23e145982e"
);
}

#[test]
fn into_compact_test() {
let full = Params::Full {
signblockscript: vec![0x01, 0x02].into(),
signblock_witness_limit: 3,
fedpeg_program: vec![0x04, 0x05].into(),
fedpegscript: vec![0x06, 0x07],
extension_space: vec![vec![0x08, 0x09], vec![0x0a]],
};
let extra_root = full.extra_root();

let compact = full.into_compact().unwrap();
assert_eq!(compact.elided_root(), Some(&extra_root));
assert_eq!(compact.extra_root(), extra_root);
}
}