Cleanup HTTP APIs, update ports to avoid gap, rustfmt
Moved the HTTP APIs away from the REST endpoint abstraction and to simpler Hyper handlers. Re-established all routes as v1. Changed wallet receiver port to 13415 to avoid a gap in port numbers. Finally, rustfmt seems to have ignored specific files arguments, running on everything.
This commit is contained in:
+19
-22
@@ -28,7 +28,7 @@ use core::target::Difficulty;
|
||||
pub const GRIN_BASE: u64 = 1_000_000_000;
|
||||
|
||||
/// The block subsidy amount
|
||||
pub const REWARD: u64 = 50*GRIN_BASE;
|
||||
pub const REWARD: u64 = 50 * GRIN_BASE;
|
||||
|
||||
/// Actual block reward for a given total fee amount
|
||||
pub fn reward(fee: u64) -> u64 {
|
||||
@@ -80,8 +80,8 @@ pub const MAX_BLOCK_WEIGHT: usize = 80_000;
|
||||
|
||||
/// Whether a block exceeds the maximum acceptable weight
|
||||
pub fn exceeds_weight(input_len: usize, output_len: usize, kernel_len: usize) -> bool {
|
||||
input_len * BLOCK_INPUT_WEIGHT + output_len * BLOCK_OUTPUT_WEIGHT +
|
||||
kernel_len * BLOCK_KERNEL_WEIGHT > MAX_BLOCK_WEIGHT
|
||||
input_len * BLOCK_INPUT_WEIGHT + output_len * BLOCK_OUTPUT_WEIGHT
|
||||
+ kernel_len * BLOCK_KERNEL_WEIGHT > MAX_BLOCK_WEIGHT
|
||||
}
|
||||
|
||||
/// Fork every 250,000 blocks for first 2 years, simple number and just a
|
||||
@@ -150,9 +150,8 @@ pub fn next_difficulty<T>(cursor: T) -> Result<Difficulty, TargetError>
|
||||
where
|
||||
T: IntoIterator<Item = Result<(u64, Difficulty), TargetError>>,
|
||||
{
|
||||
|
||||
// Block times at the begining and end of the adjustment window, used to
|
||||
// calculate medians later.
|
||||
// calculate medians later.
|
||||
let mut window_begin = vec![];
|
||||
let mut window_end = vec![];
|
||||
|
||||
@@ -165,8 +164,8 @@ where
|
||||
let (ts, diff) = head_info?;
|
||||
|
||||
// Sum each element in the adjustment window. In addition, retain
|
||||
// timestamps within median windows (at ]start;start-11] and ]end;end-11]
|
||||
// to later calculate medians.
|
||||
// timestamps within median windows (at ]start;start-11] and ]end;end-11]
|
||||
// to later calculate medians.
|
||||
if m < DIFFICULTY_ADJUST_WINDOW {
|
||||
diff_sum = diff_sum + diff;
|
||||
|
||||
@@ -204,9 +203,7 @@ where
|
||||
ts_damp
|
||||
};
|
||||
|
||||
Ok(
|
||||
diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW) / Difficulty::from_num(adj_ts),
|
||||
)
|
||||
Ok(diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW) / Difficulty::from_num(adj_ts))
|
||||
}
|
||||
|
||||
/// Consensus rule that collections of items are sorted lexicographically over the wire.
|
||||
@@ -225,7 +222,7 @@ mod test {
|
||||
use super::*;
|
||||
|
||||
// Builds an iterator for next difficulty calculation with the provided
|
||||
// constant time interval, difficulty and total length.
|
||||
// constant time interval, difficulty and total length.
|
||||
fn repeat(interval: u64, diff: u64, len: u64) -> Vec<Result<(u64, Difficulty), TargetError>> {
|
||||
// watch overflow here, length shouldn't be ridiculous anyhow
|
||||
assert!(len < std::usize::MAX as u64);
|
||||
@@ -336,15 +333,15 @@ mod test {
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn hard_fork_2() {
|
||||
// assert!(valid_header_version(0, 1));
|
||||
// assert!(valid_header_version(10, 1));
|
||||
// assert!(valid_header_version(10, 2));
|
||||
// assert!(valid_header_version(250_000, 1));
|
||||
// assert!(!valid_header_version(250_001, 1));
|
||||
// assert!(!valid_header_version(500_000, 1));
|
||||
// assert!(valid_header_version(250_001, 2));
|
||||
// assert!(valid_header_version(500_000, 2));
|
||||
// assert!(!valid_header_version(500_001, 2));
|
||||
// }
|
||||
// fn hard_fork_2() {
|
||||
// assert!(valid_header_version(0, 1));
|
||||
// assert!(valid_header_version(10, 1));
|
||||
// assert!(valid_header_version(10, 2));
|
||||
// assert!(valid_header_version(250_000, 1));
|
||||
// assert!(!valid_header_version(250_001, 1));
|
||||
// assert!(!valid_header_version(500_000, 1));
|
||||
// assert!(valid_header_version(250_001, 2));
|
||||
// assert!(valid_header_version(500_000, 2));
|
||||
// assert!(!valid_header_version(500_001, 2));
|
||||
// }
|
||||
}
|
||||
|
||||
+29
-29
@@ -20,12 +20,12 @@ use util::secp::{self, Secp256k1};
|
||||
use std::collections::HashSet;
|
||||
|
||||
use core::Committed;
|
||||
use core::{Input, Output, SwitchCommitHash, Proof, TxKernel, Transaction, COINBASE_KERNEL,
|
||||
use core::{Input, Output, Proof, SwitchCommitHash, Transaction, TxKernel, COINBASE_KERNEL,
|
||||
COINBASE_OUTPUT};
|
||||
use consensus::{MINIMUM_DIFFICULTY, REWARD, reward, exceeds_weight};
|
||||
use consensus::{exceeds_weight, reward, MINIMUM_DIFFICULTY, REWARD};
|
||||
use core::hash::{Hash, Hashed, ZERO_HASH};
|
||||
use core::target::Difficulty;
|
||||
use ser::{self, Readable, Reader, Writeable, Writer, WriteableSorted, read_and_verify_sorted};
|
||||
use ser::{self, read_and_verify_sorted, Readable, Reader, Writeable, WriteableSorted, Writer};
|
||||
use util::LOGGER;
|
||||
use global;
|
||||
use keychain;
|
||||
@@ -282,9 +282,8 @@ impl Block {
|
||||
reward_out: Output,
|
||||
reward_kern: TxKernel,
|
||||
) -> Result<Block, secp::Error> {
|
||||
|
||||
// note: the following reads easily but may not be the most efficient due to
|
||||
// repeated iterations, revisit if a problem
|
||||
// repeated iterations, revisit if a problem
|
||||
let secp = Secp256k1::with_caps(secp::ContextFlag::Commit);
|
||||
|
||||
// validate each transaction and gather their kernels
|
||||
@@ -292,8 +291,8 @@ impl Block {
|
||||
kernels.push(reward_kern);
|
||||
|
||||
// build vectors with all inputs and all outputs, ordering them by hash
|
||||
// needs to be a fold so we don't end up with a vector of vectors and we
|
||||
// want to fully own the refs (not just a pointer like flat_map).
|
||||
// needs to be a fold so we don't end up with a vector of vectors and we
|
||||
// want to fully own the refs (not just a pointer like flat_map).
|
||||
let inputs = txs.iter().fold(vec![], |mut acc, ref tx| {
|
||||
let mut inputs = tx.inputs.clone();
|
||||
acc.append(&mut inputs);
|
||||
@@ -317,8 +316,8 @@ impl Block {
|
||||
..time::now_utc()
|
||||
},
|
||||
previous: prev.hash(),
|
||||
total_difficulty: prev.pow.clone().to_difficulty() +
|
||||
prev.total_difficulty.clone(),
|
||||
total_difficulty: prev.pow.clone().to_difficulty()
|
||||
+ prev.total_difficulty.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
inputs: inputs,
|
||||
@@ -439,7 +438,9 @@ impl Block {
|
||||
}
|
||||
|
||||
if k.lock_height > self.header.height {
|
||||
return Err(Error::KernelLockHeight { lock_height: k.lock_height });
|
||||
return Err(Error::KernelLockHeight {
|
||||
lock_height: k.lock_height,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,18 +466,17 @@ impl Block {
|
||||
}
|
||||
|
||||
// Validate the coinbase outputs generated by miners. Entails 2 main checks:
|
||||
//
|
||||
// * That the sum of all coinbase-marked outputs equal the supply.
|
||||
// * That the sum of blinding factors for all coinbase-marked outputs match
|
||||
// the coinbase-marked kernels.
|
||||
//
|
||||
// * That the sum of all coinbase-marked outputs equal the supply.
|
||||
// * That the sum of blinding factors for all coinbase-marked outputs match
|
||||
// the coinbase-marked kernels.
|
||||
fn verify_coinbase(&self, secp: &Secp256k1) -> Result<(), Error> {
|
||||
let cb_outs = filter_map_vec!(self.outputs, |out| if out.features.contains(
|
||||
COINBASE_OUTPUT,
|
||||
)
|
||||
{
|
||||
Some(out.commitment())
|
||||
} else {
|
||||
None
|
||||
let cb_outs = filter_map_vec!(self.outputs, |out| {
|
||||
if out.features.contains(COINBASE_OUTPUT) {
|
||||
Some(out.commitment())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let cb_kerns = filter_map_vec!(self.kernels, |k| if k.features.contains(COINBASE_KERNEL) {
|
||||
Some(k.excess)
|
||||
@@ -557,14 +557,14 @@ mod test {
|
||||
use util::secp;
|
||||
|
||||
// utility to create a block without worrying about the key or previous
|
||||
// header
|
||||
// header
|
||||
fn new_block(txs: Vec<&Transaction>, keychain: &Keychain) -> Block {
|
||||
let key_id = keychain.derive_key_id(1).unwrap();
|
||||
Block::new(&BlockHeader::default(), txs, keychain, &key_id).unwrap()
|
||||
}
|
||||
|
||||
// utility producing a transaction that spends an output with the provided
|
||||
// value and blinding key
|
||||
// value and blinding key
|
||||
fn txspend1i1o(
|
||||
v: u64,
|
||||
keychain: &Keychain,
|
||||
@@ -624,7 +624,7 @@ mod test {
|
||||
let b = new_block(vec![&mut btx1, &mut btx2, &mut btx3], &keychain);
|
||||
|
||||
// block should have been automatically compacted (including reward
|
||||
// output) and should still be valid
|
||||
// output) and should still be valid
|
||||
b.validate(&keychain.secp()).unwrap();
|
||||
assert_eq!(b.inputs.len(), 3);
|
||||
assert_eq!(b.outputs.len(), 3);
|
||||
@@ -632,7 +632,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
// builds 2 different blocks with a tx spending another and check if merging
|
||||
// occurs
|
||||
// occurs
|
||||
fn mergeable_blocks() {
|
||||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let key_id1 = keychain.derive_key_id(1).unwrap();
|
||||
@@ -685,14 +685,14 @@ mod test {
|
||||
assert_eq!(coinbase_kernels.len(), 1);
|
||||
|
||||
// the block should be valid here (single coinbase output with corresponding
|
||||
// txn kernel)
|
||||
// txn kernel)
|
||||
assert_eq!(b.validate(&keychain.secp()), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
// test that flipping the COINBASE_OUTPUT flag on the output features
|
||||
// invalidates the block and specifically it causes verify_coinbase to fail
|
||||
// additionally verifying the merkle_inputs_outputs also fails
|
||||
// invalidates the block and specifically it causes verify_coinbase to fail
|
||||
// additionally verifying the merkle_inputs_outputs also fails
|
||||
fn remove_coinbase_output_flag() {
|
||||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let mut b = new_block(vec![], &keychain);
|
||||
@@ -714,7 +714,7 @@ mod test {
|
||||
|
||||
#[test]
|
||||
// test that flipping the COINBASE_KERNEL flag on the kernel features
|
||||
// invalidates the block and specifically it causes verify_coinbase to fail
|
||||
// invalidates the block and specifically it causes verify_coinbase to fail
|
||||
fn remove_coinbase_kernel_flag() {
|
||||
let keychain = Keychain::from_random_seed().unwrap();
|
||||
let mut b = new_block(vec![], &keychain);
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
|
||||
use util::secp;
|
||||
|
||||
use core::{Transaction, Input, Output, SwitchCommitHash, DEFAULT_OUTPUT};
|
||||
use core::{Input, Output, SwitchCommitHash, Transaction, DEFAULT_OUTPUT};
|
||||
use core::transaction::kernel_sig_msg;
|
||||
use util::LOGGER;
|
||||
use keychain;
|
||||
use keychain::{Keychain, BlindSum, BlindingFactor, Identifier};
|
||||
use keychain::{BlindSum, BlindingFactor, Identifier, Keychain};
|
||||
|
||||
/// Context information available to transaction combinators.
|
||||
pub struct Context<'a> {
|
||||
@@ -40,7 +40,8 @@ pub struct Context<'a> {
|
||||
|
||||
/// Function type returned by the transaction combinators. Transforms a
|
||||
/// (Transaction, BlindSum) pair into another, provided some context.
|
||||
pub type Append = for<'a> Fn(&'a mut Context, (Transaction, BlindSum)) -> (Transaction, BlindSum);
|
||||
pub type Append = for<'a> Fn(&'a mut Context, (Transaction, BlindSum))
|
||||
-> (Transaction, BlindSum);
|
||||
|
||||
/// Adds an input with the provided value and blinding key to the transaction
|
||||
/// being built.
|
||||
@@ -132,10 +133,11 @@ pub fn transaction(
|
||||
keychain: &keychain::Keychain,
|
||||
) -> Result<(Transaction, BlindingFactor), keychain::Error> {
|
||||
let mut ctx = Context { keychain };
|
||||
let (mut tx, sum) = elems.iter().fold(
|
||||
(Transaction::empty(), BlindSum::new()),
|
||||
|acc, elem| elem(&mut ctx, acc),
|
||||
);
|
||||
let (mut tx, sum) = elems
|
||||
.iter()
|
||||
.fold((Transaction::empty(), BlindSum::new()), |acc, elem| {
|
||||
elem(&mut ctx, acc)
|
||||
});
|
||||
let blind_sum = ctx.keychain.blind_sum(&sum)?;
|
||||
let msg = secp::Message::from_slice(&kernel_sig_msg(tx.fee, tx.lock_height))?;
|
||||
let sig = ctx.keychain.sign_with_blinding(&msg, &blind_sum)?;
|
||||
|
||||
@@ -24,7 +24,7 @@ use std::convert::AsRef;
|
||||
use blake2::blake2b::Blake2b;
|
||||
|
||||
use consensus::VerifySortOrder;
|
||||
use ser::{self, Reader, Readable, Writer, Writeable, Error, AsFixedBytes};
|
||||
use ser::{self, AsFixedBytes, Error, Readable, Reader, Writeable, Writer};
|
||||
use util::LOGGER;
|
||||
|
||||
/// A hash consisting of all zeroes, used as a sentinel. No known preimage.
|
||||
@@ -153,7 +153,9 @@ impl HashWriter {
|
||||
|
||||
impl Default for HashWriter {
|
||||
fn default() -> HashWriter {
|
||||
HashWriter { state: Blake2b::new(32) }
|
||||
HashWriter {
|
||||
state: Blake2b::new(32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,19 +175,19 @@ pub trait Hashed {
|
||||
/// Obtain the hash of the object
|
||||
fn hash(&self) -> Hash;
|
||||
/// Hash the object together with another writeable object
|
||||
fn hash_with<T: Writeable>(&self, other:T) -> Hash;
|
||||
fn hash_with<T: Writeable>(&self, other: T) -> Hash;
|
||||
}
|
||||
|
||||
impl<W: ser::Writeable> Hashed for W {
|
||||
fn hash(&self) -> Hash {
|
||||
let mut hasher = HashWriter::default();
|
||||
ser::Writeable::write(self, &mut hasher).unwrap();
|
||||
ser::Writeable::write(self, &mut hasher).unwrap();
|
||||
let mut ret = [0; 32];
|
||||
hasher.finalize(&mut ret);
|
||||
Hash(ret)
|
||||
}
|
||||
|
||||
fn hash_with<T: Writeable>(&self, other:T) -> Hash{
|
||||
fn hash_with<T: Writeable>(&self, other: T) -> Hash {
|
||||
let mut hasher = HashWriter::default();
|
||||
ser::Writeable::write(self, &mut hasher).unwrap();
|
||||
trace!(LOGGER, "Hashing with additional data");
|
||||
@@ -202,7 +204,8 @@ impl<T: Writeable> VerifySortOrder<T> for Vec<T> {
|
||||
.map(|item| item.hash())
|
||||
.collect::<Vec<_>>()
|
||||
.windows(2)
|
||||
.any(|pair| pair[0] > pair[1]) {
|
||||
.any(|pair| pair[0] > pair[1])
|
||||
{
|
||||
true => Err(ser::Error::BadlySorted),
|
||||
false => Ok(()),
|
||||
}
|
||||
|
||||
+13
-11
@@ -31,8 +31,8 @@ use util::secp::pedersen::*;
|
||||
|
||||
pub use self::block::*;
|
||||
pub use self::transaction::*;
|
||||
use self::hash::{Hashed};
|
||||
use ser::{Writeable, Writer, Reader, Readable, Error};
|
||||
use self::hash::Hashed;
|
||||
use ser::{Error, Readable, Reader, Writeable, Writer};
|
||||
use global;
|
||||
// use keychain;
|
||||
|
||||
@@ -53,7 +53,7 @@ pub trait Committed {
|
||||
let mut output_commits = map_vec!(self.outputs_committed(), |out| out.commitment());
|
||||
|
||||
// add the overage as output commitment if positive, as an input commitment if
|
||||
// negative
|
||||
// negative
|
||||
let overage = self.overage();
|
||||
if overage != 0 {
|
||||
let over_commit = secp.commit_value(overage.abs() as u64).unwrap();
|
||||
@@ -186,11 +186,11 @@ impl Writeable for Proof {
|
||||
mod test {
|
||||
use super::*;
|
||||
use core::hash::ZERO_HASH;
|
||||
use core::build::{input, output, with_fee, initial_tx, with_excess, with_lock_height};
|
||||
use core::build::{initial_tx, input, output, with_excess, with_fee, with_lock_height};
|
||||
use core::block::Error::KernelLockHeight;
|
||||
use ser;
|
||||
use keychain;
|
||||
use keychain::{Keychain, BlindingFactor};
|
||||
use keychain::{BlindingFactor, Keychain};
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "InvalidSecretKey")]
|
||||
@@ -308,11 +308,11 @@ mod test {
|
||||
|
||||
{
|
||||
// Alice gets 2 of her pre-existing outputs to send 5 coins to Bob, they
|
||||
// become inputs in the new transaction
|
||||
// become inputs in the new transaction
|
||||
let (in1, in2) = (input(4, key_id1), input(3, key_id2));
|
||||
|
||||
// Alice builds her transaction, with change, which also produces the sum
|
||||
// of blinding factors before they're obscured.
|
||||
// of blinding factors before they're obscured.
|
||||
let (tx, sum) =
|
||||
build::transaction(vec![in1, in2, output(1, key_id3), with_fee(2)], &keychain)
|
||||
.unwrap();
|
||||
@@ -321,8 +321,8 @@ mod test {
|
||||
}
|
||||
|
||||
// From now on, Bob only has the obscured transaction and the sum of
|
||||
// blinding factors. He adds his output, finalizes the transaction so it's
|
||||
// ready for broadcast.
|
||||
// blinding factors. He adds his output, finalizes the transaction so it's
|
||||
// ready for broadcast.
|
||||
let (tx_final, _) = build::transaction(
|
||||
vec![
|
||||
initial_tx(tx_alice),
|
||||
@@ -382,7 +382,7 @@ mod test {
|
||||
let key_id3 = keychain.derive_key_id(3).unwrap();
|
||||
|
||||
// first check we can add a timelocked tx where lock height matches current block height
|
||||
// and that the resulting block is valid
|
||||
// and that the resulting block is valid
|
||||
let tx1 = build::transaction(
|
||||
vec![
|
||||
input(5, key_id1.clone()),
|
||||
@@ -421,7 +421,9 @@ mod test {
|
||||
&key_id3.clone(),
|
||||
).unwrap();
|
||||
match b.validate(keychain.secp()) {
|
||||
Err(KernelLockHeight { lock_height: height }) => {
|
||||
Err(KernelLockHeight {
|
||||
lock_height: height,
|
||||
}) => {
|
||||
assert_eq!(height, 2);
|
||||
}
|
||||
_ => panic!("expecting KernelLockHeight error here"),
|
||||
|
||||
+85
-75
@@ -119,7 +119,7 @@ where
|
||||
T: Summable + Hashed,
|
||||
{
|
||||
/// Create a hash sum from a summable
|
||||
pub fn from_summable<W: Writeable>(idx: u64, elmt: &T, hash_with:Option<W>) -> HashSum<T> {
|
||||
pub fn from_summable<W: Writeable>(idx: u64, elmt: &T, hash_with: Option<W>) -> HashSum<T> {
|
||||
let hash = match hash_with {
|
||||
Some(h) => elmt.hash_with(h),
|
||||
None => elmt.hash(),
|
||||
@@ -259,7 +259,7 @@ where
|
||||
|
||||
/// Push a new Summable element in the MMR. Computes new related peaks at
|
||||
/// the same time if applicable.
|
||||
pub fn push<W: Writeable>(&mut self, elmt: T, hash_with:Option<W>) -> Result<u64, String> {
|
||||
pub fn push<W: Writeable>(&mut self, elmt: T, hash_with: Option<W>) -> Result<u64, String> {
|
||||
let elmt_pos = self.last_pos + 1;
|
||||
let mut current_hashsum = HashSum::from_summable(elmt_pos, &elmt, hash_with);
|
||||
let mut to_append = vec![current_hashsum.clone()];
|
||||
@@ -267,14 +267,14 @@ where
|
||||
let mut pos = elmt_pos;
|
||||
|
||||
// we look ahead one position in the MMR, if the expected node has a higher
|
||||
// height it means we have to build a higher peak by summing with a previous
|
||||
// sibling. we do it iteratively in case the new peak itself allows the
|
||||
// creation of another parent.
|
||||
// height it means we have to build a higher peak by summing with a previous
|
||||
// sibling. we do it iteratively in case the new peak itself allows the
|
||||
// creation of another parent.
|
||||
while bintree_postorder_height(pos + 1) > height {
|
||||
let left_sibling = bintree_jump_left_sibling(pos);
|
||||
let left_hashsum = self.backend.get(left_sibling).expect(
|
||||
"missing left sibling in tree, should not have been pruned",
|
||||
);
|
||||
let left_hashsum = self.backend
|
||||
.get(left_sibling)
|
||||
.expect("missing left sibling in tree, should not have been pruned");
|
||||
current_hashsum = left_hashsum + current_hashsum;
|
||||
|
||||
to_append.push(current_hashsum.clone());
|
||||
@@ -293,8 +293,8 @@ where
|
||||
/// well as the consumer-provided index of when the change occurred.
|
||||
pub fn rewind(&mut self, position: u64, index: u32) -> Result<(), String> {
|
||||
// identify which actual position we should rewind to as the provided
|
||||
// position is a leaf, which may had some parent that needs to exist
|
||||
// afterward for the MMR to be valid
|
||||
// position is a leaf, which may had some parent that needs to exist
|
||||
// afterward for the MMR to be valid
|
||||
let mut pos = position;
|
||||
while bintree_postorder_height(pos + 1) > 0 {
|
||||
pos += 1;
|
||||
@@ -320,7 +320,7 @@ where
|
||||
}
|
||||
|
||||
// loop going up the tree, from node to parent, as long as we stay inside
|
||||
// the tree.
|
||||
// the tree.
|
||||
let mut to_prune = vec![];
|
||||
let mut current = position;
|
||||
while current + 1 < self.last_pos {
|
||||
@@ -332,7 +332,7 @@ where
|
||||
to_prune.push(current);
|
||||
|
||||
// if we have a pruned sibling, we can continue up the tree
|
||||
// otherwise we're done
|
||||
// otherwise we're done
|
||||
if let None = self.backend.get(sibling) {
|
||||
current = parent;
|
||||
} else {
|
||||
@@ -353,30 +353,30 @@ where
|
||||
/// Helper function to get the last N nodes inserted, i.e. the last
|
||||
/// n nodes along the bottom of the tree
|
||||
pub fn get_last_n_insertions(&self, n: u64) -> Vec<HashSum<T>> {
|
||||
let mut return_vec=Vec::new();
|
||||
let mut return_vec = Vec::new();
|
||||
let mut last_leaf = self.last_pos;
|
||||
let size=self.unpruned_size();
|
||||
//Special case that causes issues in bintree functions,
|
||||
//just return
|
||||
if size==1 {
|
||||
let size = self.unpruned_size();
|
||||
// Special case that causes issues in bintree functions,
|
||||
// just return
|
||||
if size == 1 {
|
||||
return_vec.push(self.backend.get(last_leaf).unwrap());
|
||||
return return_vec;
|
||||
}
|
||||
//if size is even, we're already at the bottom, otherwise
|
||||
//we need to traverse down to it (reverse post-order direction)
|
||||
// if size is even, we're already at the bottom, otherwise
|
||||
// we need to traverse down to it (reverse post-order direction)
|
||||
if size % 2 == 1 {
|
||||
last_leaf=bintree_rightmost(self.last_pos);
|
||||
last_leaf = bintree_rightmost(self.last_pos);
|
||||
}
|
||||
for _ in 0..n as u64 {
|
||||
if last_leaf==0 {
|
||||
if last_leaf == 0 {
|
||||
break;
|
||||
}
|
||||
if bintree_postorder_height(last_leaf) > 0 {
|
||||
last_leaf = bintree_rightmost(last_leaf);
|
||||
}
|
||||
return_vec.push(self.backend.get(last_leaf).unwrap());
|
||||
|
||||
last_leaf=bintree_jump_left_sibling(last_leaf);
|
||||
|
||||
last_leaf = bintree_jump_left_sibling(last_leaf);
|
||||
}
|
||||
return_vec
|
||||
}
|
||||
@@ -388,30 +388,30 @@ where
|
||||
}
|
||||
|
||||
/// Debugging utility to print information about the MMRs. Short version
|
||||
/// only prints the last 8 nodes.
|
||||
/// only prints the last 8 nodes.
|
||||
pub fn dump(&self, short: bool) {
|
||||
let sz = self.unpruned_size();
|
||||
if sz > 600 {
|
||||
return;
|
||||
}
|
||||
let start = if short && sz > 7 { sz/8 - 1 } else { 0 };
|
||||
for n in start..(sz/8+1) {
|
||||
let mut idx = "".to_owned();
|
||||
let mut hashes = "".to_owned();
|
||||
for m in (n*8)..(n+1)*8 {
|
||||
if m >= sz {
|
||||
break;
|
||||
}
|
||||
idx.push_str(&format!("{:>8} ", m + 1));
|
||||
let ohs = self.get(m+1);
|
||||
match ohs {
|
||||
Some(hs) => hashes.push_str(&format!("{} ", hs.hash)),
|
||||
None => hashes.push_str(&format!("{:>8} ", "??")),
|
||||
}
|
||||
}
|
||||
debug!(LOGGER, "{}", idx);
|
||||
debug!(LOGGER, "{}", hashes);
|
||||
}
|
||||
let start = if short && sz > 7 { sz / 8 - 1 } else { 0 };
|
||||
for n in start..(sz / 8 + 1) {
|
||||
let mut idx = "".to_owned();
|
||||
let mut hashes = "".to_owned();
|
||||
for m in (n * 8)..(n + 1) * 8 {
|
||||
if m >= sz {
|
||||
break;
|
||||
}
|
||||
idx.push_str(&format!("{:>8} ", m + 1));
|
||||
let ohs = self.get(m + 1);
|
||||
match ohs {
|
||||
Some(hs) => hashes.push_str(&format!("{} ", hs.hash)),
|
||||
None => hashes.push_str(&format!("{:>8} ", "??")),
|
||||
}
|
||||
}
|
||||
debug!(LOGGER, "{}", idx);
|
||||
debug!(LOGGER, "{}", hashes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,19 +503,21 @@ pub struct PruneList {
|
||||
impl PruneList {
|
||||
/// Instantiate a new empty prune list
|
||||
pub fn new() -> PruneList {
|
||||
PruneList { pruned_nodes: vec![] }
|
||||
PruneList {
|
||||
pruned_nodes: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes by how many positions a node at pos should be shifted given the
|
||||
/// number of nodes that have already been pruned before it.
|
||||
pub fn get_shift(&self, pos: u64) -> Option<u64> {
|
||||
// get the position where the node at pos would fit in the pruned list, if
|
||||
// it's already pruned, nothing to skip
|
||||
// it's already pruned, nothing to skip
|
||||
match self.pruned_pos(pos) {
|
||||
None => None,
|
||||
Some(idx) => {
|
||||
// skip by the number of elements pruned in the preceding subtrees,
|
||||
// which is the sum of the size of each subtree
|
||||
// which is the sum of the size of each subtree
|
||||
Some(
|
||||
self.pruned_nodes[0..(idx as usize)]
|
||||
.iter()
|
||||
@@ -557,8 +559,8 @@ impl PruneList {
|
||||
Err(idx) => {
|
||||
if self.pruned_nodes.len() > idx {
|
||||
// the node at pos can't be a child of lower position nodes by MMR
|
||||
// construction but can be a child of the next node, going up parents
|
||||
// from pos to make sure it's not the case
|
||||
// construction but can be a child of the next node, going up parents
|
||||
// from pos to make sure it's not the case
|
||||
let next_peak_pos = self.pruned_nodes[idx];
|
||||
let mut cursor = pos;
|
||||
loop {
|
||||
@@ -583,15 +585,14 @@ impl PruneList {
|
||||
/// side of the range, and navigates toward lower siblings toward the right
|
||||
/// of the range.
|
||||
fn peaks(num: u64) -> Vec<u64> {
|
||||
|
||||
// detecting an invalid mountain range, when siblings exist but no parent
|
||||
// exists
|
||||
// exists
|
||||
if bintree_postorder_height(num + 1) > bintree_postorder_height(num) {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
// our top peak is always on the leftmost side of the tree and leftmost trees
|
||||
// have for index a binary values with all 1s (i.e. 11, 111, 1111, etc.)
|
||||
// have for index a binary values with all 1s (i.e. 11, 111, 1111, etc.)
|
||||
let mut top = 1;
|
||||
while (top - 1) <= num {
|
||||
top = top << 1;
|
||||
@@ -604,7 +605,7 @@ fn peaks(num: u64) -> Vec<u64> {
|
||||
let mut peaks = vec![top];
|
||||
|
||||
// going down the range, next peaks are right neighbors of the top. if one
|
||||
// doesn't exist yet, we go down to a smaller peak to the left
|
||||
// doesn't exist yet, we go down to a smaller peak to the left
|
||||
let mut peak = top;
|
||||
'outer: loop {
|
||||
peak = bintree_jump_right_sibling(peak);
|
||||
@@ -807,8 +808,8 @@ mod test {
|
||||
#[allow(unused_variables)]
|
||||
fn first_50_mmr_heights() {
|
||||
let first_100_str = "0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 4 \
|
||||
0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 4 5 \
|
||||
0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 4 0 0 1 0 0";
|
||||
0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 4 5 \
|
||||
0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 0 0 1 0 0 1 2 0 0 1 0 0 1 2 3 4 0 0 1 0 0";
|
||||
let first_100 = first_100_str.split(' ').map(|n| n.parse::<u64>().unwrap());
|
||||
let mut count = 1;
|
||||
for n in first_100 {
|
||||
@@ -844,9 +845,9 @@ mod test {
|
||||
type Sum = u64;
|
||||
fn sum(&self) -> u64 {
|
||||
// sums are not allowed to overflow, so we use this simple
|
||||
// non-injective "sum" function that will still be homomorphic
|
||||
self.0[0] as u64 * 0x1000 + self.0[1] as u64 * 0x100 + self.0[2] as u64 * 0x10 +
|
||||
self.0[3] as u64
|
||||
// non-injective "sum" function that will still be homomorphic
|
||||
self.0[0] as u64 * 0x1000 + self.0[1] as u64 * 0x100 + self.0[2] as u64 * 0x10
|
||||
+ self.0[3] as u64
|
||||
}
|
||||
fn sum_len() -> usize {
|
||||
8
|
||||
@@ -896,7 +897,8 @@ mod test {
|
||||
|
||||
// two elements
|
||||
pmmr.push(elems[1], None::<TestElem>).unwrap();
|
||||
let sum2 = HashSum::from_summable(1, &elems[0], None::<TestElem>) + HashSum::from_summable(2, &elems[1], None::<TestElem>);
|
||||
let sum2 = HashSum::from_summable(1, &elems[0], None::<TestElem>)
|
||||
+ HashSum::from_summable(2, &elems[1], None::<TestElem>);
|
||||
assert_eq!(pmmr.root(), sum2);
|
||||
assert_eq!(pmmr.unpruned_size(), 3);
|
||||
|
||||
@@ -908,8 +910,9 @@ mod test {
|
||||
|
||||
// four elements
|
||||
pmmr.push(elems[3], None::<TestElem>).unwrap();
|
||||
let sum4 = sum2 +
|
||||
(HashSum::from_summable(4, &elems[2], None::<TestElem>) + HashSum::from_summable(5, &elems[3], None::<TestElem>));
|
||||
let sum4 = sum2
|
||||
+ (HashSum::from_summable(4, &elems[2], None::<TestElem>)
|
||||
+ HashSum::from_summable(5, &elems[3], None::<TestElem>));
|
||||
assert_eq!(pmmr.root(), sum4);
|
||||
assert_eq!(pmmr.unpruned_size(), 7);
|
||||
|
||||
@@ -921,8 +924,9 @@ mod test {
|
||||
|
||||
// six elements
|
||||
pmmr.push(elems[5], None::<TestElem>).unwrap();
|
||||
let sum6 = sum4.clone() +
|
||||
(HashSum::from_summable(8, &elems[4], None::<TestElem>) + HashSum::from_summable(9, &elems[5], None::<TestElem>));
|
||||
let sum6 = sum4.clone()
|
||||
+ (HashSum::from_summable(8, &elems[4], None::<TestElem>)
|
||||
+ HashSum::from_summable(9, &elems[5], None::<TestElem>));
|
||||
assert_eq!(pmmr.root(), sum6.clone());
|
||||
assert_eq!(pmmr.unpruned_size(), 10);
|
||||
|
||||
@@ -934,9 +938,11 @@ mod test {
|
||||
|
||||
// eight elements
|
||||
pmmr.push(elems[7], None::<TestElem>).unwrap();
|
||||
let sum8 = sum4 +
|
||||
((HashSum::from_summable(8, &elems[4], None::<TestElem>) + HashSum::from_summable(9, &elems[5], None::<TestElem>)) +
|
||||
(HashSum::from_summable(11, &elems[6], None::<TestElem>) + HashSum::from_summable(12, &elems[7], None::<TestElem>)));
|
||||
let sum8 = sum4
|
||||
+ ((HashSum::from_summable(8, &elems[4], None::<TestElem>)
|
||||
+ HashSum::from_summable(9, &elems[5], None::<TestElem>))
|
||||
+ (HashSum::from_summable(11, &elems[6], None::<TestElem>)
|
||||
+ HashSum::from_summable(12, &elems[7], None::<TestElem>)));
|
||||
assert_eq!(pmmr.root(), sum8);
|
||||
assert_eq!(pmmr.unpruned_size(), 15);
|
||||
|
||||
@@ -949,7 +955,6 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn pmmr_get_last_n_insertions() {
|
||||
|
||||
let elems = [
|
||||
TestElem([0, 0, 0, 1]),
|
||||
TestElem([0, 0, 0, 2]),
|
||||
@@ -964,28 +969,31 @@ mod test {
|
||||
let mut ba = VecBackend::new();
|
||||
let mut pmmr = PMMR::new(&mut ba);
|
||||
|
||||
//test when empty
|
||||
let res=pmmr.get_last_n_insertions(19);
|
||||
assert!(res.len()==0);
|
||||
// test when empty
|
||||
let res = pmmr.get_last_n_insertions(19);
|
||||
assert!(res.len() == 0);
|
||||
|
||||
pmmr.push(elems[0], None::<TestElem>).unwrap();
|
||||
let res=pmmr.get_last_n_insertions(19);
|
||||
assert!(res.len()==1 && res[0].sum==1);
|
||||
let res = pmmr.get_last_n_insertions(19);
|
||||
assert!(res.len() == 1 && res[0].sum == 1);
|
||||
|
||||
pmmr.push(elems[1], None::<TestElem>).unwrap();
|
||||
|
||||
let res = pmmr.get_last_n_insertions(12);
|
||||
assert!(res[0].sum==2 && res[1].sum==1);
|
||||
assert!(res[0].sum == 2 && res[1].sum == 1);
|
||||
|
||||
pmmr.push(elems[2], None::<TestElem>).unwrap();
|
||||
|
||||
let res = pmmr.get_last_n_insertions(2);
|
||||
assert!(res[0].sum==3 && res[1].sum==2);
|
||||
assert!(res[0].sum == 3 && res[1].sum == 2);
|
||||
|
||||
pmmr.push(elems[3], None::<TestElem>).unwrap();
|
||||
|
||||
let res = pmmr.get_last_n_insertions(19);
|
||||
assert!(res[0].sum==4 && res[1].sum==3 && res[2].sum==2 && res[3].sum==1 && res.len()==4);
|
||||
assert!(
|
||||
res[0].sum == 4 && res[1].sum == 3 && res[2].sum == 2 && res[3].sum == 1
|
||||
&& res.len() == 4
|
||||
);
|
||||
|
||||
pmmr.push(elems[5], None::<TestElem>).unwrap();
|
||||
pmmr.push(elems[6], None::<TestElem>).unwrap();
|
||||
@@ -993,8 +1001,10 @@ mod test {
|
||||
pmmr.push(elems[8], None::<TestElem>).unwrap();
|
||||
|
||||
let res = pmmr.get_last_n_insertions(7);
|
||||
assert!(res[0].sum==9 && res[1].sum==8 && res[2].sum==7 && res[3].sum==6 && res.len()==7);
|
||||
|
||||
assert!(
|
||||
res[0].sum == 9 && res[1].sum == 8 && res[2].sum == 7 && res[3].sum == 6
|
||||
&& res.len() == 7
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+22
-10
@@ -20,13 +20,13 @@
|
||||
//! wrapper in case the internal representation needs to change again
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::{Add, Mul, Div, Sub};
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer, de};
|
||||
use byteorder::{ByteOrder, BigEndian};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
use core::hash::Hash;
|
||||
use ser::{self, Reader, Writer, Writeable, Readable};
|
||||
use ser::{self, Readable, Reader, Writeable, Writer};
|
||||
|
||||
/// The target is the 32-bytes hash block hashes must be lower than.
|
||||
pub const MAX_TARGET: [u8; 8] = [0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
|
||||
@@ -63,7 +63,9 @@ impl Difficulty {
|
||||
let mut in_vec = h.to_vec();
|
||||
in_vec.truncate(8);
|
||||
let num = BigEndian::read_u64(&in_vec);
|
||||
Difficulty { num: max_target / num }
|
||||
Difficulty {
|
||||
num: max_target / num,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the difficulty into a u64
|
||||
@@ -81,28 +83,36 @@ impl fmt::Display for Difficulty {
|
||||
impl Add<Difficulty> for Difficulty {
|
||||
type Output = Difficulty;
|
||||
fn add(self, other: Difficulty) -> Difficulty {
|
||||
Difficulty { num: self.num + other.num }
|
||||
Difficulty {
|
||||
num: self.num + other.num,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Difficulty> for Difficulty {
|
||||
type Output = Difficulty;
|
||||
fn sub(self, other: Difficulty) -> Difficulty {
|
||||
Difficulty { num: self.num - other.num }
|
||||
Difficulty {
|
||||
num: self.num - other.num,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Difficulty> for Difficulty {
|
||||
type Output = Difficulty;
|
||||
fn mul(self, other: Difficulty) -> Difficulty {
|
||||
Difficulty { num: self.num * other.num }
|
||||
Difficulty {
|
||||
num: self.num * other.num,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Difficulty> for Difficulty {
|
||||
type Output = Difficulty;
|
||||
fn div(self, other: Difficulty) -> Difficulty {
|
||||
Difficulty { num: self.num / other.num }
|
||||
Difficulty {
|
||||
num: self.num / other.num,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +167,8 @@ impl<'de> de::Visitor<'de> for DiffVisitor {
|
||||
&"a value number",
|
||||
));
|
||||
};
|
||||
Ok(Difficulty { num: num_in.unwrap() })
|
||||
Ok(Difficulty {
|
||||
num: num_in.unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
//! Transactions
|
||||
|
||||
use byteorder::{ByteOrder, BigEndian};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use blake2::blake2b::blake2b;
|
||||
use util::secp::{self, Secp256k1, Message, Signature};
|
||||
use util::secp::pedersen::{RangeProof, Commitment};
|
||||
@@ -23,7 +23,7 @@ use std::ops;
|
||||
use core::Committed;
|
||||
use core::pmmr::Summable;
|
||||
use keychain::{Identifier, Keychain};
|
||||
use ser::{self, Reader, Writer, Readable, Writeable, WriteableSorted, read_and_verify_sorted};
|
||||
use ser::{self, read_and_verify_sorted, Readable, Reader, Writeable, WriteableSorted, Writer};
|
||||
use util::LOGGER;
|
||||
|
||||
/// The size to use for the stored blake2 hash of a switch_commitment
|
||||
@@ -102,9 +102,8 @@ impl Writeable for TxKernel {
|
||||
|
||||
impl Readable for TxKernel {
|
||||
fn read(reader: &mut Reader) -> Result<TxKernel, ser::Error> {
|
||||
let features = KernelFeatures::from_bits(reader.read_u8()?).ok_or(
|
||||
ser::Error::CorruptedData,
|
||||
)?;
|
||||
let features =
|
||||
KernelFeatures::from_bits(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
|
||||
|
||||
Ok(TxKernel {
|
||||
features: features,
|
||||
@@ -287,12 +286,12 @@ impl Transaction {
|
||||
let sig = Signature::from_der(secp, &self.excess_sig)?;
|
||||
|
||||
// pretend the sum is a public key (which it is, being of the form r.G) and
|
||||
// verify the transaction sig with it
|
||||
//
|
||||
// we originally converted the commitment to a key_id here (commitment to zero)
|
||||
// and then passed the key_id to secp.verify()
|
||||
// the secp api no longer allows us to do this so we have wrapped the complexity
|
||||
// of generating a public key from a commitment behind verify_from_commit
|
||||
// verify the transaction sig with it
|
||||
//
|
||||
// we originally converted the commitment to a key_id here (commitment to zero)
|
||||
// and then passed the key_id to secp.verify()
|
||||
// the secp api no longer allows us to do this so we have wrapped the complexity
|
||||
// of generating a public key from a commitment behind verify_from_commit
|
||||
secp.verify_from_commit(&msg, &sig, &rsum)?;
|
||||
|
||||
let kernel = TxKernel {
|
||||
@@ -456,9 +455,8 @@ impl Writeable for Output {
|
||||
/// an Output from a binary stream.
|
||||
impl Readable for Output {
|
||||
fn read(reader: &mut Reader) -> Result<Output, ser::Error> {
|
||||
let features = OutputFeatures::from_bits(reader.read_u8()?).ok_or(
|
||||
ser::Error::CorruptedData,
|
||||
)?;
|
||||
let features =
|
||||
OutputFeatures::from_bits(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
|
||||
|
||||
Ok(Output {
|
||||
features: features,
|
||||
@@ -494,13 +492,11 @@ impl Output {
|
||||
/// value from the range proof and the commitment
|
||||
pub fn recover_value(&self, keychain: &Keychain, key_id: &Identifier) -> Option<u64> {
|
||||
match keychain.rewind_range_proof(key_id, self.commit, self.proof) {
|
||||
Ok(proof_info) => {
|
||||
if proof_info.success {
|
||||
Some(proof_info.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Ok(proof_info) => if proof_info.success {
|
||||
Some(proof_info.value)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
@@ -554,10 +550,9 @@ impl ops::Add for SumCommit {
|
||||
type Output = SumCommit;
|
||||
|
||||
fn add(self, other: SumCommit) -> SumCommit {
|
||||
let sum = match self.secp.commit_sum(
|
||||
vec![self.commit.clone(), other.commit.clone()],
|
||||
vec![],
|
||||
) {
|
||||
let sum = match self.secp
|
||||
.commit_sum(vec![self.commit.clone(), other.commit.clone()], vec![])
|
||||
{
|
||||
Ok(s) => s,
|
||||
Err(_) => Commitment::from_vec(vec![1; 33]),
|
||||
};
|
||||
|
||||
+2
-2
@@ -61,8 +61,8 @@ pub enum MiningParameterMode {
|
||||
}
|
||||
|
||||
lazy_static!{
|
||||
/// The mining parameter mode
|
||||
pub static ref MINING_PARAMETER_MODE: RwLock<MiningParameterMode> =
|
||||
/// The mining parameter mode
|
||||
pub static ref MINING_PARAMETER_MODE: RwLock<MiningParameterMode> =
|
||||
RwLock::new(MiningParameterMode::Production);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -25,8 +25,10 @@
|
||||
extern crate bitflags;
|
||||
extern crate blake2_rfc as blake2;
|
||||
extern crate byteorder;
|
||||
extern crate grin_keychain as keychain;
|
||||
extern crate grin_util as util;
|
||||
#[macro_use]
|
||||
extern crate slog;
|
||||
extern crate lazy_static;
|
||||
extern crate num_bigint as bigint;
|
||||
extern crate rand;
|
||||
extern crate grin_keychain as keychain;
|
||||
@@ -34,9 +36,9 @@ extern crate grin_util as util;
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate time;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate slog;
|
||||
extern crate time;
|
||||
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
|
||||
+11
-8
@@ -19,9 +19,9 @@
|
||||
//! To use it simply implement `Writeable` or `Readable` and then use the
|
||||
//! `serialize` or `deserialize` functions on them as appropriate.
|
||||
|
||||
use std::{error, fmt, cmp};
|
||||
use std::io::{self, Write, Read};
|
||||
use byteorder::{ByteOrder, ReadBytesExt, BigEndian};
|
||||
use std::{cmp, error, fmt};
|
||||
use std::io::{self, Read, Write};
|
||||
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
|
||||
use keychain::{Identifier, IDENTIFIER_SIZE};
|
||||
use core::hash::Hashed;
|
||||
use consensus::VerifySortOrder;
|
||||
@@ -199,7 +199,8 @@ pub trait WriteableSorted {
|
||||
/// A consensus rule requires everything is sorted lexicographically to avoid
|
||||
/// leaking any information through specific ordering of items.
|
||||
pub fn read_and_verify_sorted<T>(reader: &mut Reader, count: u64) -> Result<Vec<T>, Error>
|
||||
where T: Readable + Hashed + Writeable
|
||||
where
|
||||
T: Readable + Hashed + Writeable,
|
||||
{
|
||||
let result: Vec<T> = try!((0..count).map(|_| T::read(reader)).collect());
|
||||
result.verify_sort_order()?;
|
||||
@@ -276,9 +277,10 @@ impl<'a> Reader for BinReader<'a> {
|
||||
return Err(Error::TooLargeReadErr);
|
||||
}
|
||||
let mut buf = vec![0; length];
|
||||
self.source.read_exact(&mut buf).map(move |_| buf).map_err(
|
||||
Error::IOErr,
|
||||
)
|
||||
self.source
|
||||
.read_exact(&mut buf)
|
||||
.map(move |_| buf)
|
||||
.map_err(Error::IOErr)
|
||||
}
|
||||
|
||||
fn expect_u8(&mut self, val: u8) -> Result<u8, Error> {
|
||||
@@ -532,7 +534,8 @@ impl AsFixedBytes for [u8; 20] {
|
||||
fn len(&self) -> usize {
|
||||
return 20;
|
||||
}
|
||||
}impl AsFixedBytes for [u8; 32] {
|
||||
}
|
||||
impl AsFixedBytes for [u8; 32] {
|
||||
fn len(&self) -> usize {
|
||||
return 32;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user