diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 7640cd9fde..b682522cd2 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -545,12 +545,12 @@ impl Chain { pipe::rewind_and_apply_fork(&previous_header, &header_head, extension)?; // Retrieve the header root before we apply the new block - let prev_root = extension.header_root(); + let prev_root = extension.header_root()?; // Apply the latest block to the chain state via the extension. extension.apply_block(b)?; - Ok((prev_root, extension.roots(), extension.sizes())) + Ok((prev_root, extension.roots()?, extension.sizes())) })?; // Set the prev_root on the header. diff --git a/chain/src/txhashset/txhashset.rs b/chain/src/txhashset/txhashset.rs index 473f00a011..f43497e01d 100644 --- a/chain/src/txhashset/txhashset.rs +++ b/chain/src/txhashset/txhashset.rs @@ -670,7 +670,7 @@ impl<'a> HeaderExtension<'a> { pub fn apply_header(&mut self, header: &BlockHeader) -> Result { self.pmmr.push(header).map_err(&ErrorKind::TxHashSetErr)?; self.head = Tip::from_header(header); - Ok(self.root()) + Ok(self.root()?) } /// Rewind the header extension to the specified header. @@ -749,8 +749,8 @@ impl<'a> HeaderExtension<'a> { } /// The root of the header MMR for convenience. - pub fn root(&self) -> Hash { - self.pmmr.root() + pub fn root(&self) -> Result { + Ok(self.pmmr.root().map_err(|_| ErrorKind::InvalidRoot)?) } /// Validate the prev_root of the header against the root of the current header MMR. @@ -760,7 +760,7 @@ impl<'a> HeaderExtension<'a> { if header.height == 0 { return Ok(()); } - if self.root() != header.prev_root { + if self.root()? != header.prev_root { Err(ErrorKind::InvalidRoot.into()) } else { Ok(()) @@ -1095,18 +1095,33 @@ impl<'a> Extension<'a> { /// Current root hashes and sums (if applicable) for the Output, range proof /// and kernel sum trees. - pub fn roots(&self) -> TxHashSetRoots { - TxHashSetRoots { - header_root: self.header_pmmr.root(), - output_root: self.output_pmmr.root(), - rproof_root: self.rproof_pmmr.root(), - kernel_root: self.kernel_pmmr.root(), - } + pub fn roots(&self) -> Result { + Ok(TxHashSetRoots { + header_root: self + .header_pmmr + .root() + .map_err(|_| ErrorKind::InvalidRoot)?, + output_root: self + .output_pmmr + .root() + .map_err(|_| ErrorKind::InvalidRoot)?, + rproof_root: self + .rproof_pmmr + .root() + .map_err(|_| ErrorKind::InvalidRoot)?, + kernel_root: self + .kernel_pmmr + .root() + .map_err(|_| ErrorKind::InvalidRoot)?, + }) } /// Get the root of the current header MMR. - pub fn header_root(&self) -> Hash { - self.header_pmmr.root() + pub fn header_root(&self) -> Result { + Ok(self + .header_pmmr + .root() + .map_err(|_| ErrorKind::InvalidRoot)?) } /// Validate the following MMR roots against the latest header applied - @@ -1126,7 +1141,7 @@ impl<'a> Extension<'a> { return Ok(()); } let head_header = self.batch.get_block_header(&self.head.last_block_h)?; - let roots = self.roots(); + let roots = self.roots()?; if roots.output_root != head_header.output_root || roots.rproof_root != head_header.range_proof_root || roots.kernel_root != head_header.kernel_root @@ -1143,7 +1158,7 @@ impl<'a> Extension<'a> { if header.height == 0 { return Ok(()); } - let roots = self.roots(); + let roots = self.roots()?; if roots.header_root != header.prev_root { Err(ErrorKind::InvalidRoot.into()) } else { diff --git a/core/src/core/pmmr/pmmr.rs b/core/src/core/pmmr/pmmr.rs index c57c39d67b..6e19addf2d 100644 --- a/core/src/core/pmmr/pmmr.rs +++ b/core/src/core/pmmr/pmmr.rs @@ -129,9 +129,9 @@ where /// Computes the root of the MMR. Find all the peaks in the current /// tree and "bags" them to get a single peak. - pub fn root(&self) -> Hash { + pub fn root(&self) -> Result { if self.is_empty() { - return ZERO_HASH; + return Ok(ZERO_HASH); } let mut res = None; for peak in self.peaks().iter().rev() { @@ -140,7 +140,7 @@ where Some(rhash) => Some((*peak, rhash).hash_with_index(self.unpruned_size())), } } - res.expect("no root, invalid tree") + res.ok_or_else(|| "no root, invalid tree".to_owned()) } /// Build a Merkle proof for the element at the given position. diff --git a/core/tests/merkle_proof.rs b/core/tests/merkle_proof.rs index f254973989..f750a6eac3 100644 --- a/core/tests/merkle_proof.rs +++ b/core/tests/merkle_proof.rs @@ -81,7 +81,7 @@ fn pmmr_merkle_proof() { let proof = pmmr.merkle_proof(1).unwrap(); assert_eq!(proof.path, vec![]); - assert!(proof.verify(pmmr.root(), &elems[0], 1).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[0], 1).is_ok()); pmmr.push(&elems[1]).unwrap(); let pos_1 = elems[1].hash_with_index(1); @@ -89,37 +89,37 @@ fn pmmr_merkle_proof() { let pos_2 = (pos_0, pos_1).hash_with_index(2); assert_eq!(pmmr.get_hash(3).unwrap(), pos_2); - assert_eq!(pmmr.root(), pos_2); + assert_eq!(pmmr.root().unwrap(), pos_2); assert_eq!(pmmr.peaks(), [pos_2]); // single peak, path with single sibling let proof = pmmr.merkle_proof(1).unwrap(); assert_eq!(proof.path, vec![pos_1]); - assert!(proof.verify(pmmr.root(), &elems[0], 1).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[0], 1).is_ok()); let proof = pmmr.merkle_proof(2).unwrap(); assert_eq!(proof.path, vec![pos_0]); - assert!(proof.verify(pmmr.root(), &elems[1], 2).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[1], 2).is_ok()); // three leaves, two peaks (one also the right-most leaf) pmmr.push(&elems[2]).unwrap(); let pos_3 = elems[2].hash_with_index(3); assert_eq!(pmmr.get_hash(4).unwrap(), pos_3); - assert_eq!(pmmr.root(), (pos_2, pos_3).hash_with_index(4)); + assert_eq!(pmmr.root().unwrap(), (pos_2, pos_3).hash_with_index(4)); assert_eq!(pmmr.peaks(), [pos_2, pos_3]); let proof = pmmr.merkle_proof(1).unwrap(); assert_eq!(proof.path, vec![pos_1, pos_3]); - assert!(proof.verify(pmmr.root(), &elems[0], 1).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[0], 1).is_ok()); let proof = pmmr.merkle_proof(2).unwrap(); assert_eq!(proof.path, vec![pos_0, pos_3]); - assert!(proof.verify(pmmr.root(), &elems[1], 2).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[1], 2).is_ok()); let proof = pmmr.merkle_proof(4).unwrap(); assert_eq!(proof.path, vec![pos_2]); - assert!(proof.verify(pmmr.root(), &elems[2], 4).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[2], 4).is_ok()); // 7 leaves, 3 peaks, 11 pos in total pmmr.push(&elems[3]).unwrap(); @@ -152,38 +152,38 @@ fn pmmr_merkle_proof() { proof.path, vec![pos_1, pos_5, (pos_9, pos_10).hash_with_index(11)] ); - assert!(proof.verify(pmmr.root(), &elems[0], 1).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[0], 1).is_ok()); let proof = pmmr.merkle_proof(2).unwrap(); assert_eq!( proof.path, vec![pos_0, pos_5, (pos_9, pos_10).hash_with_index(11)] ); - assert!(proof.verify(pmmr.root(), &elems[1], 2).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[1], 2).is_ok()); let proof = pmmr.merkle_proof(4).unwrap(); assert_eq!( proof.path, vec![pos_4, pos_2, (pos_9, pos_10).hash_with_index(11)] ); - assert!(proof.verify(pmmr.root(), &elems[2], 4).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[2], 4).is_ok()); let proof = pmmr.merkle_proof(5).unwrap(); assert_eq!( proof.path, vec![pos_3, pos_2, (pos_9, pos_10).hash_with_index(11)] ); - assert!(proof.verify(pmmr.root(), &elems[3], 5).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[3], 5).is_ok()); let proof = pmmr.merkle_proof(8).unwrap(); assert_eq!(proof.path, vec![pos_8, pos_10, pos_6]); - assert!(proof.verify(pmmr.root(), &elems[4], 8).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[4], 8).is_ok()); let proof = pmmr.merkle_proof(9).unwrap(); assert_eq!(proof.path, vec![pos_7, pos_10, pos_6]); - assert!(proof.verify(pmmr.root(), &elems[5], 9).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[5], 9).is_ok()); let proof = pmmr.merkle_proof(11).unwrap(); assert_eq!(proof.path, vec![pos_9, pos_6]); - assert!(proof.verify(pmmr.root(), &elems[6], 11).is_ok()); + assert!(proof.verify(pmmr.root().unwrap(), &elems[6], 11).is_ok()); } diff --git a/core/tests/pmmr.rs b/core/tests/pmmr.rs index 2606cddfd3..e122a18659 100644 --- a/core/tests/pmmr.rs +++ b/core/tests/pmmr.rs @@ -280,7 +280,7 @@ fn pmmr_push_root() { pmmr.dump(false); let pos_0 = elems[0].hash_with_index(0); assert_eq!(pmmr.peaks(), vec![pos_0]); - assert_eq!(pmmr.root(), pos_0); + assert_eq!(pmmr.root().unwrap(), pos_0); assert_eq!(pmmr.unpruned_size(), 1); // two elements @@ -289,7 +289,7 @@ fn pmmr_push_root() { let pos_1 = elems[1].hash_with_index(1); let pos_2 = (pos_0, pos_1).hash_with_index(2); assert_eq!(pmmr.peaks(), vec![pos_2]); - assert_eq!(pmmr.root(), pos_2); + assert_eq!(pmmr.root().unwrap(), pos_2); assert_eq!(pmmr.unpruned_size(), 3); // three elements @@ -297,7 +297,7 @@ fn pmmr_push_root() { pmmr.dump(false); let pos_3 = elems[2].hash_with_index(3); assert_eq!(pmmr.peaks(), vec![pos_2, pos_3]); - assert_eq!(pmmr.root(), (pos_2, pos_3).hash_with_index(4)); + assert_eq!(pmmr.root().unwrap(), (pos_2, pos_3).hash_with_index(4)); assert_eq!(pmmr.unpruned_size(), 4); // four elements @@ -307,7 +307,7 @@ fn pmmr_push_root() { let pos_5 = (pos_3, pos_4).hash_with_index(5); let pos_6 = (pos_2, pos_5).hash_with_index(6); assert_eq!(pmmr.peaks(), vec![pos_6]); - assert_eq!(pmmr.root(), pos_6); + assert_eq!(pmmr.root().unwrap(), pos_6); assert_eq!(pmmr.unpruned_size(), 7); // five elements @@ -315,7 +315,7 @@ fn pmmr_push_root() { pmmr.dump(false); let pos_7 = elems[4].hash_with_index(7); assert_eq!(pmmr.peaks(), vec![pos_6, pos_7]); - assert_eq!(pmmr.root(), (pos_6, pos_7).hash_with_index(8)); + assert_eq!(pmmr.root().unwrap(), (pos_6, pos_7).hash_with_index(8)); assert_eq!(pmmr.unpruned_size(), 8); // six elements @@ -323,7 +323,7 @@ fn pmmr_push_root() { let pos_8 = elems[5].hash_with_index(8); let pos_9 = (pos_7, pos_8).hash_with_index(9); assert_eq!(pmmr.peaks(), vec![pos_6, pos_9]); - assert_eq!(pmmr.root(), (pos_6, pos_9).hash_with_index(10)); + assert_eq!(pmmr.root().unwrap(), (pos_6, pos_9).hash_with_index(10)); assert_eq!(pmmr.unpruned_size(), 10); // seven elements @@ -331,7 +331,7 @@ fn pmmr_push_root() { let pos_10 = elems[6].hash_with_index(10); assert_eq!(pmmr.peaks(), vec![pos_6, pos_9, pos_10]); assert_eq!( - pmmr.root(), + pmmr.root().unwrap(), (pos_6, (pos_9, pos_10).hash_with_index(11)).hash_with_index(11) ); assert_eq!(pmmr.unpruned_size(), 11); @@ -344,14 +344,14 @@ fn pmmr_push_root() { let pos_13 = (pos_9, pos_12).hash_with_index(13); let pos_14 = (pos_6, pos_13).hash_with_index(14); assert_eq!(pmmr.peaks(), vec![pos_14]); - assert_eq!(pmmr.root(), pos_14); + assert_eq!(pmmr.root().unwrap(), pos_14); assert_eq!(pmmr.unpruned_size(), 15); // nine elements pmmr.push(&elems[8]).unwrap(); let pos_15 = elems[8].hash_with_index(15); assert_eq!(pmmr.peaks(), vec![pos_14, pos_15]); - assert_eq!(pmmr.root(), (pos_14, pos_15).hash_with_index(16)); + assert_eq!(pmmr.root().unwrap(), (pos_14, pos_15).hash_with_index(16)); assert_eq!(pmmr.unpruned_size(), 16); } @@ -427,7 +427,7 @@ fn pmmr_prune() { for elem in &elems[..] { pmmr.push(elem).unwrap(); } - orig_root = pmmr.root(); + orig_root = pmmr.root().unwrap(); sz = pmmr.unpruned_size(); } @@ -439,7 +439,7 @@ fn pmmr_prune() { { let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz); pmmr.prune(16).unwrap(); - assert_eq!(orig_root, pmmr.root()); + assert_eq!(orig_root, pmmr.root().unwrap()); } assert_eq!(ba.hashes.len(), 16); assert_eq!(ba.remove_list.len(), 1); @@ -448,7 +448,7 @@ fn pmmr_prune() { { let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz); pmmr.prune(2).unwrap(); - assert_eq!(orig_root, pmmr.root()); + assert_eq!(orig_root, pmmr.root().unwrap()); } assert_eq!(ba.hashes.len(), 16); assert_eq!(ba.remove_list.len(), 2); @@ -456,7 +456,7 @@ fn pmmr_prune() { { let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz); pmmr.prune(4).unwrap(); - assert_eq!(orig_root, pmmr.root()); + assert_eq!(orig_root, pmmr.root().unwrap()); } assert_eq!(ba.hashes.len(), 16); assert_eq!(ba.remove_list.len(), 3); @@ -465,7 +465,7 @@ fn pmmr_prune() { { let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz); pmmr.prune(3).unwrap_err(); - assert_eq!(orig_root, pmmr.root()); + assert_eq!(orig_root, pmmr.root().unwrap()); } assert_eq!(ba.hashes.len(), 16); assert_eq!(ba.remove_list.len(), 3); @@ -474,7 +474,7 @@ fn pmmr_prune() { { let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz); pmmr.prune(5).unwrap(); - assert_eq!(orig_root, pmmr.root()); + assert_eq!(orig_root, pmmr.root().unwrap()); } assert_eq!(ba.hashes.len(), 16); assert_eq!(ba.remove_list.len(), 4); @@ -484,7 +484,7 @@ fn pmmr_prune() { { let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut ba, sz); pmmr.prune(1).unwrap(); - assert_eq!(orig_root, pmmr.root()); + assert_eq!(orig_root, pmmr.root().unwrap()); } assert_eq!(ba.hashes.len(), 16); assert_eq!(ba.remove_list.len(), 5); @@ -495,7 +495,7 @@ fn pmmr_prune() { for n in 1..16 { let _ = pmmr.prune(n); } - assert_eq!(orig_root, pmmr.root()); + assert_eq!(orig_root, pmmr.root().unwrap()); } assert_eq!(ba.hashes.len(), 16); assert_eq!(ba.remove_list.len(), 9); diff --git a/store/tests/pmmr.rs b/store/tests/pmmr.rs index e70717c658..6d0a1c88ba 100644 --- a/store/tests/pmmr.rs +++ b/store/tests/pmmr.rs @@ -101,7 +101,7 @@ fn pmmr_append() { { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(pmmr.root(), (pos_14, pos_15).hash_with_index(16)); + assert_eq!(pmmr.root().unwrap(), (pos_14, pos_15).hash_with_index(16)); } } @@ -195,7 +195,7 @@ fn pmmr_prune_compact() { // save the root let root = { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.root() + pmmr.root().unwrap() }; // pruning some choice nodes @@ -210,7 +210,7 @@ fn pmmr_prune_compact() { // check the root and stored data { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); + assert_eq!(root, pmmr.root().unwrap()); // check we can still retrieve same element from leaf index 2 assert_eq!(pmmr.get_data(2).unwrap(), TestElem(2)); // and the same for leaf index 7 @@ -223,7 +223,7 @@ fn pmmr_prune_compact() { // recheck the root and stored data { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); + assert_eq!(root, pmmr.root().unwrap()); assert_eq!(pmmr.get_data(2).unwrap(), TestElem(2)); assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); } @@ -251,7 +251,7 @@ fn pmmr_reload() { // save the root let root = { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.root() + pmmr.root().unwrap() }; { @@ -303,7 +303,7 @@ fn pmmr_reload() { assert_eq!(backend.unpruned_size(), mmr_size); { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); + assert_eq!(root, pmmr.root().unwrap()); } // pos 1 and pos 2 are both removed (via parent pos 3 in prune list) @@ -347,7 +347,7 @@ fn pmmr_rewind() { backend.sync().unwrap(); let root1 = { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.root() + pmmr.root().unwrap() }; mmr_size = load(mmr_size, &elems[4..6], &mut backend); @@ -355,7 +355,7 @@ fn pmmr_rewind() { let root2 = { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); assert_eq!(pmmr.unpruned_size(), 10); - pmmr.root() + pmmr.root().unwrap() }; mmr_size = load(mmr_size, &elems[6..9], &mut backend); @@ -363,7 +363,7 @@ fn pmmr_rewind() { let root3 = { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); assert_eq!(pmmr.unpruned_size(), 16); - pmmr.root() + pmmr.root().unwrap() }; // prune the first 4 elements (leaves at pos 1, 2, 4, 5) @@ -388,14 +388,14 @@ fn pmmr_rewind() { pmmr.rewind(9, &Bitmap::of(&vec![11, 12, 16])).unwrap(); assert_eq!(pmmr.unpruned_size(), 10); - assert_eq!(pmmr.root(), root2); + assert_eq!(pmmr.root().unwrap(), root2); } backend.sync().unwrap(); { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 10); - assert_eq!(pmmr.root(), root2); + assert_eq!(pmmr.root().unwrap(), root2); } // Also check the data file looks correct. @@ -423,13 +423,13 @@ fn pmmr_rewind() { { let mut pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 10); pmmr.rewind(5, &Bitmap::create()).unwrap(); - assert_eq!(pmmr.root(), root1); + assert_eq!(pmmr.root().unwrap(), root1); } backend.sync().unwrap(); { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, 7); - assert_eq!(pmmr.root(), root1); + assert_eq!(pmmr.root().unwrap(), root1); } // also check the data file looks correct @@ -699,7 +699,7 @@ fn compact_twice() { // save the root let root = { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - pmmr.root() + pmmr.root().unwrap() }; // pruning some choice nodes @@ -714,7 +714,7 @@ fn compact_twice() { // check the root and stored data { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); + assert_eq!(root, pmmr.root().unwrap()); assert_eq!(pmmr.get_data(5).unwrap(), TestElem(4)); assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); } @@ -725,7 +725,7 @@ fn compact_twice() { // recheck the root and stored data { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); + assert_eq!(root, pmmr.root().unwrap()); assert_eq!(pmmr.get_data(5).unwrap(), TestElem(4)); assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); } @@ -742,7 +742,7 @@ fn compact_twice() { // recheck the root and stored data { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); + assert_eq!(root, pmmr.root().unwrap()); assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); } @@ -752,7 +752,7 @@ fn compact_twice() { // recheck the root and stored data { let pmmr: PMMR<'_, TestElem, _> = PMMR::at(&mut backend, mmr_size); - assert_eq!(root, pmmr.root()); + assert_eq!(root, pmmr.root().unwrap()); assert_eq!(pmmr.get_data(11).unwrap(), TestElem(7)); } }