mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
Optimizing the code and making it more idiomatic (#2269)
This commit is contained in:
parent
23df6fa976
commit
f2a29ce37a
17 changed files with 119 additions and 104 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -5,10 +5,11 @@ node*
|
||||||
!node_clients
|
!node_clients
|
||||||
!node_clients.rs
|
!node_clients.rs
|
||||||
target
|
target
|
||||||
Cargo.lock
|
*/Cargo.lock
|
||||||
*.iml
|
*.iml
|
||||||
grin.log
|
grin.log
|
||||||
wallet.seed
|
wallet.seed
|
||||||
test_output
|
test_output
|
||||||
wallet_data
|
wallet_data
|
||||||
wallet/db
|
wallet/db
|
||||||
|
.idea/
|
||||||
|
|
|
@ -270,7 +270,7 @@ impl<'a> Batch<'a> {
|
||||||
fn save_block_input_bitmap(&self, bh: &Hash, bm: &Bitmap) -> Result<(), Error> {
|
fn save_block_input_bitmap(&self, bh: &Hash, bm: &Bitmap) -> Result<(), Error> {
|
||||||
self.db.put(
|
self.db.put(
|
||||||
&to_key(BLOCK_INPUT_BITMAP_PREFIX, &mut bh.to_vec())[..],
|
&to_key(BLOCK_INPUT_BITMAP_PREFIX, &mut bh.to_vec())[..],
|
||||||
bm.serialize(),
|
&bm.serialize(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -309,19 +309,13 @@ where
|
||||||
|
|
||||||
/// Count, in units of 1/100 (a percent), the number of "secondary" (AR) blocks in the provided window of blocks.
|
/// Count, in units of 1/100 (a percent), the number of "secondary" (AR) blocks in the provided window of blocks.
|
||||||
pub fn ar_count(_height: u64, diff_data: &[HeaderInfo]) -> u64 {
|
pub fn ar_count(_height: u64, diff_data: &[HeaderInfo]) -> u64 {
|
||||||
100 * diff_data
|
100 * diff_data.iter().filter(|n| n.is_secondary).count() as u64
|
||||||
.iter()
|
|
||||||
.filter(|n| n.is_secondary)
|
|
||||||
.count() as u64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Factor by which the secondary proof of work difficulty will be adjusted
|
/// Factor by which the secondary proof of work difficulty will be adjusted
|
||||||
pub fn secondary_pow_scaling(height: u64, diff_data: &[HeaderInfo]) -> u32 {
|
pub fn secondary_pow_scaling(height: u64, diff_data: &[HeaderInfo]) -> u32 {
|
||||||
// Get the scaling factor sum of the last DIFFICULTY_ADJUST_WINDOW elements
|
// Get the scaling factor sum of the last DIFFICULTY_ADJUST_WINDOW elements
|
||||||
let scale_sum: u64 = diff_data
|
let scale_sum: u64 = diff_data.iter().map(|dd| dd.secondary_scaling as u64).sum();
|
||||||
.iter()
|
|
||||||
.map(|dd| dd.secondary_scaling as u64)
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
// compute ideal 2nd_pow_fraction in pct and across window
|
// compute ideal 2nd_pow_fraction in pct and across window
|
||||||
let target_pct = secondary_pow_ratio(height);
|
let target_pct = secondary_pow_ratio(height);
|
||||||
|
|
|
@ -27,10 +27,7 @@ use crate::core::committed::{self, Committed};
|
||||||
use crate::core::compact_block::{CompactBlock, CompactBlockBody};
|
use crate::core::compact_block::{CompactBlock, CompactBlockBody};
|
||||||
use crate::core::hash::{Hash, Hashed, ZERO_HASH};
|
use crate::core::hash::{Hash, Hashed, ZERO_HASH};
|
||||||
use crate::core::verifier_cache::VerifierCache;
|
use crate::core::verifier_cache::VerifierCache;
|
||||||
use crate::core::{
|
use crate::core::{transaction, Commitment, Input, Output, Transaction, TransactionBody, TxKernel};
|
||||||
transaction, Commitment, Input, Output, Transaction,
|
|
||||||
TransactionBody, TxKernel,
|
|
||||||
};
|
|
||||||
use crate::global;
|
use crate::global;
|
||||||
use crate::keychain::{self, BlindingFactor};
|
use crate::keychain::{self, BlindingFactor};
|
||||||
use crate::pow::{Difficulty, Proof, ProofOfWork};
|
use crate::pow::{Difficulty, Proof, ProofOfWork};
|
||||||
|
|
|
@ -17,6 +17,7 @@ use croaring::Bitmap;
|
||||||
use crate::core::hash::Hash;
|
use crate::core::hash::Hash;
|
||||||
use crate::core::BlockHeader;
|
use crate::core::BlockHeader;
|
||||||
use crate::ser::PMMRable;
|
use crate::ser::PMMRable;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
/// Storage backend for the MMR, just needs to be indexed by order of insertion.
|
/// Storage backend for the MMR, just needs to be indexed by order of insertion.
|
||||||
/// The PMMR itself does not need the Backend to be accurate on the existence
|
/// The PMMR itself does not need the Backend to be accurate on the existence
|
||||||
|
@ -59,7 +60,7 @@ pub trait Backend<T: PMMRable> {
|
||||||
/// Returns the data file path.. this is a bit of a hack now that doesn't
|
/// Returns the data file path.. this is a bit of a hack now that doesn't
|
||||||
/// sit well with the design, but TxKernels have to be summed and the
|
/// sit well with the design, but TxKernels have to be summed and the
|
||||||
/// fastest way to to be able to allow direct access to the file
|
/// fastest way to to be able to allow direct access to the file
|
||||||
fn get_data_file_path(&self) -> &str;
|
fn get_data_file_path(&self) -> &Path;
|
||||||
|
|
||||||
/// Also a bit of a hack...
|
/// Also a bit of a hack...
|
||||||
/// Saves a snapshot of the rewound utxo file with the block hash as
|
/// Saves a snapshot of the rewound utxo file with the block hash as
|
||||||
|
|
|
@ -22,6 +22,7 @@ use crate::core::merkle_proof::MerkleProof;
|
||||||
use crate::core::pmmr::{Backend, ReadonlyPMMR};
|
use crate::core::pmmr::{Backend, ReadonlyPMMR};
|
||||||
use crate::core::BlockHeader;
|
use crate::core::BlockHeader;
|
||||||
use crate::ser::{PMMRIndexHashable, PMMRable};
|
use crate::ser::{PMMRIndexHashable, PMMRable};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
/// 64 bits all ones: 0b11111111...1
|
/// 64 bits all ones: 0b11111111...1
|
||||||
const ALL_ONES: u64 = u64::MAX;
|
const ALL_ONES: u64 = u64::MAX;
|
||||||
|
@ -323,7 +324,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the path of the data file (needed to sum kernels efficiently)
|
/// Return the path of the data file (needed to sum kernels efficiently)
|
||||||
pub fn data_file_path(&self) -> &str {
|
pub fn data_file_path(&self) -> &Path {
|
||||||
self.backend.get_data_file_path()
|
self.backend.get_data_file_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,7 @@ use crate::libtx::{aggsig, proof};
|
||||||
use crate::util::static_secp_instance;
|
use crate::util::static_secp_instance;
|
||||||
|
|
||||||
/// output a reward output
|
/// output a reward output
|
||||||
pub fn output<K>(
|
pub fn output<K>(keychain: &K, key_id: &Identifier, fees: u64) -> Result<(Output, TxKernel), Error>
|
||||||
keychain: &K,
|
|
||||||
key_id: &Identifier,
|
|
||||||
fees: u64,
|
|
||||||
) -> Result<(Output, TxKernel), Error>
|
|
||||||
where
|
where
|
||||||
K: Keychain,
|
K: Keychain,
|
||||||
{
|
{
|
||||||
|
|
|
@ -342,7 +342,6 @@ fn adjustment_scenarios() {
|
||||||
println!("*********************************************************");
|
println!("*********************************************************");
|
||||||
print_chain_sim(chain_sim);
|
print_chain_sim(chain_sim);
|
||||||
println!("*********************************************************");
|
println!("*********************************************************");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks different next_target adjustments and difficulty boundaries
|
/// Checks different next_target adjustments and difficulty boundaries
|
||||||
|
|
|
@ -20,6 +20,7 @@ use self::core::ser::{FixedLength, PMMRable, Readable, Reader, Writeable, Writer
|
||||||
use croaring;
|
use croaring;
|
||||||
use croaring::Bitmap;
|
use croaring::Bitmap;
|
||||||
use grin_core as core;
|
use grin_core as core;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct TestElem(pub [u32; 4]);
|
pub struct TestElem(pub [u32; 4]);
|
||||||
|
@ -117,8 +118,8 @@ impl<T: PMMRable> Backend<T> for VecBackend<T> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_data_file_path(&self) -> &str {
|
fn get_data_file_path(&self) -> &Path {
|
||||||
""
|
Path::new("")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_stats(&self) {}
|
fn dump_stats(&self) {}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
//! Compact (roaring) bitmap representing the set of leaf positions
|
//! Compact (roaring) bitmap representing the set of leaf positions
|
||||||
//! that exist and are not currently pruned in the MMR.
|
//! that exist and are not currently pruned in the MMR.
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use croaring::Bitmap;
|
use croaring::Bitmap;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ use std::io::{self, BufWriter, Write};
|
||||||
/// Compact (roaring) bitmap representing the set of positions of
|
/// Compact (roaring) bitmap representing the set of positions of
|
||||||
/// leaves that are currently unpruned in the MMR.
|
/// leaves that are currently unpruned in the MMR.
|
||||||
pub struct LeafSet {
|
pub struct LeafSet {
|
||||||
path: String,
|
path: PathBuf,
|
||||||
bitmap: Bitmap,
|
bitmap: Bitmap,
|
||||||
bitmap_bak: Bitmap,
|
bitmap_bak: Bitmap,
|
||||||
}
|
}
|
||||||
|
@ -39,35 +39,42 @@ pub struct LeafSet {
|
||||||
impl LeafSet {
|
impl LeafSet {
|
||||||
/// Open the remove log file.
|
/// Open the remove log file.
|
||||||
/// The content of the file will be read in memory for fast checking.
|
/// The content of the file will be read in memory for fast checking.
|
||||||
pub fn open(path: &str) -> io::Result<LeafSet> {
|
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<LeafSet> {
|
||||||
let file_path = Path::new(&path);
|
let file_path = path.as_ref();
|
||||||
let bitmap = if file_path.exists() {
|
let bitmap = if file_path.exists() {
|
||||||
read_bitmap(file_path)?
|
read_bitmap(&file_path)?
|
||||||
} else {
|
} else {
|
||||||
Bitmap::create()
|
Bitmap::create()
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(LeafSet {
|
Ok(LeafSet {
|
||||||
path: path.to_string(),
|
path: file_path.to_path_buf(),
|
||||||
bitmap_bak: bitmap.clone(),
|
bitmap_bak: bitmap.clone(),
|
||||||
bitmap,
|
bitmap,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copies a snapshot of the utxo file into the primary utxo file.
|
/// Copies a snapshot of the utxo file into the primary utxo file.
|
||||||
pub fn copy_snapshot(path: &str, cp_path: &str) -> io::Result<()> {
|
pub fn copy_snapshot<P: AsRef<Path>>(path: P, cp_path: P) -> io::Result<()> {
|
||||||
let cp_file_path = Path::new(&cp_path);
|
let cp_file_path = cp_path.as_ref();
|
||||||
|
|
||||||
if !cp_file_path.exists() {
|
if !cp_file_path.exists() {
|
||||||
debug!("leaf_set: rewound leaf file not found: {}", cp_path);
|
debug!(
|
||||||
|
"leaf_set: rewound leaf file not found: {}",
|
||||||
|
cp_file_path.display()
|
||||||
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let bitmap = read_bitmap(cp_file_path)?;
|
let bitmap = read_bitmap(&cp_file_path)?;
|
||||||
debug!("leaf_set: copying rewound file {} to {}", cp_path, path);
|
debug!(
|
||||||
|
"leaf_set: copying rewound file {} to {}",
|
||||||
|
cp_file_path.display(),
|
||||||
|
path.as_ref().display()
|
||||||
|
);
|
||||||
|
|
||||||
let mut leaf_set = LeafSet {
|
let mut leaf_set = LeafSet {
|
||||||
path: path.to_string(),
|
path: path.as_ref().to_path_buf(),
|
||||||
bitmap_bak: bitmap.clone(),
|
bitmap_bak: bitmap.clone(),
|
||||||
bitmap,
|
bitmap,
|
||||||
};
|
};
|
||||||
|
@ -148,7 +155,7 @@ impl LeafSet {
|
||||||
let mut cp_bitmap = self.bitmap.clone();
|
let mut cp_bitmap = self.bitmap.clone();
|
||||||
cp_bitmap.run_optimize();
|
cp_bitmap.run_optimize();
|
||||||
|
|
||||||
let cp_path = format!("{}.{}", self.path, header.hash());
|
let cp_path = self.path.join(header.hash().to_string());
|
||||||
let mut file = BufWriter::new(File::create(cp_path)?);
|
let mut file = BufWriter::new(File::create(cp_path)?);
|
||||||
file.write_all(&cp_bitmap.serialize())?;
|
file.write_all(&cp_bitmap.serialize())?;
|
||||||
file.flush()?;
|
file.flush()?;
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub fn to_key(prefix: u8, k: &mut Vec<u8>) -> Vec<u8> {
|
||||||
|
|
||||||
/// Build a db key from a prefix and a byte vector identifier and numeric identifier
|
/// Build a db key from a prefix and a byte vector identifier and numeric identifier
|
||||||
pub fn to_key_u64(prefix: u8, k: &mut Vec<u8>, val: u64) -> Vec<u8> {
|
pub fn to_key_u64(prefix: u8, k: &mut Vec<u8>, val: u64) -> Vec<u8> {
|
||||||
let mut res = vec![];
|
let mut res = Vec::with_capacity(k.len() + 10);
|
||||||
res.push(prefix);
|
res.push(prefix);
|
||||||
res.push(SEP);
|
res.push(SEP);
|
||||||
res.append(k);
|
res.append(k);
|
||||||
|
@ -65,31 +65,36 @@ pub fn to_key_u64(prefix: u8, k: &mut Vec<u8>, val: u64) -> Vec<u8> {
|
||||||
}
|
}
|
||||||
/// Build a db key from a prefix and a numeric identifier.
|
/// Build a db key from a prefix and a numeric identifier.
|
||||||
pub fn u64_to_key(prefix: u8, val: u64) -> Vec<u8> {
|
pub fn u64_to_key(prefix: u8, val: u64) -> Vec<u8> {
|
||||||
let mut u64_vec = vec![];
|
let mut res = Vec::with_capacity(10);
|
||||||
u64_vec.write_u64::<BigEndian>(val).unwrap();
|
res.push(prefix);
|
||||||
u64_vec.insert(0, SEP);
|
res.push(SEP);
|
||||||
u64_vec.insert(0, prefix);
|
res.write_u64::<BigEndian>(val).unwrap();
|
||||||
u64_vec
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::fs::{remove_file, rename, File};
|
||||||
|
use std::path::Path;
|
||||||
/// Creates temporary file with name created by adding `temp_suffix` to `path`.
|
/// Creates temporary file with name created by adding `temp_suffix` to `path`.
|
||||||
/// Applies writer function to it and renames temporary file into original specified by `path`.
|
/// Applies writer function to it and renames temporary file into original specified by `path`.
|
||||||
pub fn save_via_temp_file<F>(
|
pub fn save_via_temp_file<F, P, E>(
|
||||||
path: &str,
|
path: P,
|
||||||
temp_suffix: &str,
|
temp_suffix: E,
|
||||||
mut writer: F,
|
mut writer: F,
|
||||||
) -> Result<(), std::io::Error>
|
) -> Result<(), std::io::Error>
|
||||||
where
|
where
|
||||||
F: FnMut(Box<dyn std::io::Write>) -> Result<(), std::io::Error>,
|
F: FnMut(Box<dyn std::io::Write>) -> Result<(), std::io::Error>,
|
||||||
|
P: AsRef<Path>,
|
||||||
|
E: AsRef<OsStr>,
|
||||||
{
|
{
|
||||||
assert_ne!(*temp_suffix, *"");
|
let temp_suffix = temp_suffix.as_ref();
|
||||||
|
assert!(!temp_suffix.is_empty());
|
||||||
use std::fs::{remove_file, rename, File};
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
|
let original = path.as_ref();
|
||||||
|
let mut _original = original.as_os_str().to_os_string();
|
||||||
|
_original.push(temp_suffix);
|
||||||
// Write temporary file
|
// Write temporary file
|
||||||
let temp_name = format!("{}{}", &path, temp_suffix);
|
let temp_path = Path::new(&_original);
|
||||||
let temp_path = Path::new(&temp_name);
|
|
||||||
if temp_path.exists() {
|
if temp_path.exists() {
|
||||||
remove_file(&temp_path)?;
|
remove_file(&temp_path)?;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +103,6 @@ where
|
||||||
writer(Box::new(file))?;
|
writer(Box::new(file))?;
|
||||||
|
|
||||||
// Move temporary file into original
|
// Move temporary file into original
|
||||||
let original = Path::new(&path);
|
|
||||||
if original.exists() {
|
if original.exists() {
|
||||||
remove_file(&original)?;
|
remove_file(&original)?;
|
||||||
}
|
}
|
||||||
|
@ -110,10 +114,8 @@ where
|
||||||
|
|
||||||
use croaring::Bitmap;
|
use croaring::Bitmap;
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
use std::path::Path;
|
|
||||||
/// Read Bitmap from a file
|
/// Read Bitmap from a file
|
||||||
pub fn read_bitmap<P: AsRef<Path>>(file_path: P) -> io::Result<Bitmap> {
|
pub fn read_bitmap<P: AsRef<Path>>(file_path: P) -> io::Result<Bitmap> {
|
||||||
use std::fs::File;
|
|
||||||
let mut bitmap_file = File::open(file_path)?;
|
let mut bitmap_file = File::open(file_path)?;
|
||||||
let f_md = bitmap_file.metadata()?;
|
let f_md = bitmap_file.metadata()?;
|
||||||
let mut buffer = Vec::with_capacity(f_md.len() as usize);
|
let mut buffer = Vec::with_capacity(f_md.len() as usize);
|
||||||
|
|
|
@ -67,15 +67,17 @@ pub fn new_env(path: String) -> lmdb::Environment {
|
||||||
pub fn new_named_env(path: String, name: String) -> lmdb::Environment {
|
pub fn new_named_env(path: String, name: String) -> lmdb::Environment {
|
||||||
let full_path = [path, name].join("/");
|
let full_path = [path, name].join("/");
|
||||||
fs::create_dir_all(&full_path).unwrap();
|
fs::create_dir_all(&full_path).unwrap();
|
||||||
unsafe {
|
|
||||||
let mut env_builder = lmdb::EnvBuilder::new().unwrap();
|
let mut env_builder = lmdb::EnvBuilder::new().unwrap();
|
||||||
env_builder.set_maxdbs(8).unwrap();
|
env_builder.set_maxdbs(8).unwrap();
|
||||||
// half a TB should give us plenty room, will be an issue on 32 bits
|
// half a TB should give us plenty room, will be an issue on 32 bits
|
||||||
// (which we don't support anyway)
|
// (which we don't support anyway)
|
||||||
env_builder.set_mapsize(549755813888).unwrap_or_else(|e| {
|
env_builder
|
||||||
|
.set_mapsize(549_755_813_888)
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
panic!("Unable to allocate LMDB space: {:?}", e);
|
panic!("Unable to allocate LMDB space: {:?}", e);
|
||||||
});
|
});
|
||||||
|
unsafe {
|
||||||
env_builder
|
env_builder
|
||||||
.open(&full_path, lmdb::open::Flags::empty(), 0o600)
|
.open(&full_path, lmdb::open::Flags::empty(), 0o600)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -178,10 +180,10 @@ pub struct Batch<'a> {
|
||||||
|
|
||||||
impl<'a> Batch<'a> {
|
impl<'a> Batch<'a> {
|
||||||
/// Writes a single key/value pair to the db
|
/// Writes a single key/value pair to the db
|
||||||
pub fn put(&self, key: &[u8], value: Vec<u8>) -> Result<(), Error> {
|
pub fn put(&self, key: &[u8], value: &[u8]) -> Result<(), Error> {
|
||||||
self.tx
|
self.tx
|
||||||
.access()
|
.access()
|
||||||
.put(&self.store.db, key, &value, lmdb::put::Flags::empty())?;
|
.put(&self.store.db, key, value, lmdb::put::Flags::empty())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +192,7 @@ impl<'a> Batch<'a> {
|
||||||
pub fn put_ser<W: ser::Writeable>(&self, key: &[u8], value: &W) -> Result<(), Error> {
|
pub fn put_ser<W: ser::Writeable>(&self, key: &[u8], value: &W) -> Result<(), Error> {
|
||||||
let ser_value = ser::ser_vec(value);
|
let ser_value = ser::ser_vec(value);
|
||||||
match ser_value {
|
match ser_value {
|
||||||
Ok(data) => self.put(key, data),
|
Ok(data) => self.put(key, &data),
|
||||||
Err(err) => Err(Error::SerErr(format!("{}", err))),
|
Err(err) => Err(Error::SerErr(format!("{}", err))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ use crate::leaf_set::LeafSet;
|
||||||
use crate::prune_list::PruneList;
|
use crate::prune_list::PruneList;
|
||||||
use crate::types::{prune_noop, DataFile};
|
use crate::types::{prune_noop, DataFile};
|
||||||
use croaring::Bitmap;
|
use croaring::Bitmap;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
const PMMR_HASH_FILE: &str = "pmmr_hash.bin";
|
const PMMR_HASH_FILE: &str = "pmmr_hash.bin";
|
||||||
const PMMR_DATA_FILE: &str = "pmmr_data.bin";
|
const PMMR_DATA_FILE: &str = "pmmr_data.bin";
|
||||||
|
@ -50,7 +51,7 @@ pub const PMMR_FILES: [&str; 4] = [
|
||||||
/// * A prune_list tracks the positions of pruned (and compacted) roots in the
|
/// * A prune_list tracks the positions of pruned (and compacted) roots in the
|
||||||
/// MMR.
|
/// MMR.
|
||||||
pub struct PMMRBackend<T: PMMRable> {
|
pub struct PMMRBackend<T: PMMRable> {
|
||||||
data_dir: String,
|
data_dir: PathBuf,
|
||||||
prunable: bool,
|
prunable: bool,
|
||||||
hash_file: DataFile<Hash>,
|
hash_file: DataFile<Hash>,
|
||||||
data_file: DataFile<T::E>,
|
data_file: DataFile<T::E>,
|
||||||
|
@ -147,7 +148,7 @@ impl<T: PMMRable> Backend<T> for PMMRBackend<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return data file path
|
/// Return data file path
|
||||||
fn get_data_file_path(&self) -> &str {
|
fn get_data_file_path(&self) -> &Path {
|
||||||
self.data_file.path()
|
self.data_file.path()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,28 +174,32 @@ impl<T: PMMRable> Backend<T> for PMMRBackend<T> {
|
||||||
impl<T: PMMRable> PMMRBackend<T> {
|
impl<T: PMMRable> PMMRBackend<T> {
|
||||||
/// Instantiates a new PMMR backend.
|
/// Instantiates a new PMMR backend.
|
||||||
/// Use the provided dir to store its files.
|
/// Use the provided dir to store its files.
|
||||||
pub fn new(
|
pub fn new<P: AsRef<Path>>(
|
||||||
data_dir: String,
|
data_dir: P,
|
||||||
prunable: bool,
|
prunable: bool,
|
||||||
header: Option<&BlockHeader>,
|
header: Option<&BlockHeader>,
|
||||||
) -> io::Result<PMMRBackend<T>> {
|
) -> io::Result<PMMRBackend<T>> {
|
||||||
let hash_file = DataFile::open(&format!("{}/{}", data_dir, PMMR_HASH_FILE))?;
|
let data_dir = data_dir.as_ref();
|
||||||
let data_file = DataFile::open(&format!("{}/{}", data_dir, PMMR_DATA_FILE))?;
|
let hash_file = DataFile::open(&data_dir.join(PMMR_HASH_FILE))?;
|
||||||
|
let data_file = DataFile::open(&data_dir.join(PMMR_DATA_FILE))?;
|
||||||
|
|
||||||
let leaf_set_path = format!("{}/{}", data_dir, PMMR_LEAF_FILE);
|
let leaf_set_path = data_dir.join(PMMR_LEAF_FILE);
|
||||||
|
|
||||||
// If we received a rewound "snapshot" leaf_set file move it into
|
// If we received a rewound "snapshot" leaf_set file move it into
|
||||||
// place so we use it.
|
// place so we use it.
|
||||||
if let Some(header) = header {
|
if let Some(header) = header {
|
||||||
let leaf_snapshot_path = format!("{}/{}.{}", data_dir, PMMR_LEAF_FILE, header.hash());
|
let _leaf_snapshot_path = (data_dir.join(PMMR_LEAF_FILE).to_string_lossy()
|
||||||
|
+ header.hash().to_string().as_ref())
|
||||||
|
.into_owned();
|
||||||
|
let leaf_snapshot_path = PathBuf::from(_leaf_snapshot_path);
|
||||||
LeafSet::copy_snapshot(&leaf_set_path, &leaf_snapshot_path)?;
|
LeafSet::copy_snapshot(&leaf_set_path, &leaf_snapshot_path)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let leaf_set = LeafSet::open(&leaf_set_path)?;
|
let leaf_set = LeafSet::open(&leaf_set_path)?;
|
||||||
let prune_list = PruneList::open(&format!("{}/{}", data_dir, PMMR_PRUN_FILE))?;
|
let prune_list = PruneList::open(&data_dir.join(PMMR_PRUN_FILE))?;
|
||||||
|
|
||||||
Ok(PMMRBackend {
|
Ok(PMMRBackend {
|
||||||
data_dir,
|
data_dir: data_dir.to_path_buf(),
|
||||||
prunable,
|
prunable,
|
||||||
hash_file,
|
hash_file,
|
||||||
data_file,
|
data_file,
|
||||||
|
@ -278,9 +283,10 @@ impl<T: PMMRable> PMMRBackend<T> {
|
||||||
assert!(self.prunable, "Trying to compact a non-prunable PMMR");
|
assert!(self.prunable, "Trying to compact a non-prunable PMMR");
|
||||||
|
|
||||||
// Paths for tmp hash and data files.
|
// Paths for tmp hash and data files.
|
||||||
let tmp_prune_file_hash = format!("{}/{}.hashprune", self.data_dir, PMMR_HASH_FILE);
|
let tmp_prune_file_hash =
|
||||||
let tmp_prune_file_data = format!("{}/{}.dataprune", self.data_dir, PMMR_DATA_FILE);
|
format!("{}.hashprune", self.data_dir.join(PMMR_HASH_FILE).display());
|
||||||
|
let tmp_prune_file_data =
|
||||||
|
format!("{}.dataprune", self.data_dir.join(PMMR_DATA_FILE).display());
|
||||||
// Calculate the sets of leaf positions and node positions to remove based
|
// Calculate the sets of leaf positions and node positions to remove based
|
||||||
// on the cutoff_pos provided.
|
// on the cutoff_pos provided.
|
||||||
let (leaves_removed, pos_to_rm) = self.pos_to_rm(cutoff_pos, rewind_rm_pos);
|
let (leaves_removed, pos_to_rm) = self.pos_to_rm(cutoff_pos, rewind_rm_pos);
|
||||||
|
@ -293,7 +299,7 @@ impl<T: PMMRable> PMMRBackend<T> {
|
||||||
});
|
});
|
||||||
|
|
||||||
self.hash_file
|
self.hash_file
|
||||||
.save_prune(tmp_prune_file_hash.clone(), &off_to_rm, &prune_noop)?;
|
.save_prune(&tmp_prune_file_hash, &off_to_rm, &prune_noop)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Save compact copy of the data file, skipping removed leaves.
|
// 2. Save compact copy of the data file, skipping removed leaves.
|
||||||
|
@ -311,7 +317,7 @@ impl<T: PMMRable> PMMRBackend<T> {
|
||||||
});
|
});
|
||||||
|
|
||||||
self.data_file
|
self.data_file
|
||||||
.save_prune(tmp_prune_file_data.clone(), &off_to_rm, prune_cb)?;
|
.save_prune(&tmp_prune_file_data, &off_to_rm, prune_cb)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Update the prune list and write to disk.
|
// 3. Update the prune list and write to disk.
|
||||||
|
@ -325,16 +331,16 @@ impl<T: PMMRable> PMMRBackend<T> {
|
||||||
// 4. Rename the compact copy of hash file and reopen it.
|
// 4. Rename the compact copy of hash file and reopen it.
|
||||||
fs::rename(
|
fs::rename(
|
||||||
tmp_prune_file_hash.clone(),
|
tmp_prune_file_hash.clone(),
|
||||||
format!("{}/{}", self.data_dir, PMMR_HASH_FILE),
|
self.data_dir.join(PMMR_HASH_FILE),
|
||||||
)?;
|
)?;
|
||||||
self.hash_file = DataFile::open(&format!("{}/{}", self.data_dir, PMMR_HASH_FILE))?;
|
self.hash_file = DataFile::open(self.data_dir.join(PMMR_HASH_FILE))?;
|
||||||
|
|
||||||
// 5. Rename the compact copy of the data file and reopen it.
|
// 5. Rename the compact copy of the data file and reopen it.
|
||||||
fs::rename(
|
fs::rename(
|
||||||
tmp_prune_file_data.clone(),
|
tmp_prune_file_data.clone(),
|
||||||
format!("{}/{}", self.data_dir, PMMR_DATA_FILE),
|
self.data_dir.join(PMMR_DATA_FILE),
|
||||||
)?;
|
)?;
|
||||||
self.data_file = DataFile::open(&format!("{}/{}", self.data_dir, PMMR_DATA_FILE))?;
|
self.data_file = DataFile::open(self.data_dir.join(PMMR_DATA_FILE))?;
|
||||||
|
|
||||||
// 6. Write the leaf_set to disk.
|
// 6. Write the leaf_set to disk.
|
||||||
// Optimize the bitmap storage in the process.
|
// Optimize the bitmap storage in the process.
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
//! files.
|
//! files.
|
||||||
|
|
||||||
use std::io::{self, BufWriter, Write};
|
use std::io::{self, BufWriter, Write};
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use croaring::Bitmap;
|
use croaring::Bitmap;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ use crate::{read_bitmap, save_via_temp_file};
|
||||||
/// backend storage anymore. The PruneList accounts for that mismatch and does
|
/// backend storage anymore. The PruneList accounts for that mismatch and does
|
||||||
/// the position translation.
|
/// the position translation.
|
||||||
pub struct PruneList {
|
pub struct PruneList {
|
||||||
path: Option<String>,
|
path: Option<PathBuf>,
|
||||||
/// Bitmap representing pruned root node positions.
|
/// Bitmap representing pruned root node positions.
|
||||||
bitmap: Bitmap,
|
bitmap: Bitmap,
|
||||||
/// Bitmap representing all pruned node positions (everything under the pruned roots).
|
/// Bitmap representing all pruned node positions (everything under the pruned roots).
|
||||||
|
@ -63,8 +63,8 @@ impl PruneList {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open an existing prune_list or create a new one.
|
/// Open an existing prune_list or create a new one.
|
||||||
pub fn open(path: &str) -> io::Result<PruneList> {
|
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<PruneList> {
|
||||||
let file_path = Path::new(&path);
|
let file_path = PathBuf::from(path.as_ref());
|
||||||
let bitmap = if file_path.exists() {
|
let bitmap = if file_path.exists() {
|
||||||
read_bitmap(&file_path)?
|
read_bitmap(&file_path)?
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,7 +72,7 @@ impl PruneList {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut prune_list = PruneList {
|
let mut prune_list = PruneList {
|
||||||
path: Some(path.to_string()),
|
path: Some(file_path),
|
||||||
bitmap,
|
bitmap,
|
||||||
pruned_cache: Bitmap::create(),
|
pruned_cache: Bitmap::create(),
|
||||||
shift_cache: vec![],
|
shift_cache: vec![],
|
||||||
|
@ -111,7 +111,7 @@ impl PruneList {
|
||||||
|
|
||||||
// Write the updated bitmap file to disk.
|
// Write the updated bitmap file to disk.
|
||||||
if let Some(ref path) = self.path {
|
if let Some(ref path) = self.path {
|
||||||
save_via_temp_file(&path, ".tmp", |w| {
|
save_via_temp_file(path, ".tmp", |w| {
|
||||||
let mut w = BufWriter::new(w);
|
let mut w = BufWriter::new(w);
|
||||||
w.write_all(&self.bitmap.serialize())?;
|
w.write_all(&self.bitmap.serialize())?;
|
||||||
w.flush()
|
w.flush()
|
||||||
|
@ -264,7 +264,7 @@ impl PruneList {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.pruned_cache = Bitmap::create_with_capacity(self.bitmap.maximum());
|
self.pruned_cache = Bitmap::create_with_capacity(self.bitmap.maximum());
|
||||||
for pos in 1..(self.bitmap.maximum() + 1) {
|
for pos in 1..=self.bitmap.maximum() {
|
||||||
let path = path(pos as u64, self.bitmap.maximum() as u64);
|
let path = path(pos as u64, self.bitmap.maximum() as u64);
|
||||||
let pruned = path.into_iter().any(|x| self.bitmap.contains(x as u32));
|
let pruned = path.into_iter().any(|x| self.bitmap.contains(x as u32));
|
||||||
if pruned {
|
if pruned {
|
||||||
|
@ -279,3 +279,9 @@ impl PruneList {
|
||||||
self.bitmap.contains(pos as u32)
|
self.bitmap.contains(pos as u32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for PruneList {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ use crate::core::ser::{self, FixedLength, Readable, Writeable};
|
||||||
use std::fs::{self, File, OpenOptions};
|
use std::fs::{self, File, OpenOptions};
|
||||||
use std::io::{self, BufWriter, ErrorKind, Read, Write};
|
use std::io::{self, BufWriter, ErrorKind, Read, Write};
|
||||||
use std::marker;
|
use std::marker;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
/// A no-op function for doing nothing with some pruned data.
|
/// A no-op function for doing nothing with some pruned data.
|
||||||
pub fn prune_noop(_pruned_data: &[u8]) {}
|
pub fn prune_noop(_pruned_data: &[u8]) {}
|
||||||
|
@ -33,7 +34,7 @@ where
|
||||||
T: FixedLength + Readable + Writeable,
|
T: FixedLength + Readable + Writeable,
|
||||||
{
|
{
|
||||||
/// Open (or create) a file at the provided path on disk.
|
/// Open (or create) a file at the provided path on disk.
|
||||||
pub fn open(path: &str) -> io::Result<DataFile<T>> {
|
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<DataFile<T>> {
|
||||||
let file = AppendOnlyFile::open(path)?;
|
let file = AppendOnlyFile::open(path)?;
|
||||||
Ok(DataFile {
|
Ok(DataFile {
|
||||||
file,
|
file,
|
||||||
|
@ -96,12 +97,12 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Path of the underlying file
|
/// Path of the underlying file
|
||||||
pub fn path(&self) -> &str {
|
pub fn path(&self) -> &Path {
|
||||||
self.file.path()
|
self.file.path()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the file out to disk, pruning removed elements.
|
/// Write the file out to disk, pruning removed elements.
|
||||||
pub fn save_prune<F>(&self, target: String, prune_offs: &[u64], prune_cb: F) -> io::Result<()>
|
pub fn save_prune<F>(&self, target: &str, prune_offs: &[u64], prune_cb: F) -> io::Result<()>
|
||||||
where
|
where
|
||||||
F: Fn(&[u8]),
|
F: Fn(&[u8]),
|
||||||
{
|
{
|
||||||
|
@ -123,7 +124,7 @@ where
|
||||||
/// former simply happens by rewriting it, ignoring some of the data. The
|
/// former simply happens by rewriting it, ignoring some of the data. The
|
||||||
/// latter by truncating the underlying file and re-creating the mmap.
|
/// latter by truncating the underlying file and re-creating the mmap.
|
||||||
pub struct AppendOnlyFile {
|
pub struct AppendOnlyFile {
|
||||||
path: String,
|
path: PathBuf,
|
||||||
file: File,
|
file: File,
|
||||||
mmap: Option<memmap::Mmap>,
|
mmap: Option<memmap::Mmap>,
|
||||||
buffer_start: usize,
|
buffer_start: usize,
|
||||||
|
@ -133,7 +134,7 @@ pub struct AppendOnlyFile {
|
||||||
|
|
||||||
impl AppendOnlyFile {
|
impl AppendOnlyFile {
|
||||||
/// Open a file (existing or not) as append-only, backed by a mmap.
|
/// Open a file (existing or not) as append-only, backed by a mmap.
|
||||||
pub fn open(path: &str) -> io::Result<AppendOnlyFile> {
|
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<AppendOnlyFile> {
|
||||||
let file = OpenOptions::new()
|
let file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.append(true)
|
.append(true)
|
||||||
|
@ -141,7 +142,7 @@ impl AppendOnlyFile {
|
||||||
.open(&path)?;
|
.open(&path)?;
|
||||||
let mut aof = AppendOnlyFile {
|
let mut aof = AppendOnlyFile {
|
||||||
file,
|
file,
|
||||||
path: path.to_string(),
|
path: path.as_ref().to_path_buf(),
|
||||||
mmap: None,
|
mmap: None,
|
||||||
buffer_start: 0,
|
buffer_start: 0,
|
||||||
buffer: vec![],
|
buffer: vec![],
|
||||||
|
@ -258,15 +259,16 @@ impl AppendOnlyFile {
|
||||||
|
|
||||||
/// Saves a copy of the current file content, skipping data at the provided
|
/// Saves a copy of the current file content, skipping data at the provided
|
||||||
/// prune indices. The prune Vec must be ordered.
|
/// prune indices. The prune Vec must be ordered.
|
||||||
pub fn save_prune<T>(
|
pub fn save_prune<T, P>(
|
||||||
&self,
|
&self,
|
||||||
target: String,
|
target: P,
|
||||||
prune_offs: &[u64],
|
prune_offs: &[u64],
|
||||||
prune_len: u64,
|
prune_len: u64,
|
||||||
prune_cb: T,
|
prune_cb: T,
|
||||||
) -> io::Result<()>
|
) -> io::Result<()>
|
||||||
where
|
where
|
||||||
T: Fn(&[u8]),
|
T: Fn(&[u8]),
|
||||||
|
P: AsRef<Path>,
|
||||||
{
|
{
|
||||||
if prune_offs.is_empty() {
|
if prune_offs.is_empty() {
|
||||||
fs::copy(&self.path, &target)?;
|
fs::copy(&self.path, &target)?;
|
||||||
|
@ -322,7 +324,7 @@ impl AppendOnlyFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Path of the underlying file
|
/// Path of the underlying file
|
||||||
pub fn path(&self) -> &str {
|
pub fn path(&self) -> &Path {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ use grin_core as core;
|
||||||
use grin_store as store;
|
use grin_store as store;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::prelude::*;
|
|
||||||
|
|
||||||
use chrono::prelude::Utc;
|
use chrono::prelude::Utc;
|
||||||
use croaring::Bitmap;
|
use croaring::Bitmap;
|
||||||
|
@ -822,9 +821,9 @@ fn create_numbered_files(
|
||||||
prefix,
|
prefix,
|
||||||
start_index + rewind_file_num
|
start_index + rewind_file_num
|
||||||
));
|
));
|
||||||
let mut file = fs::File::create(path.clone()).unwrap();
|
let file = fs::File::create(path.clone()).unwrap();
|
||||||
let metadata = file.metadata().unwrap();
|
let metadata = file.metadata().unwrap();
|
||||||
filetime::set_file_times(path, time_to_set_ft, time_to_set_ft);
|
filetime::set_file_times(path, time_to_set_ft, time_to_set_ft).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,8 @@ where
|
||||||
verifier_cache,
|
verifier_cache,
|
||||||
false,
|
false,
|
||||||
Arc::new(Mutex::new(StopState::new())),
|
Arc::new(Mutex::new(StopState::new())),
|
||||||
).unwrap();
|
)
|
||||||
|
.unwrap();
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let retval = WalletProxy {
|
let retval = WalletProxy {
|
||||||
chain_dir: chain_dir.to_owned(),
|
chain_dir: chain_dir.to_owned(),
|
||||||
|
|
Loading…
Reference in a new issue