tree state

This commit is contained in:
NikVolf 2018-12-28 17:17:18 +03:00
parent 899b499466
commit 1157929fd0
4 changed files with 196 additions and 9 deletions

2
Cargo.lock generated
View File

@ -1342,9 +1342,11 @@ name = "storage"
version = "0.1.0"
dependencies = [
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bitcrypto 0.1.0",
"chain 0.1.0",
"display_derive 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"primitives 0.1.0",

View File

@ -12,3 +12,5 @@ primitives = { path = "../primitives" }
serialization = { path = "../serialization" }
chain = { path = "../chain" }
display_derive = "0.0.0"
bitcrypto = { path = "../crypto" }
lazy_static = "*"

View File

@ -1,12 +1,193 @@
use EpochTag;
use hash::H256;
use crypto::sha256_compress;
/// Trait to query sequence of blockchain commitments;
pub trait CommitmentProvider : Sync {
/// Total amount of stored commitments
fn commitments_count(&self, tag: EpochTag) -> u64;
/// Commitment at given position
fn commitment_at(&self, tag: EpochTag, index: u64) -> H256;
/// Root of all stored commitments
fn commitments_merkle_root(&self, tag: EpochTag) -> H256;
lazy_static! {
static ref EMPTY_ROOTS: Vec<H256> = [
H256::from("0000000000000000000000000000000000000000000000000000000000000000"),
H256::from("da5698be17b9b46962335799779fbeca8ce5d491c0d26243bafef9ea1837a9d8"),
H256::from("dc766fab492ccf3d1e49d4f374b5235fa56506aac2224d39f943fcd49202974c"),
H256::from("3f0a406181105968fdaee30679e3273c66b72bf9a7f5debbf3b5a0a26e359f92"),
H256::from("26b0052694fc42fdff93e6fb5a71d38c3dd7dc5b6ad710eb048c660233137fab"),
H256::from("0109ecc0722659ff83450b8f7b8846e67b2859f33c30d9b7acd5bf39cae54e31"),
H256::from("3f909b8ce3d7ffd8a5b30908f605a03b0db85169558ddc1da7bbbcc9b09fd325"),
H256::from("40460fa6bc692a06f47521a6725a547c028a6a240d8409f165e63cb54da2d23f"),
H256::from("8c085674249b43da1b9a31a0e820e81e75f342807b03b6b9e64983217bc2b38e"),
H256::from("a083450c1ba2a3a7be76fad9d13bc37be4bf83bd3e59fc375a36ba62dc620298"),
H256::from("1ddddabc2caa2de9eff9e18c8c5a39406d7936e889bc16cfabb144f5c0022682"),
H256::from("c22d8f0b5e4056e5f318ba22091cc07db5694fbeb5e87ef0d7e2c57ca352359e"),
H256::from("89a434ae1febd7687eceea21d07f20a2512449d08ce2eee55871cdb9d46c1233"),
H256::from("7333dbffbd11f09247a2b33a013ec4c4342029d851e22ba485d4461851370c15"),
H256::from("5dad844ab9466b70f745137195ca221b48f346abd145fb5efc23a8b4ba508022"),
H256::from("507e0dae81cbfbe457fd370ef1ca4201c2b6401083ddab440e4a038dc1e358c4"),
H256::from("bdcdb3293188c9807d808267018684cfece07ac35a42c00f2c79b4003825305d"),
H256::from("bab5800972a16c2c22530c66066d0a5867e987bed21a6d5a450b683cf1cfd709"),
H256::from("11aa0b4ad29b13b057a31619d6500d636cd735cdd07d811ea265ec4bcbbbd058"),
H256::from("5145b1b055c2df02b95675e3797b91de1b846d25003c0a803d08900728f2cd6a"),
H256::from("0323f2850bf3444f4b4c5c09a6057ec7169190f45acb9e46984ab3dfcec4f06a"),
H256::from("671546e26b1da1af754531e26d8a6a51073a57ddd72dc472efb43fcb257cffff"),
H256::from("bb23a9bba56de57cb284b0d2b01c642cf79c9a5563f0067a21292412145bd78a"),
H256::from("f30cc836b9f71b4e7ee3c72b1fd253268af9a27e9d7291a23d02821b21ddfd16"),
H256::from("58a2753dade103cecbcda50b5ebfce31e12d41d5841dcc95620f7b3d50a1b9a1"),
H256::from("925e6d474a5d8d3004f29da0dd78d30ae3824ce79dfe4934bb29ec3afaf3d521"),
H256::from("08f279618616bcdd4eadc9c7a9062691a59b43b07e2c1e237f17bd189cd6a8fe"),
H256::from("c92b32db42f42e2bf0a59df9055be5c669d3242df45357659b75ae2c27a76f50"),
H256::from("c0db2a74998c50eb7ba6534f6d410efc27c4bb88acb0222c7906ea28a327b511"),
H256::from("d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259"),
H256::from("b22370106c67a17209f6130bc09f735d83aa2c04fc4fe72ea5d80b216723e7ce"),
H256::from("9f67d5f664664c901940eee3d02dd5b3e4b92e7b42820c42fc5159e91b41172a"),
H256::from("ac58cd1388fec290d398f1944b564449a63c815880566bd1d189f7839e3b0c8c"),
H256::from("5698eae7c8515ed05a70339bdf7c1028e7acca13a4fa97d9538f01ac8d889ae3"),
H256::from("2d4995770a76fb93314ca74b3524ea1db5688ad0a76183ea17204a8f024a9f3b"),
H256::from("5e8992c1b072c16e9e28a85358fb5fb6901a81587766dadb7aa0b973ded2f264"),
H256::from("e95db71e1f7291ba5499461bc715203e29b84bfa4283e3bb7f470a15d0e1584e"),
H256::from("41f078bd1824c8a4b71964f394aa595084d8eb17b97a3630433af70d10e0eff6"),
H256::from("a1913fe6b20132312f8c1f00ddd63cec7a03f5f1d7d83492fa284c0b5d6320b0"),
H256::from("ba9440c4dbfcf55ceb605a5b8990fc11f8ef22870d8d12e130f986491eae84b3"),
H256::from("49db2d5e22b8015cae4810d75e54014c5469862738e161ec96ec20218718828a"),
H256::from("d4851fb8431edfbb8b1e85ada6895967c2dac87df344992a05faf1ecf836eec9"),
H256::from("e4ab9f4470f00cd196d47c75c82e7adaf06fe17e042e3953d93bb5d56d8cd8fb"),
H256::from("7e4320434849ecb357f1afaaba21a54400ef2d11cff83b937d87fdafa49f8199"),
H256::from("020adc98d96cfbbcca15fc3aa03760ed286686c35b5d92c7cb64a999b394a854"),
H256::from("3a26b29fe1acfdd6c6a151bcc3dbcb95a10ebe2f0553f80779569b67b7244e77"),
H256::from("ec2d0986e6a0ddf43897b2d4f23bb034f538ffe00827f310dc4963f3267f0bfb"),
H256::from("d48073f8819f81f0358e3fc35a047cc74082ae1cb7ee22fb609c01649342d0e6"),
H256::from("ad8037601793f172441ecb00dc138d9fc5957125ecc382ec65e36f817dc799fb"),
H256::from("ca500a5441f36f4df673d6b8ed075d36dae2c7e6481428c70a5a76b7a9bebce8"),
H256::from("422b6ddd473231dc4d56fe913444ccd56f7c61f747ba57ca946d5fef72d840a0"),
H256::from("ab41f4ecb7d7089615800e19fcc53b8379ed05ee35c82567095583fd90ff3035"),
H256::from("bbf7618248354ceb1bc1fc9dbc42c426a4e2c1e0d443c5683a9256c62ecdc26f"),
H256::from("e50ae71479fc8ec569192a13072e011afc249f471af09500ea39f75d0af856bf"),
H256::from("e74c0b9220147db2d50a3b58d413775d16c984690be7d90f0bc43d99dba1b689"),
H256::from("29324a0a48d11657a51ba08b004879bfcfc66a1acb7ce36dfe478d2655484b48"),
H256::from("88952e3d0ac06cb16b665201122249659a22325e01c870f49e29da6b1757e082"),
H256::from("cdf879f2435b95af042a3bf7b850f7819246c805285803d67ffbf4f295bed004"),
H256::from("e005e324200b4f428c62bc3331e695c373607cd0faa9790341fa3ba1ed228bc5"),
H256::from("354447727aa9a53dd8345b6b6c693443e56ef4aeba13c410179fc8589e7733d5"),
H256::from("da52dda91f2829c15c0e58d29a95360b86ab30cf0cac8101832a29f38c3185f1"),
H256::from("c7da7814e228e1144411d78b536092fe920bcdfcc36cf19d1259047b267d58b5"),
H256::from("aba1f68b6c2b4db6cc06a7340e12313c4b4a4ea6deb17deb3e1e66cd8eacf32b"),
H256::from("c160ae4f64ab764d864a52ad5e33126c4b5ce105a47deedd75bc70199a5247ef"),
H256::from("eadf23fc99d514dd8ea204d223e98da988831f9b5d1940274ca520b7fb173d8a"),
H256::from("5b8e14facac8a7c7a3bfee8bae71f2f7793d3ad5fe3383f93ab6061f2a11bb02")
].to_vec();
}
struct TreeState {
height: u32,
left: Option<H256>,
right: Option<H256>,
parents: Vec<Option<H256>>,
}
impl TreeState {
fn new(height: u32) -> Self {
TreeState {
height: height,
left: None,
right: None,
parents: vec![None; height as usize],
}
}
fn append(&mut self, hash: H256) -> Result<(), &'static str> {
if self.left.is_none() {
self.left = Some(hash);
} else if self.right.is_none() {
self.right = Some(hash);
} else {
let former_left = ::std::mem::replace(&mut self.left, Some(hash))
.expect("none variant is handled in the branch above; qed");
let former_right = self.right.take()
.expect("none variant is handled in the branch above; qed");
let mut combined = sha256_compress(&*former_left, &*former_right);
for i in 0..self.height {
let parent_slot = self.parents.get_mut(i as usize)
.expect("Vector is at least self.height in size");
if parent_slot.is_none() {
*parent_slot = Some(combined);
break;
} else {
let former_parent_slot = parent_slot.take().expect("None variant checked above; qed");
combined = sha256_compress(&*former_parent_slot, &*combined);
}
}
return Err("Appending to full tree");
}
Ok(())
}
fn root(&self) -> H256 {
let left = self.left.as_ref().unwrap_or(&EMPTY_ROOTS[0]);
let right = self.right.as_ref().unwrap_or(&EMPTY_ROOTS[0]);
let mut root = sha256_compress(&**left, &**right);
for i in 1..self.height {
match &self.parents[i as usize] {
&None => { root = sha256_compress(&*root, &*EMPTY_ROOTS[i as usize]); },
&Some(ref parent) => { root = sha256_compress(&**parent, &*root); }
}
}
root
}
}
#[cfg(test)]
mod tests {
use super::*;
use EpochTag;
#[test]
fn single_root() {
let mut tree = TreeState::new(1);
tree.append(EMPTY_ROOTS[0].clone()).unwrap();
assert_eq!(
tree.root(),
H256::from("da5698be17b9b46962335799779fbeca8ce5d491c0d26243bafef9ea1837a9d8")
);
}
#[test]
fn single_elem_in_double_tree() {
let mut tree = TreeState::new(2);
tree.append(EMPTY_ROOTS[0].clone()).unwrap();
assert_eq!(
tree.root(),
H256::from("dc766fab492ccf3d1e49d4f374b5235fa56506aac2224d39f943fcd49202974c")
);
}
#[test]
fn commitment_1() {
let mut tree = TreeState::new(4);
tree.append(H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62"))
.unwrap();
assert_eq!(
tree.root(),
H256::from("95bf71d8e803b8601c14b5949d0f92690181154ef9d82eb3e24852266823317a")
);
}
#[test]
fn commitment_2() {
let mut tree = TreeState::new(4);
tree.append(H256::from_reversed_str("bab6e8992959caf0ca94847c36b4e648a7f88a9b9c6a62ea387cf1fb9badfd62"))
.unwrap();
tree.append(H256::from_reversed_str("43c9a4b21555b832a79fc12ce27a97d4f4eca1638e7161a780db1d5ebc35eb68"))
.unwrap();
assert_eq!(
tree.root(),
H256::from("73f18d3f9cd11010aa01d4f444039e566f14ef282109df9649b2eb75e7a53ed1")
);
}
}

View File

@ -8,6 +8,8 @@ extern crate display_derive;
extern crate primitives;
extern crate serialization as ser;
extern crate chain;
extern crate bitcrypto as crypto;
#[macro_use] extern crate lazy_static;
mod best_block;
mod block_ancestors;