Merge branch 'master' of github.com:ethcore/parity into ethash
This commit is contained in:
1
util/cov.sh
Symbolic link
1
util/cov.sh
Symbolic link
@@ -0,0 +1 @@
|
||||
../cov.sh
|
||||
@@ -43,6 +43,7 @@ use std::ops::{Deref, DerefMut};
|
||||
use uint::{Uint, U128, U256};
|
||||
use hash::FixedHash;
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub struct PrettySlice<'a> (&'a [u8]);
|
||||
|
||||
impl<'a> fmt::Debug for PrettySlice<'a> {
|
||||
@@ -66,8 +67,11 @@ impl<'a> fmt::Display for PrettySlice<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub trait ToPretty {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn pretty(&self) -> PrettySlice;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn to_hex(&self) -> String {
|
||||
format!("{}", self.pretty())
|
||||
}
|
||||
@@ -90,8 +94,11 @@ impl ToPretty for Bytes {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub enum BytesRef<'a> {
|
||||
/// TODO [debris] Please document me
|
||||
Flexible(&'a mut Bytes),
|
||||
/// TODO [debris] Please document me
|
||||
Fixed(&'a mut [u8])
|
||||
}
|
||||
|
||||
@@ -121,8 +128,11 @@ pub type Bytes = Vec<u8>;
|
||||
/// Slice of bytes to underlying memory
|
||||
pub trait BytesConvertable {
|
||||
// TODO: rename to as_slice
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn bytes(&self) -> &[u8];
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn as_slice(&self) -> &[u8] { self.bytes() }
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn to_bytes(&self) -> Bytes { self.as_slice().to_vec() }
|
||||
}
|
||||
|
||||
@@ -160,8 +170,11 @@ fn bytes_convertable() {
|
||||
///
|
||||
/// TODO: optimise some conversations
|
||||
pub trait ToBytes {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn to_bytes(&self) -> Vec<u8>;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn to_bytes_len(&self) -> usize { self.to_bytes().len() }
|
||||
/// TODO [debris] Please document me
|
||||
fn first_byte(&self) -> Option<u8> { self.to_bytes().first().map(|&x| { x })}
|
||||
}
|
||||
|
||||
@@ -257,7 +270,9 @@ impl <T>ToBytes for T where T: FixedHash {
|
||||
/// Error returned when FromBytes conversation goes wrong
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum FromBytesError {
|
||||
/// TODO [debris] Please document me
|
||||
DataIsTooShort,
|
||||
/// TODO [debris] Please document me
|
||||
DataIsTooLong
|
||||
}
|
||||
|
||||
@@ -278,6 +293,7 @@ pub type FromBytesResult<T> = Result<T, FromBytesError>;
|
||||
///
|
||||
/// TODO: check size of bytes before conversation and return appropriate error
|
||||
pub trait FromBytes: Sized {
|
||||
/// TODO [debris] Please document me
|
||||
fn from_bytes(bytes: &[u8]) -> FromBytesResult<Self>;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,9 @@ use sha3::*;
|
||||
/// index. Their `BloomIndex` can be created from block number and given level.
|
||||
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
|
||||
pub struct BloomIndex {
|
||||
/// TODO [debris] Please document me
|
||||
pub level: u8,
|
||||
/// TODO [debris] Please document me
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ macro_rules! flushln {
|
||||
($fmt:expr, $($arg:tt)*) => (flush!(concat!($fmt, "\n"), $($arg)*));
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn flush(s: String) {
|
||||
::std::io::stdout().write(s.as_bytes()).unwrap();
|
||||
::std::io::stdout().flush().unwrap();
|
||||
|
||||
@@ -4,8 +4,11 @@ use uint::*;
|
||||
use secp256k1::{key, Secp256k1};
|
||||
use rand::os::OsRng;
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub type Secret = H256;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub type Public = H512;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub type Signature = H520;
|
||||
|
||||
lazy_static! {
|
||||
@@ -33,11 +36,17 @@ impl Signature {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// TODO [arkpar] Please document me
|
||||
pub enum CryptoError {
|
||||
/// TODO [arkpar] Please document me
|
||||
InvalidSecret,
|
||||
/// TODO [arkpar] Please document me
|
||||
InvalidPublic,
|
||||
/// TODO [arkpar] Please document me
|
||||
InvalidSignature,
|
||||
/// TODO [arkpar] Please document me
|
||||
InvalidMessage,
|
||||
/// TODO [arkpar] Please document me
|
||||
Io(::std::io::Error),
|
||||
}
|
||||
|
||||
@@ -122,6 +131,7 @@ impl KeyPair {
|
||||
pub fn sign(&self, message: &H256) -> Result<Signature, CryptoError> { ec::sign(&self.secret, message) }
|
||||
}
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub mod ec {
|
||||
use hash::*;
|
||||
use uint::*;
|
||||
@@ -151,6 +161,12 @@ pub mod ec {
|
||||
let mut signature: crypto::Signature = unsafe { ::std::mem::uninitialized() };
|
||||
signature.clone_from_slice(&data);
|
||||
signature[64] = rec_id.to_i32() as u8;
|
||||
|
||||
let (_, s, v) = signature.to_rsv();
|
||||
let secp256k1n = U256::from_str("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap();
|
||||
if !is_low_s(&s) {
|
||||
signature = super::Signature::from_rsv(&H256::from_slice(&signature[0..32]), &H256::from(secp256k1n - s), v ^ 1);
|
||||
}
|
||||
Ok(signature)
|
||||
}
|
||||
/// Verify signature.
|
||||
@@ -174,7 +190,7 @@ pub mod ec {
|
||||
|
||||
/// Check if this is a "low" signature.
|
||||
pub fn is_low(sig: &Signature) -> bool {
|
||||
H256::from_slice(&sig[32..64]) <= h256_from_hex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0")
|
||||
H256::from_slice(&sig[32..64]) <= h256_from_hex("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0")
|
||||
}
|
||||
|
||||
/// Check if this is a "low" signature.
|
||||
@@ -192,10 +208,12 @@ pub mod ec {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub mod ecdh {
|
||||
use crypto::*;
|
||||
use crypto::{self};
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub fn agree(secret: &Secret, public: &Public, ) -> Result<Secret, CryptoError> {
|
||||
use secp256k1::*;
|
||||
let context = &crypto::SECP256K1;
|
||||
@@ -211,11 +229,13 @@ pub mod ecdh {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub mod ecies {
|
||||
use hash::*;
|
||||
use bytes::*;
|
||||
use crypto::*;
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub fn encrypt(public: &Public, plain: &[u8]) -> Result<Bytes, CryptoError> {
|
||||
use ::rcrypto::digest::Digest;
|
||||
use ::rcrypto::sha2::Sha256;
|
||||
@@ -251,6 +271,7 @@ pub mod ecies {
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub fn decrypt(secret: &Secret, encrypted: &[u8]) -> Result<Bytes, CryptoError> {
|
||||
use ::rcrypto::digest::Digest;
|
||||
use ::rcrypto::sha2::Sha256;
|
||||
@@ -316,17 +337,20 @@ pub mod ecies {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub mod aes {
|
||||
use ::rcrypto::blockmodes::*;
|
||||
use ::rcrypto::aessafe::*;
|
||||
use ::rcrypto::symmetriccipher::*;
|
||||
use ::rcrypto::buffer::*;
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub fn encrypt(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) {
|
||||
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
|
||||
encryptor.encrypt(&mut RefReadBuffer::new(plain), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
|
||||
}
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub fn decrypt(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) {
|
||||
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
|
||||
encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
|
||||
|
||||
@@ -6,22 +6,36 @@ use rlp::DecoderError;
|
||||
use io;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub enum BaseDataError {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
NegativelyReferencedHash,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// General error type which should be capable of representing all errors in ethcore.
|
||||
pub enum UtilError {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Crypto(::crypto::CryptoError),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
StdIo(::std::io::Error),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Io(io::IoError),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
AddressParse(::std::net::AddrParseError),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
AddressResolve(Option<::std::io::Error>),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
FromHex(FromHexError),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
BaseData(BaseDataError),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Network(NetworkError),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Decoder(DecoderError),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
SimpleString(String),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
BadSize,
|
||||
}
|
||||
|
||||
@@ -73,6 +87,12 @@ impl From<::rlp::DecoderError> for UtilError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for UtilError {
|
||||
fn from(err: String) -> UtilError {
|
||||
UtilError::SimpleString(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: uncomment below once https://github.com/rust-lang/rust/issues/27336 sorted.
|
||||
/*#![feature(concat_idents)]
|
||||
macro_rules! assimilate {
|
||||
|
||||
@@ -7,6 +7,8 @@ macro_rules! xjson {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub trait FromJson {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn from_json(json: &Json) -> Self;
|
||||
}
|
||||
|
||||
@@ -13,20 +13,33 @@ use uint::{Uint, U256};
|
||||
///
|
||||
/// Note: types implementing `FixedHash` must be also `BytesConvertable`.
|
||||
pub trait FixedHash: Sized + BytesConvertable + Populatable + FromStr + Default {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn new() -> Self;
|
||||
/// Synonym for `new()`. Prefer to new as it's more readable.
|
||||
fn zero() -> Self;
|
||||
/// TODO [debris] Please document me
|
||||
fn random() -> Self;
|
||||
/// TODO [debris] Please document me
|
||||
fn randomize(&mut self);
|
||||
/// TODO [arkpar] Please document me
|
||||
fn size() -> usize;
|
||||
/// TODO [arkpar] Please document me
|
||||
fn from_slice(src: &[u8]) -> Self;
|
||||
/// TODO [arkpar] Please document me
|
||||
fn clone_from_slice(&mut self, src: &[u8]) -> usize;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn copy_to(&self, dest: &mut [u8]);
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn shift_bloomed<'a, T>(&'a mut self, b: &T) -> &'a mut Self where T: FixedHash;
|
||||
/// TODO [debris] Please document me
|
||||
fn with_bloomed<T>(mut self, b: &T) -> Self where T: FixedHash { self.shift_bloomed(b); self }
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn bloom_part<T>(&self, m: usize) -> T where T: FixedHash;
|
||||
/// TODO [debris] Please document me
|
||||
fn contains_bloomed<T>(&self, b: &T) -> bool where T: FixedHash;
|
||||
/// TODO [arkpar] Please document me
|
||||
fn contains<'a>(&'a self, b: &'a Self) -> bool;
|
||||
/// TODO [debris] Please document me
|
||||
fn is_zero(&self) -> bool;
|
||||
}
|
||||
|
||||
@@ -41,6 +54,7 @@ fn clean_0x(s: &str) -> &str {
|
||||
macro_rules! impl_hash {
|
||||
($from: ident, $size: expr) => {
|
||||
#[derive(Eq)]
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub struct $from (pub [u8; $size]);
|
||||
|
||||
impl BytesConvertable for $from {
|
||||
@@ -396,10 +410,12 @@ macro_rules! impl_hash {
|
||||
}
|
||||
|
||||
impl $from {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn hex(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn from_bloomed<T>(b: &T) -> Self where T: FixedHash { b.bloom_part($size) }
|
||||
}
|
||||
|
||||
@@ -503,21 +519,25 @@ impl<'_> From<&'_ Address> for H256 {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn h256_from_hex(s: &str) -> H256 {
|
||||
use std::str::FromStr;
|
||||
H256::from_str(s).unwrap()
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn h256_from_u64(n: u64) -> H256 {
|
||||
use uint::U256;
|
||||
H256::from(&U256::from(n))
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn address_from_hex(s: &str) -> Address {
|
||||
use std::str::FromStr;
|
||||
Address::from_str(s).unwrap()
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn address_from_u64(n: u64) -> Address {
|
||||
let h256 = h256_from_u64(n);
|
||||
From::from(h256)
|
||||
|
||||
@@ -41,7 +41,9 @@ mod worker;
|
||||
use mio::{EventLoop, Token};
|
||||
|
||||
#[derive(Debug)]
|
||||
/// TODO [arkpar] Please document me
|
||||
pub enum IoError {
|
||||
/// TODO [arkpar] Please document me
|
||||
Mio(::std::io::Error),
|
||||
}
|
||||
|
||||
@@ -73,13 +75,20 @@ pub trait IoHandler<Message>: Send + Sync where Message: Send + Sync + Clone + '
|
||||
fn update_stream(&self, _stream: StreamToken, _reg: Token, _event_loop: &mut EventLoop<IoManager<Message>>) {}
|
||||
}
|
||||
|
||||
pub type TimerToken = service::TimerToken;
|
||||
pub type StreamToken = service::StreamToken;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use io::service::TimerToken;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use io::service::StreamToken;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use io::service::IoContext;
|
||||
pub type IoService<Message> = service::IoService<Message>;
|
||||
pub type IoChannel<Message> = service::IoChannel<Message>;
|
||||
pub type IoManager<Message> = service::IoManager<Message>;
|
||||
pub const TOKENS_PER_HANDLER: usize = service::TOKENS_PER_HANDLER;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use io::service::IoService;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use io::service::IoChannel;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use io::service::IoManager;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use io::service::TOKENS_PER_HANDLER;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
104
util/src/io/worker.rs
Normal file
104
util/src/io/worker.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use std::sync::*;
|
||||
use std::mem;
|
||||
use std::thread::{JoinHandle, self};
|
||||
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
|
||||
use crossbeam::sync::chase_lev;
|
||||
use io::service::{HandlerId, IoChannel, IoContext};
|
||||
use io::{IoHandler};
|
||||
|
||||
pub enum WorkType<Message> {
|
||||
Readable,
|
||||
Writable,
|
||||
Hup,
|
||||
Timeout,
|
||||
Message(Message)
|
||||
}
|
||||
|
||||
pub struct Work<Message> {
|
||||
pub work_type: WorkType<Message>,
|
||||
pub token: usize,
|
||||
pub handler_id: HandlerId,
|
||||
pub handler: Arc<IoHandler<Message>>,
|
||||
}
|
||||
|
||||
/// An IO worker thread
|
||||
/// Sorts them ready for blockchain insertion.
|
||||
pub struct Worker {
|
||||
thread: Option<JoinHandle<()>>,
|
||||
wait: Arc<Condvar>,
|
||||
deleting: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl Worker {
|
||||
/// Creates a new worker instance.
|
||||
pub fn new<Message>(index: usize,
|
||||
stealer: chase_lev::Stealer<Work<Message>>,
|
||||
channel: IoChannel<Message>,
|
||||
wait: Arc<Condvar>,
|
||||
wait_mutex: Arc<Mutex<bool>>) -> Worker
|
||||
where Message: Send + Sync + Clone + 'static {
|
||||
let deleting = Arc::new(AtomicBool::new(false));
|
||||
let mut worker = Worker {
|
||||
thread: None,
|
||||
wait: wait.clone(),
|
||||
deleting: deleting.clone(),
|
||||
};
|
||||
worker.thread = Some(thread::Builder::new().name(format!("IO Worker #{}", index)).spawn(
|
||||
move || Worker::work_loop(stealer, channel.clone(), wait, wait_mutex.clone(), deleting))
|
||||
.expect("Error creating worker thread"));
|
||||
worker
|
||||
}
|
||||
|
||||
fn work_loop<Message>(stealer: chase_lev::Stealer<Work<Message>>,
|
||||
channel: IoChannel<Message>, wait: Arc<Condvar>,
|
||||
wait_mutex: Arc<Mutex<bool>>,
|
||||
deleting: Arc<AtomicBool>)
|
||||
where Message: Send + Sync + Clone + 'static {
|
||||
while !deleting.load(AtomicOrdering::Relaxed) {
|
||||
{
|
||||
let lock = wait_mutex.lock().unwrap();
|
||||
let _ = wait.wait(lock).unwrap();
|
||||
if deleting.load(AtomicOrdering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
loop {
|
||||
match stealer.steal() {
|
||||
chase_lev::Steal::Data(work) => {
|
||||
Worker::do_work(work, channel.clone());
|
||||
}
|
||||
_ => break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_work<Message>(work: Work<Message>, channel: IoChannel<Message>) where Message: Send + Sync + Clone + 'static {
|
||||
match work.work_type {
|
||||
WorkType::Readable => {
|
||||
work.handler.stream_readable(&mut IoContext::new(channel, work.handler_id), work.token);
|
||||
},
|
||||
WorkType::Writable => {
|
||||
work.handler.stream_writable(&mut IoContext::new(channel, work.handler_id), work.token);
|
||||
}
|
||||
WorkType::Hup => {
|
||||
work.handler.stream_hup(&mut IoContext::new(channel, work.handler_id), work.token);
|
||||
}
|
||||
WorkType::Timeout => {
|
||||
work.handler.timeout(&mut IoContext::new(channel, work.handler_id), work.token);
|
||||
}
|
||||
WorkType::Message(message) => {
|
||||
work.handler.message(&mut IoContext::new(channel, work.handler_id), &message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Worker {
|
||||
fn drop(&mut self) {
|
||||
self.deleting.store(true, AtomicOrdering::Relaxed);
|
||||
self.wait.notify_all();
|
||||
let thread = mem::replace(&mut self.thread, None).unwrap();
|
||||
thread.join().unwrap();
|
||||
}
|
||||
}
|
||||
214
util/src/journaldb.rs
Normal file
214
util/src/journaldb.rs
Normal file
@@ -0,0 +1,214 @@
|
||||
//! Disk-backed HashDB implementation.
|
||||
|
||||
use std::env;
|
||||
use common::*;
|
||||
use rlp::*;
|
||||
use hashdb::*;
|
||||
use overlaydb::*;
|
||||
use rocksdb::{DB, Writable};
|
||||
|
||||
#[derive(Clone)]
|
||||
/// Implementation of the HashDB trait for a disk-backed database with a memory overlay
|
||||
/// and latent-removal semantics.
|
||||
///
|
||||
/// Like OverlayDB, there is a memory overlay; `commit()` must be called in order to
|
||||
/// write operations out to disk. Unlike OverlayDB, `remove()` operations do not take effect
|
||||
/// immediately. Rather some age (based on a linear but arbitrary metric) must pass before
|
||||
/// the removals actually take effect.
|
||||
pub struct JournalDB {
|
||||
forward: OverlayDB,
|
||||
backing: Arc<DB>,
|
||||
inserts: Vec<H256>,
|
||||
removes: Vec<H256>,
|
||||
}
|
||||
|
||||
impl JournalDB {
|
||||
/// Create a new instance given a `backing` database.
|
||||
pub fn new(backing: DB) -> JournalDB {
|
||||
let db = Arc::new(backing);
|
||||
JournalDB {
|
||||
forward: OverlayDB::new_with_arc(db.clone()),
|
||||
backing: db,
|
||||
inserts: vec![],
|
||||
removes: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new instance with an anonymous temporary database.
|
||||
pub fn new_temp() -> JournalDB {
|
||||
let mut dir = env::temp_dir();
|
||||
dir.push(H32::random().hex());
|
||||
Self::new(DB::open_default(dir.to_str().unwrap()).unwrap())
|
||||
}
|
||||
|
||||
/// Get a clone of the overlay db portion of this.
|
||||
pub fn to_overlaydb(&self) -> OverlayDB { self.forward.clone() }
|
||||
|
||||
/// Commit all recent insert operations and historical removals from the old era
|
||||
/// to the backing database.
|
||||
pub fn commit(&mut self, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result<u32, UtilError> {
|
||||
// journal format:
|
||||
// [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ]
|
||||
// [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ]
|
||||
// [era, n] => [ ... ]
|
||||
|
||||
// TODO: store last_era, reclaim_period.
|
||||
|
||||
// when we make a new commit, we journal the inserts and removes.
|
||||
// for each end_era that we journaled that we are no passing by,
|
||||
// we remove all of its removes assuming it is canonical and all
|
||||
// of its inserts otherwise.
|
||||
|
||||
// record new commit's details.
|
||||
{
|
||||
let mut index = 0usize;
|
||||
let mut last;
|
||||
|
||||
while try!(self.backing.get({
|
||||
let mut r = RlpStream::new_list(2);
|
||||
r.append(&now);
|
||||
r.append(&index);
|
||||
last = r.drain();
|
||||
&last
|
||||
})).is_some() {
|
||||
index += 1;
|
||||
}
|
||||
|
||||
let mut r = RlpStream::new_list(3);
|
||||
r.append(id);
|
||||
r.append(&self.inserts);
|
||||
r.append(&self.removes);
|
||||
try!(self.backing.put(&last, r.as_raw()));
|
||||
self.inserts.clear();
|
||||
self.removes.clear();
|
||||
}
|
||||
|
||||
// apply old commits' details
|
||||
if let Some((end_era, canon_id)) = end {
|
||||
let mut index = 0usize;
|
||||
let mut last;
|
||||
while let Some(rlp_data) = try!(self.backing.get({
|
||||
let mut r = RlpStream::new_list(2);
|
||||
r.append(&end_era);
|
||||
r.append(&index);
|
||||
last = r.drain();
|
||||
&last
|
||||
})) {
|
||||
let rlp = Rlp::new(&rlp_data);
|
||||
let to_remove: Vec<H256> = rlp.val_at(if canon_id == rlp.val_at(0) {2} else {1});
|
||||
for i in to_remove.iter() {
|
||||
self.forward.remove(i);
|
||||
}
|
||||
try!(self.backing.delete(&last));
|
||||
trace!("JournalDB: delete journal for time #{}.{}, (canon was {}): {} entries", end_era, index, canon_id, to_remove.len());
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
self.forward.commit()
|
||||
}
|
||||
|
||||
/// Revert all operations on this object (i.e. `insert()`s and `removes()`s) since the
|
||||
/// last `commit()`.
|
||||
pub fn revert(&mut self) { self.forward.revert(); self.removes.clear(); }
|
||||
}
|
||||
|
||||
impl HashDB for JournalDB {
|
||||
fn keys(&self) -> HashMap<H256, i32> { self.forward.keys() }
|
||||
fn lookup(&self, key: &H256) -> Option<&[u8]> { self.forward.lookup(key) }
|
||||
fn exists(&self, key: &H256) -> bool { self.forward.exists(key) }
|
||||
fn insert(&mut self, value: &[u8]) -> H256 { let r = self.forward.insert(value); self.inserts.push(r.clone()); r }
|
||||
fn emplace(&mut self, key: H256, value: Bytes) { self.inserts.push(key.clone()); self.forward.emplace(key, value); }
|
||||
fn kill(&mut self, key: &H256) { self.removes.push(key.clone()); }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use common::*;
|
||||
use super::*;
|
||||
use hashdb::*;
|
||||
|
||||
#[test]
|
||||
fn long_history() {
|
||||
// history is 3
|
||||
let mut jdb = JournalDB::new_temp();
|
||||
let h = jdb.insert(b"foo");
|
||||
jdb.commit(0, &b"0".sha3(), None).unwrap();
|
||||
assert!(jdb.exists(&h));
|
||||
jdb.remove(&h);
|
||||
jdb.commit(1, &b"1".sha3(), None).unwrap();
|
||||
assert!(jdb.exists(&h));
|
||||
jdb.commit(2, &b"2".sha3(), None).unwrap();
|
||||
assert!(jdb.exists(&h));
|
||||
jdb.commit(3, &b"3".sha3(), Some((0, b"0".sha3()))).unwrap();
|
||||
assert!(jdb.exists(&h));
|
||||
jdb.commit(4, &b"4".sha3(), Some((1, b"1".sha3()))).unwrap();
|
||||
assert!(!jdb.exists(&h));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complex() {
|
||||
// history is 1
|
||||
let mut jdb = JournalDB::new_temp();
|
||||
|
||||
let foo = jdb.insert(b"foo");
|
||||
let bar = jdb.insert(b"bar");
|
||||
jdb.commit(0, &b"0".sha3(), None).unwrap();
|
||||
assert!(jdb.exists(&foo));
|
||||
assert!(jdb.exists(&bar));
|
||||
|
||||
jdb.remove(&foo);
|
||||
jdb.remove(&bar);
|
||||
let baz = jdb.insert(b"baz");
|
||||
jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap();
|
||||
assert!(jdb.exists(&foo));
|
||||
assert!(jdb.exists(&bar));
|
||||
assert!(jdb.exists(&baz));
|
||||
|
||||
let foo = jdb.insert(b"foo");
|
||||
jdb.remove(&baz);
|
||||
jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap();
|
||||
assert!(jdb.exists(&foo));
|
||||
assert!(!jdb.exists(&bar));
|
||||
assert!(jdb.exists(&baz));
|
||||
|
||||
jdb.remove(&foo);
|
||||
jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap();
|
||||
assert!(jdb.exists(&foo));
|
||||
assert!(!jdb.exists(&bar));
|
||||
assert!(!jdb.exists(&baz));
|
||||
|
||||
jdb.commit(4, &b"4".sha3(), Some((3, b"3".sha3()))).unwrap();
|
||||
assert!(!jdb.exists(&foo));
|
||||
assert!(!jdb.exists(&bar));
|
||||
assert!(!jdb.exists(&baz));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fork() {
|
||||
// history is 1
|
||||
let mut jdb = JournalDB::new_temp();
|
||||
|
||||
let foo = jdb.insert(b"foo");
|
||||
let bar = jdb.insert(b"bar");
|
||||
jdb.commit(0, &b"0".sha3(), None).unwrap();
|
||||
assert!(jdb.exists(&foo));
|
||||
assert!(jdb.exists(&bar));
|
||||
|
||||
jdb.remove(&foo);
|
||||
let baz = jdb.insert(b"baz");
|
||||
jdb.commit(1, &b"1a".sha3(), Some((0, b"0".sha3()))).unwrap();
|
||||
|
||||
jdb.remove(&bar);
|
||||
jdb.commit(1, &b"1b".sha3(), Some((0, b"0".sha3()))).unwrap();
|
||||
|
||||
assert!(jdb.exists(&foo));
|
||||
assert!(jdb.exists(&bar));
|
||||
assert!(jdb.exists(&baz));
|
||||
|
||||
jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap();
|
||||
assert!(jdb.exists(&foo));
|
||||
assert!(!jdb.exists(&baz));
|
||||
assert!(!jdb.exists(&bar));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
use common::*;
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn clean(s: &str) -> &str {
|
||||
if s.len() >= 2 && &s[0..2] == "0x" {
|
||||
&s[2..]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![warn(missing_docs)]
|
||||
#![feature(op_assign_traits)]
|
||||
#![feature(augmented_assignments)]
|
||||
#![feature(associated_consts)]
|
||||
#![feature(wrapping)]
|
||||
//! Ethcore-util library
|
||||
//!
|
||||
//! ### Rust version:
|
||||
@@ -53,33 +53,46 @@ extern crate arrayvec;
|
||||
extern crate elastic_array;
|
||||
extern crate crossbeam;
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod standard;
|
||||
#[macro_use]
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod from_json;
|
||||
#[macro_use]
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod common;
|
||||
pub mod error;
|
||||
pub mod hash;
|
||||
pub mod uint;
|
||||
pub mod bytes;
|
||||
pub mod rlp;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod misc;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod json_aid;
|
||||
pub mod vector;
|
||||
pub mod sha3;
|
||||
pub mod hashdb;
|
||||
pub mod memorydb;
|
||||
pub mod overlaydb;
|
||||
pub mod journaldb;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod math;
|
||||
pub mod chainfilter;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod crypto;
|
||||
pub mod triehash;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod trie;
|
||||
pub mod nibbleslice;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod heapsizeof;
|
||||
pub mod squeeze;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod semantic_version;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod io;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod network;
|
||||
|
||||
pub use common::*;
|
||||
@@ -89,6 +102,7 @@ pub use rlp::*;
|
||||
pub use hashdb::*;
|
||||
pub use memorydb::*;
|
||||
pub use overlaydb::*;
|
||||
pub use journaldb::*;
|
||||
pub use math::*;
|
||||
pub use chainfilter::*;
|
||||
pub use crypto::*;
|
||||
|
||||
@@ -107,12 +107,14 @@ impl MemoryDB {
|
||||
self.data.get(key)
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn drain(&mut self) -> HashMap<H256, (Bytes, i32)> {
|
||||
let mut data = HashMap::new();
|
||||
mem::swap(&mut self.data, &mut data);
|
||||
data
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn denote(&self, key: &H256, value: Bytes) -> &(Bytes, i32) {
|
||||
if self.raw(key) == None {
|
||||
unsafe {
|
||||
|
||||
@@ -3,9 +3,13 @@ use common::*;
|
||||
#[derive(Debug,Clone,PartialEq,Eq)]
|
||||
/// Diff type for specifying a change (or not).
|
||||
pub enum Diff<T> where T: Eq {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Same,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Born(T),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Changed(T, T),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Died(T),
|
||||
}
|
||||
|
||||
@@ -26,6 +30,8 @@ impl<T> Diff<T> where T: Eq {
|
||||
#[derive(PartialEq,Eq,Clone,Copy)]
|
||||
/// Boolean type for clean/dirty status.
|
||||
pub enum Filth {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Clean,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Dirty,
|
||||
}
|
||||
|
||||
@@ -56,12 +56,19 @@ mod service;
|
||||
mod error;
|
||||
mod node;
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use network::host::PeerId;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use network::host::PacketId;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use network::host::NetworkContext;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use network::service::NetworkService;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use network::host::NetworkIoMessage;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use network::host::NetworkIoMessage::User as UserMessage;
|
||||
/// TODO [arkpar] Please document me
|
||||
pub use network::error::NetworkError;
|
||||
|
||||
use io::TimerToken;
|
||||
|
||||
@@ -34,6 +34,7 @@ pub struct NibbleSlice<'a> {
|
||||
offset_encode_suffix: usize,
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub struct NibbleSliceIterator<'a> {
|
||||
p: &'a NibbleSlice<'a>,
|
||||
i: usize,
|
||||
@@ -76,6 +77,7 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
|
||||
(r, a.len() + b.len())
|
||||
}*/
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn iter(&'a self) -> NibbleSliceIterator<'a> {
|
||||
NibbleSliceIterator { p: self, i: 0 }
|
||||
}
|
||||
@@ -130,6 +132,7 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
|
||||
i
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn encoded(&self, is_leaf: bool) -> Bytes {
|
||||
let l = self.len();
|
||||
let mut r = Bytes::with_capacity(l / 2 + 1);
|
||||
@@ -142,6 +145,7 @@ impl<'a, 'view> NibbleSlice<'a> where 'a: 'view {
|
||||
r
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub fn encoded_leftmost(&self, n: usize, is_leaf: bool) -> Bytes {
|
||||
let l = min(self.len(), n);
|
||||
let mut r = Bytes::with_capacity(l / 2 + 1);
|
||||
|
||||
@@ -15,11 +15,11 @@ use rocksdb::{DB, Writable, IteratorMode};
|
||||
#[derive(Clone)]
|
||||
/// Implementation of the HashDB trait for a disk-backed database with a memory overlay.
|
||||
///
|
||||
/// The operations `insert()` and `kill()` take place on the memory overlay; batches of
|
||||
/// The operations `insert()` and `remove()` take place on the memory overlay; batches of
|
||||
/// such operations may be flushed to the disk-backed DB with `commit()` or discarded with
|
||||
/// `revert()`.
|
||||
///
|
||||
/// `lookup()` and `exists()` maintain normal behaviour - all `insert()` and `kill()`
|
||||
/// `lookup()` and `contains()` maintain normal behaviour - all `insert()` and `remove()`
|
||||
/// queries have an immediate effect in terms of these functions.
|
||||
pub struct OverlayDB {
|
||||
overlay: MemoryDB,
|
||||
@@ -28,8 +28,11 @@ pub struct OverlayDB {
|
||||
|
||||
impl OverlayDB {
|
||||
/// Create a new instance of OverlayDB given a `backing` database.
|
||||
pub fn new(backing: DB) -> OverlayDB {
|
||||
OverlayDB{ overlay: MemoryDB::new(), backing: Arc::new(backing) }
|
||||
pub fn new(backing: DB) -> OverlayDB { Self::new_with_arc(Arc::new(backing)) }
|
||||
|
||||
/// Create a new instance of OverlayDB given a `backing` database.
|
||||
pub fn new_with_arc(backing: Arc<DB>) -> OverlayDB {
|
||||
OverlayDB{ overlay: MemoryDB::new(), backing: backing }
|
||||
}
|
||||
|
||||
/// Create a new instance of OverlayDB with an anonymous temporary database.
|
||||
@@ -68,11 +71,10 @@ impl OverlayDB {
|
||||
/// ```
|
||||
pub fn commit(&mut self) -> Result<u32, UtilError> {
|
||||
let mut ret = 0u32;
|
||||
let mut deletes = 0usize;
|
||||
for i in self.overlay.drain().into_iter() {
|
||||
let (key, (value, rc)) = i;
|
||||
// until we figure out state trie pruning, only commit stuff when it has a strictly positive delkta of RCs -
|
||||
// this prevents RCs being reduced to 0 where the DB would pretent that the node had been removed.
|
||||
if rc > 0 {
|
||||
if rc != 0 {
|
||||
match self.payload(&key) {
|
||||
Some(x) => {
|
||||
let (back_value, back_rc) = x;
|
||||
@@ -80,7 +82,7 @@ impl OverlayDB {
|
||||
if total_rc < 0 {
|
||||
return Err(From::from(BaseDataError::NegativelyReferencedHash));
|
||||
}
|
||||
self.put_payload(&key, (back_value, total_rc as u32));
|
||||
deletes += if self.put_payload(&key, (back_value, total_rc as u32)) {1} else {0};
|
||||
}
|
||||
None => {
|
||||
if rc < 0 {
|
||||
@@ -92,6 +94,7 @@ impl OverlayDB {
|
||||
ret += 1;
|
||||
}
|
||||
}
|
||||
trace!("OverlayDB::commit() deleted {} nodes", deletes);
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
@@ -129,11 +132,18 @@ impl OverlayDB {
|
||||
}
|
||||
|
||||
/// Get the refs and value of the given key.
|
||||
fn put_payload(&self, key: &H256, payload: (Bytes, u32)) {
|
||||
let mut s = RlpStream::new_list(2);
|
||||
s.append(&payload.1);
|
||||
s.append(&payload.0);
|
||||
self.backing.put(&key.bytes(), &s.out()).expect("Low-level database error. Some issue with your hard disk?");
|
||||
fn put_payload(&self, key: &H256, payload: (Bytes, u32)) -> bool {
|
||||
if payload.1 > 0 {
|
||||
let mut s = RlpStream::new_list(2);
|
||||
s.append(&payload.1);
|
||||
s.append(&payload.0);
|
||||
self.backing.put(&key.bytes(), s.as_raw()).expect("Low-level database error. Some issue with your hard disk?");
|
||||
false
|
||||
} else {
|
||||
self.backing.delete(&key.bytes()).expect("Low-level database error. Some issue with your hard disk?");
|
||||
true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,10 +30,15 @@
|
||||
//! * You want to get view onto rlp-slice.
|
||||
//! * You don't want to decode whole rlp at once.
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod rlptraits;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod rlperrors;
|
||||
/// TODO [debris] Please document me
|
||||
pub mod rlpin;
|
||||
/// TODO [debris] Please document me
|
||||
pub mod untrusted_rlp;
|
||||
/// TODO [debris] Please document me
|
||||
pub mod rlpstream;
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -46,9 +51,13 @@ pub use self::rlpin::{Rlp, RlpIterator};
|
||||
pub use self::rlpstream::{RlpStream,RlpStandard};
|
||||
use super::hash::H256;
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
pub const NULL_RLP: [u8; 1] = [0x80; 1];
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub const EMPTY_LIST_RLP: [u8; 1] = [0xC0; 1];
|
||||
/// TODO [arkpar] Please document me
|
||||
pub const SHA3_NULL_RLP: H256 = H256( [0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21] );
|
||||
/// TODO [debris] Please document me
|
||||
pub const SHA3_EMPTY_LIST_RLP: H256 = H256( [0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7, 0x5d, 0x7a, 0xab, 0x85, 0xb5, 0x67, 0xb6, 0xcc, 0xd4, 0x1a, 0xd3, 0x12, 0x45, 0x1b, 0x94, 0x8a, 0x74, 0x13, 0xf0, 0xa1, 0x42, 0xfd, 0x40, 0xd4, 0x93, 0x47] );
|
||||
|
||||
/// Shortcut function to decode trusted rlp
|
||||
|
||||
@@ -3,14 +3,23 @@ use std::error::Error as StdError;
|
||||
use bytes::FromBytesError;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
/// TODO [debris] Please document me
|
||||
pub enum DecoderError {
|
||||
/// TODO [debris] Please document me
|
||||
FromBytesError(FromBytesError),
|
||||
/// TODO [debris] Please document me
|
||||
RlpIsTooShort,
|
||||
/// TODO [debris] Please document me
|
||||
RlpExpectedToBeList,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
RlpExpectedToBeData,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
RlpIncorrectListLen,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
RlpDataLenWithZeroPrefix,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
RlpListLenWithZeroPrefix,
|
||||
/// TODO [debris] Please document me
|
||||
RlpInvalidIndirection,
|
||||
}
|
||||
|
||||
|
||||
@@ -103,10 +103,12 @@ impl <'a, 'view> Rlp<'a> where 'a: 'view {
|
||||
res.unwrap_or_else(|_| panic!())
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub fn as_val<T>(&self) -> T where T: Decodable {
|
||||
Self::view_as_val(self)
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub fn val_at<T>(&self, index: usize) -> T where T: Decodable {
|
||||
Self::view_as_val(&self.at(index))
|
||||
}
|
||||
|
||||
@@ -142,6 +142,14 @@ impl RlpStream {
|
||||
self.note_appended(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Drain the object and return the underlying ElasticArray.
|
||||
pub fn drain(self) -> ElasticArray1024<u8> {
|
||||
match self.is_finished() {
|
||||
true => self.encoder.bytes,
|
||||
false => panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BasicEncoder {
|
||||
@@ -215,15 +223,19 @@ impl Encoder for BasicEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub trait RlpStandard {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn rlp_append(&self, s: &mut RlpStream);
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn rlp_bytes(&self) -> Bytes {
|
||||
let mut s = RlpStream::new();
|
||||
self.rlp_append(&mut s);
|
||||
s.out()
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn rlp_sha3(&self) -> H256 { self.rlp_bytes().sha3() }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,36 @@
|
||||
use rlp::{DecoderError, UntrustedRlp};
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub trait Decoder: Sized {
|
||||
/// TODO [debris] Please document me
|
||||
fn read_value<T, F>(&self, f: F) -> Result<T, DecoderError>
|
||||
where F: FnOnce(&[u8]) -> Result<T, DecoderError>;
|
||||
|
||||
/// TODO [arkpar] Please document me
|
||||
fn as_list(&self) -> Result<Vec<Self>, DecoderError>;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn as_rlp<'a>(&'a self) -> &'a UntrustedRlp<'a>;
|
||||
/// TODO [debris] Please document me
|
||||
fn as_raw(&self) -> &[u8];
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub trait Decodable: Sized {
|
||||
/// TODO [debris] Please document me
|
||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder;
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub trait View<'a, 'view>: Sized {
|
||||
/// TODO [debris] Please document me
|
||||
type Prototype;
|
||||
/// TODO [debris] Please document me
|
||||
type PayloadInfo;
|
||||
/// TODO [debris] Please document me
|
||||
type Data;
|
||||
/// TODO [debris] Please document me
|
||||
type Item;
|
||||
/// TODO [debris] Please document me
|
||||
type Iter;
|
||||
|
||||
/// Creates a new instance of `Rlp` reader
|
||||
@@ -41,8 +54,10 @@ pub trait View<'a, 'view>: Sized {
|
||||
/// Get the prototype of the RLP.
|
||||
fn prototype(&self) -> Self::Prototype;
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn payload_info(&self) -> Self::PayloadInfo;
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn data(&'view self) -> Self::Data;
|
||||
|
||||
/// Returns number of RLP items.
|
||||
@@ -179,21 +194,30 @@ pub trait View<'a, 'view>: Sized {
|
||||
/// ```
|
||||
fn iter(&'view self) -> Self::Iter;
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn as_val<T>(&self) -> Result<T, DecoderError> where T: Decodable;
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn val_at<T>(&self, index: usize) -> Result<T, DecoderError> where T: Decodable;
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub trait Encoder {
|
||||
/// TODO [debris] Please document me
|
||||
fn emit_value(&mut self, bytes: &[u8]) -> ();
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> ();
|
||||
/// TODO [debris] Please document me
|
||||
fn emit_raw(&mut self, bytes: &[u8]) -> ();
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub trait Encodable {
|
||||
/// TODO [debris] Please document me
|
||||
fn encode<E>(&self, encoder: &mut E) -> () where E: Encoder;
|
||||
}
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub trait Stream: Sized {
|
||||
|
||||
/// Initializes instance of empty `Stream`.
|
||||
@@ -284,6 +308,7 @@ pub trait Stream: Sized {
|
||||
/// }
|
||||
fn is_finished(&self) -> bool;
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn as_raw(&self) -> &[u8];
|
||||
|
||||
/// Streams out encoded bytes.
|
||||
|
||||
@@ -21,15 +21,21 @@ impl OffsetCache {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// TODO [debris] Please document me
|
||||
pub enum Prototype {
|
||||
/// TODO [debris] Please document me
|
||||
Null,
|
||||
/// TODO [debris] Please document me
|
||||
Data(usize),
|
||||
/// TODO [debris] Please document me
|
||||
List(usize),
|
||||
}
|
||||
|
||||
/// Stores basic information about item
|
||||
pub struct PayloadInfo {
|
||||
/// TODO [debris] Please document me
|
||||
pub header_len: usize,
|
||||
/// TODO [debris] Please document me
|
||||
pub value_len: usize,
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use bytes::{BytesConvertable, Populatable};
|
||||
use hash::{H256, FixedHash};
|
||||
use self::sha3_ext::*;
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub const SHA3_EMPTY: H256 = H256( [0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, 0xe5, 0x00, 0xb6, 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70] );
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ use heapsize::HeapSizeOf;
|
||||
|
||||
/// Should be used to squeeze collections to certain size in bytes
|
||||
pub trait Squeeze {
|
||||
/// TODO [debris] Please document me
|
||||
fn squeeze(&mut self, size: usize);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod trietraits;
|
||||
pub mod standardmap;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod journal;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod node;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod triedb;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod triedbmut;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod sectriedb;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub mod sectriedbmut;
|
||||
|
||||
pub use self::trietraits::*;
|
||||
|
||||
@@ -7,9 +7,13 @@ use super::journal::*;
|
||||
/// Type of node in the trie and essential information thereof.
|
||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||
pub enum Node<'a> {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Empty,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Leaf(NibbleSlice<'a>, &'a[u8]),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Extension(NibbleSlice<'a>, &'a[u8]),
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Branch([&'a[u8]; 16], Option<&'a [u8]>)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,13 @@ use hash::*;
|
||||
|
||||
/// Alphabet to use when creating words for insertion into tries.
|
||||
pub enum Alphabet {
|
||||
/// TODO [Gav Wood] Please document me
|
||||
All,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Low,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Mid,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
Custom(Bytes),
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ use super::node::*;
|
||||
pub struct TrieDB<'db> {
|
||||
db: &'db HashDB,
|
||||
root: &'db H256,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub hash_count: usize,
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ use super::trietraits::*;
|
||||
pub struct TrieDBMut<'db> {
|
||||
db: &'db mut HashDB,
|
||||
root: &'db mut H256,
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub hash_count: usize,
|
||||
}
|
||||
|
||||
|
||||
245
util/src/uint.rs
245
util/src/uint.rs
@@ -23,7 +23,6 @@
|
||||
|
||||
use standard::*;
|
||||
use from_json::*;
|
||||
use std::num::wrapping::OverflowingOps;
|
||||
|
||||
macro_rules! impl_map_from {
|
||||
($thing:ident, $from:ty, $to:ty) => {
|
||||
@@ -59,15 +58,20 @@ macro_rules! panic_on_overflow {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub trait Uint: Sized + Default + FromStr + From<u64> + FromJson + fmt::Debug + fmt::Display + PartialOrd + Ord + PartialEq + Eq + Hash {
|
||||
|
||||
/// Size of this type.
|
||||
const SIZE: usize;
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn zero() -> Self;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn one() -> Self;
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
type FromDecStrErr;
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn from_dec_str(value: &str) -> Result<Self, Self::FromDecStrErr>;
|
||||
|
||||
/// Conversion to u32
|
||||
@@ -97,6 +101,28 @@ pub trait Uint: Sized + Default + FromStr + From<u64> + FromJson + fmt::Debug +
|
||||
fn pow(self, other: Self) -> Self;
|
||||
/// Return wrapped eponentation `self**other` and flag if there was an overflow
|
||||
fn overflowing_pow(self, other: Self) -> (Self, bool);
|
||||
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn overflowing_add(self, other: Self) -> (Self, bool);
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn overflowing_sub(self, other: Self) -> (Self, bool);
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn overflowing_mul(self, other: Self) -> (Self, bool);
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn overflowing_div(self, other: Self) -> (Self, bool);
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn overflowing_rem(self, other: Self) -> (Self, bool);
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
fn overflowing_neg(self) -> (Self, bool);
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
fn overflowing_shl(self, shift: u32) -> (Self, bool);
|
||||
}
|
||||
|
||||
macro_rules! construct_uint {
|
||||
@@ -259,6 +285,98 @@ macro_rules! construct_uint {
|
||||
let res = overflowing!(x.overflowing_mul(y), overflow);
|
||||
(res, overflow)
|
||||
}
|
||||
|
||||
fn overflowing_add(self, other: $name) -> ($name, bool) {
|
||||
let $name(ref me) = self;
|
||||
let $name(ref you) = other;
|
||||
let mut ret = [0u64; $n_words];
|
||||
let mut carry = [0u64; $n_words];
|
||||
let mut b_carry = false;
|
||||
let mut overflow = false;
|
||||
|
||||
for i in 0..$n_words {
|
||||
ret[i] = me[i].wrapping_add(you[i]);
|
||||
|
||||
if ret[i] < me[i] {
|
||||
if i < $n_words - 1 {
|
||||
carry[i + 1] = 1;
|
||||
b_carry = true;
|
||||
} else {
|
||||
overflow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if b_carry {
|
||||
let ret = overflowing!($name(ret).overflowing_add($name(carry)), overflow);
|
||||
(ret, overflow)
|
||||
} else {
|
||||
($name(ret), overflow)
|
||||
}
|
||||
}
|
||||
|
||||
fn overflowing_sub(self, other: $name) -> ($name, bool) {
|
||||
let res = overflowing!((!other).overflowing_add(From::from(1u64)));
|
||||
let res = overflowing!(self.overflowing_add(res));
|
||||
(res, self < other)
|
||||
}
|
||||
|
||||
fn overflowing_mul(self, other: $name) -> ($name, bool) {
|
||||
let mut res = $name::from(0u64);
|
||||
let mut overflow = false;
|
||||
// TODO: be more efficient about this
|
||||
for i in 0..(2 * $n_words) {
|
||||
let v = overflowing!(self.overflowing_mul_u32((other >> (32 * i)).low_u32()), overflow);
|
||||
let res2 = overflowing!(v.overflowing_shl(32 * i as u32), overflow);
|
||||
res = overflowing!(res.overflowing_add(res2), overflow);
|
||||
}
|
||||
(res, overflow)
|
||||
}
|
||||
|
||||
fn overflowing_div(self, other: $name) -> ($name, bool) {
|
||||
(self / other, false)
|
||||
}
|
||||
|
||||
fn overflowing_rem(self, other: $name) -> ($name, bool) {
|
||||
(self % other, false)
|
||||
}
|
||||
|
||||
fn overflowing_neg(self) -> ($name, bool) {
|
||||
(!self, true)
|
||||
}
|
||||
|
||||
fn overflowing_shl(self, shift32: u32) -> ($name, bool) {
|
||||
let $name(ref original) = self;
|
||||
let mut ret = [0u64; $n_words];
|
||||
let shift = shift32 as usize;
|
||||
let word_shift = shift / 64;
|
||||
let bit_shift = shift % 64;
|
||||
for i in 0..$n_words {
|
||||
// Shift
|
||||
if i + word_shift < $n_words {
|
||||
ret[i + word_shift] += original[i] << bit_shift;
|
||||
}
|
||||
// Carry
|
||||
if bit_shift > 0 && i + word_shift + 1 < $n_words {
|
||||
ret[i + word_shift + 1] += original[i] >> (64 - bit_shift);
|
||||
}
|
||||
}
|
||||
// Detecting overflow
|
||||
let last = $n_words - word_shift - if bit_shift > 0 { 1 } else { 0 };
|
||||
let overflow = if bit_shift > 0 {
|
||||
(original[last] >> (64 - bit_shift)) > 0
|
||||
} else if word_shift > 0 {
|
||||
original[last] > 0
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
for i in last+1..$n_words-1 {
|
||||
if original[i] > 0 {
|
||||
return ($name(ret), true);
|
||||
}
|
||||
}
|
||||
($name(ret), overflow)
|
||||
}
|
||||
}
|
||||
|
||||
impl $name {
|
||||
@@ -390,105 +508,6 @@ macro_rules! construct_uint {
|
||||
}
|
||||
}
|
||||
|
||||
impl OverflowingOps for $name {
|
||||
fn overflowing_add(self, other: $name) -> ($name, bool) {
|
||||
let $name(ref me) = self;
|
||||
let $name(ref you) = other;
|
||||
let mut ret = [0u64; $n_words];
|
||||
let mut carry = [0u64; $n_words];
|
||||
let mut b_carry = false;
|
||||
let mut overflow = false;
|
||||
|
||||
for i in 0..$n_words {
|
||||
ret[i] = me[i].wrapping_add(you[i]);
|
||||
|
||||
if ret[i] < me[i] {
|
||||
if i < $n_words - 1 {
|
||||
carry[i + 1] = 1;
|
||||
b_carry = true;
|
||||
} else {
|
||||
overflow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if b_carry {
|
||||
let ret = overflowing!($name(ret).overflowing_add($name(carry)), overflow);
|
||||
(ret, overflow)
|
||||
} else {
|
||||
($name(ret), overflow)
|
||||
}
|
||||
}
|
||||
|
||||
fn overflowing_sub(self, other: $name) -> ($name, bool) {
|
||||
let res = overflowing!((!other).overflowing_add(From::from(1u64)));
|
||||
let res = overflowing!(self.overflowing_add(res));
|
||||
(res, self < other)
|
||||
}
|
||||
|
||||
fn overflowing_mul(self, other: $name) -> ($name, bool) {
|
||||
let mut res = $name::from(0u64);
|
||||
let mut overflow = false;
|
||||
// TODO: be more efficient about this
|
||||
for i in 0..(2 * $n_words) {
|
||||
let v = overflowing!(self.overflowing_mul_u32((other >> (32 * i)).low_u32()), overflow);
|
||||
let res2 = overflowing!(v.overflowing_shl(32 * i as u32), overflow);
|
||||
res = overflowing!(res.overflowing_add(res2), overflow);
|
||||
}
|
||||
(res, overflow)
|
||||
}
|
||||
|
||||
fn overflowing_div(self, other: $name) -> ($name, bool) {
|
||||
(self / other, false)
|
||||
}
|
||||
|
||||
fn overflowing_rem(self, other: $name) -> ($name, bool) {
|
||||
(self % other, false)
|
||||
}
|
||||
|
||||
fn overflowing_neg(self) -> ($name, bool) {
|
||||
(!self, true)
|
||||
}
|
||||
|
||||
fn overflowing_shl(self, shift32: u32) -> ($name, bool) {
|
||||
let $name(ref original) = self;
|
||||
let mut ret = [0u64; $n_words];
|
||||
let shift = shift32 as usize;
|
||||
let word_shift = shift / 64;
|
||||
let bit_shift = shift % 64;
|
||||
for i in 0..$n_words {
|
||||
// Shift
|
||||
if i + word_shift < $n_words {
|
||||
ret[i + word_shift] += original[i] << bit_shift;
|
||||
}
|
||||
// Carry
|
||||
if bit_shift > 0 && i + word_shift + 1 < $n_words {
|
||||
ret[i + word_shift + 1] += original[i] >> (64 - bit_shift);
|
||||
}
|
||||
}
|
||||
// Detecting overflow
|
||||
let last = $n_words - word_shift - if bit_shift > 0 { 1 } else { 0 };
|
||||
let overflow = if bit_shift > 0 {
|
||||
(original[last] >> (64 - bit_shift)) > 0
|
||||
} else if word_shift > 0 {
|
||||
original[last] > 0
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
for i in last+1..$n_words-1 {
|
||||
if original[i] > 0 {
|
||||
return ($name(ret), true);
|
||||
}
|
||||
}
|
||||
($name(ret), overflow)
|
||||
}
|
||||
|
||||
fn overflowing_shr(self, _shift32: u32) -> ($name, bool) {
|
||||
// TODO [todr] not used for now
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<$name> for $name {
|
||||
type Output = $name;
|
||||
|
||||
@@ -907,15 +926,17 @@ impl From<U256> for u32 {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub const ZERO_U256: U256 = U256([0x00u64; 4]);
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub const ONE_U256: U256 = U256([0x01u64, 0x00u64, 0x00u64, 0x00u64]);
|
||||
/// TODO [Gav Wood] Please document me
|
||||
pub const BAD_U256: U256 = U256([0xffffffffffffffffu64; 4]);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use uint::{Uint, U128, U256, U512};
|
||||
use std::str::FromStr;
|
||||
use std::num::wrapping::OverflowingOps;
|
||||
|
||||
#[test]
|
||||
pub fn assign_ops() {
|
||||
@@ -1297,28 +1318,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
pub fn uint256_shr_overflow() {
|
||||
assert_eq!(
|
||||
U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()
|
||||
.overflowing_shr(4),
|
||||
(U256::from_str("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), true)
|
||||
);
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
pub fn uint256_shr_overflow2() {
|
||||
assert_eq!(
|
||||
U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0").unwrap()
|
||||
.overflowing_shr(4),
|
||||
(U256::from_str("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), false)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[test]
|
||||
pub fn uint256_mul() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
use std::ptr;
|
||||
|
||||
/// TODO [debris] Please document me
|
||||
pub trait InsertSlice<T> {
|
||||
/// TODO [debris] Please document me
|
||||
fn insert_slice(&mut self, index: usize, elements: &[T]);
|
||||
}
|
||||
|
||||
@@ -47,6 +49,7 @@ impl<T> InsertSlice<T> for Vec<T> {
|
||||
/// }
|
||||
/// ```
|
||||
pub trait SharedPrefix <T> {
|
||||
/// TODO [debris] Please document me
|
||||
fn shared_prefix_len(&self, elem: &[T]) -> usize;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user