acec59e249
* introduce rewindable_kernel_view cleanup header in extension * cleanup and docs/comments * txhashset does not need to be mutable here * pull validate_kernel_history out into fn
81 lines
2.5 KiB
Rust
81 lines
2.5 KiB
Rust
// Copyright 2018 The Grin Developers
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//! Lightweight readonly view into kernel MMR for convenience.
|
|
|
|
use core::core::pmmr::RewindablePMMR;
|
|
use core::core::{BlockHeader, TxKernel};
|
|
|
|
use error::{Error, ErrorKind};
|
|
use grin_store::pmmr::PMMRBackend;
|
|
use store::Batch;
|
|
|
|
/// Rewindable (but readonly) view of the kernel set (based on kernel MMR).
|
|
pub struct RewindableKernelView<'a> {
|
|
pmmr: RewindablePMMR<'a, TxKernel, PMMRBackend<TxKernel>>,
|
|
batch: &'a Batch<'a>,
|
|
header: BlockHeader,
|
|
}
|
|
|
|
impl<'a> RewindableKernelView<'a> {
|
|
/// Build a new readonly kernel view.
|
|
pub fn new(
|
|
pmmr: RewindablePMMR<'a, TxKernel, PMMRBackend<TxKernel>>,
|
|
batch: &'a Batch,
|
|
header: BlockHeader,
|
|
) -> RewindableKernelView<'a> {
|
|
RewindableKernelView {
|
|
pmmr,
|
|
batch,
|
|
header,
|
|
}
|
|
}
|
|
|
|
/// Accessor for the batch used in this view.
|
|
/// We will discard this batch (rollback) at the end, so be aware of this.
|
|
/// Nothing will get written to the db/index via this view.
|
|
pub fn batch(&self) -> &'a Batch {
|
|
self.batch
|
|
}
|
|
|
|
/// Rewind this readonly view to a previous block.
|
|
/// We accomplish this in a readonly way because we can rewind the PMMR
|
|
/// via last_pos, without rewinding the underlying backend files.
|
|
pub fn rewind(&mut self, header: &BlockHeader) -> Result<(), Error> {
|
|
self.pmmr
|
|
.rewind(header.kernel_mmr_size)
|
|
.map_err(&ErrorKind::TxHashSetErr)?;
|
|
|
|
// Update our header to reflect the one we rewound to.
|
|
self.header = header.clone();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Special handling to make sure the whole kernel set matches each of its
|
|
/// roots in each block header, without truncation. We go back header by
|
|
/// header, rewind and check each root. This fixes a potential weakness in
|
|
/// fast sync where a reorg past the horizon could allow a whole rewrite of
|
|
/// the kernel set.
|
|
pub fn validate_root(&self) -> Result<(), Error> {
|
|
if self.pmmr.root() != self.header.kernel_root {
|
|
return Err(ErrorKind::InvalidTxHashSet(format!(
|
|
"Kernel root at {} does not match",
|
|
self.header.height
|
|
)).into());
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|