Add BooleanBitfield struct

This commit is contained in:
Paul Hauner 2018-07-12 14:59:50 +10:00
parent 4c7b2eec2c
commit 5e362567e6
11 changed files with 161 additions and 17 deletions

View File

@ -20,7 +20,7 @@ impl ActiveState {
Self {
height: 0,
randao: Sha256Digest::zero(),
ffg_voter_bitfield: Vec::new(),
ffg_voter_bitfield: Bitfield::new(),
recent_attesters: Vec::new(),
partial_crosslinks: Vec::new(),
total_skip_count: 0,
@ -96,11 +96,11 @@ mod tests {
}
#[test]
fn test_serialization() {
fn test_rlp_serialization() {
let a = ActiveState {
height: 100,
randao: Sha256Digest::zero(),
ffg_voter_bitfield: Vec::new(),
ffg_voter_bitfield: Bitfield::new(),
recent_attesters: Vec::new(),
partial_crosslinks: Vec::new(),
total_skip_count: 99,

View File

@ -14,7 +14,7 @@ impl AggregateVote {
Self {
shard_id: 0,
shard_block_hash: Sha256Digest::zero(),
notary_bitfield: Vec::new(),
notary_bitfield: Bitfield::new(),
aggregate_sig: AggregateSignature::new()
}
}
@ -46,11 +46,11 @@ mod tests {
}
#[test]
fn test_serialization() {
fn test_rlp_serialization() {
let a = AggregateVote {
shard_id: 100,
shard_block_hash: Sha256Digest::zero(),
notary_bitfield: Vec::new(),
notary_bitfield: Bitfield::new(),
aggregate_sig: AggregateSignature::new()
};
let e = rlp::encode(&a);

View File

@ -23,7 +23,7 @@ impl Block {
parent_hash: parent_hash,
skip_count: 0,
randao_reveal: randao_reveal,
attestation_bitfield: Vec::new(),
attestation_bitfield: Bitfield::new(),
attestation_aggregate_sig: AggregateSignature::new(),
shard_aggregate_votes: Vec::new(),
main_chain_ref: main_chain_ref,
@ -147,12 +147,12 @@ mod tests {
}
#[test]
fn test_serialization() {
fn test_rlp_serialization() {
let b = Block {
parent_hash: Sha256Digest::zero(),
skip_count: 100,
randao_reveal: Sha256Digest::zero(),
attestation_bitfield: Vec::new(),
attestation_bitfield: Bitfield::new(),
attestation_aggregate_sig: AggregateSignature::new(),
shard_aggregate_votes: Vec::new(),
main_chain_ref: Sha256Digest::zero(),

View File

@ -40,7 +40,7 @@ mod tests {
}
#[test]
fn test_serialization() {
fn test_rlp_serialization() {
let c = CrosslinkRecord {
epoch: 100,
hash: Sha256Digest::zero()

View File

@ -92,7 +92,7 @@ mod tests {
use super::*;
#[test]
fn test_serialization() {
fn test_rlp_serialization() {
let a = CrystallizedState {
active_validators: Vec::new(),
queued_validators: Vec::new(),

View File

@ -13,7 +13,7 @@ impl PartialCrosslinkRecord {
PartialCrosslinkRecord {
shard_id: shard_id,
shard_block_hash: shard_block_hash,
voter_bitfield: Vec::new()
voter_bitfield: Bitfield::new()
}
}
}
@ -45,11 +45,11 @@ mod tests {
}
#[test]
fn test_serialization() {
fn test_rlp_serialization() {
let p = PartialCrosslinkRecord {
shard_id: 1,
shard_block_hash: Sha256Digest::zero(),
voter_bitfield: Vec::new()
voter_bitfield: Bitfield::new()
};
let e = rlp::encode(&p);
assert_eq!(e.len(), 35);

View File

@ -37,7 +37,7 @@ mod tests {
use super::*;
#[test]
fn test_serialization() {
fn test_rlp_serialization() {
let index = 1;
let randao_commitment = Sha256Digest::zero();
let balance_delta = 99;

View File

@ -81,7 +81,7 @@ mod tests {
}
#[test]
fn test_serialization() {
fn test_rlp_serialization() {
let keypair = get_dangerous_test_keypair();
let v = ValidatorRecord {
pubkey: keypair.public,

View File

@ -0,0 +1,142 @@
/*
* Implemenation of a bitfield as a vec. Only
* supports bytes (Vec<u8>) as the underlying
* storage.
*
* A future implementation should be more efficient,
* this is just to get the job done for now.
*/
extern crate rlp;
use self::rlp::{ RlpStream, Encodable };
pub struct BooleanBitfield{
vec: Vec<u8>
}
impl BooleanBitfield {
pub fn new() -> Self {
Self {
vec: vec![]
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
vec: Vec::with_capacity(capacity)
}
}
// Output the bitfield as a big-endian vec of u8
pub fn to_be_vec(&self) -> Vec<u8> {
let mut o = self.vec.clone();
o.reverse();
o
}
pub fn get_bit(&self, i: &usize) -> bool {
self.get_bit_on_byte(*i % 8, *i / 8)
}
fn get_bit_on_byte(&self, bit: usize, byte: usize) -> bool {
assert!(bit < 8);
if byte >= self.vec.len() {
false
} else {
self.vec[byte] & (1 << (bit as u8)) != 0
}
}
pub fn set_bit(&mut self, bit: &usize, to: &bool) {
self.set_bit_on_byte(*bit % 8, *bit / 8, to);
}
fn set_bit_on_byte(&mut self, bit: usize, byte: usize, val: &bool) {
assert!(bit < 8);
if byte >= self.vec.len() {
self.vec.resize(byte + 1, 0);
}
match val {
true => self.vec[byte] = self.vec[byte] | (1 << (bit as u8)),
false => self.vec[byte] = self.vec[byte] & !(1 << (bit as u8))
}
}
}
impl Encodable for BooleanBitfield {
// TODO: ensure this is a sensible method of encoding
// the bitfield. Currently, it is treated as a list of
// bytes not as a string. I do not have any guidance as
// to which method is correct -- don't follow my lead
// without seeking authoritative advice.
fn rlp_append(&self, s: &mut RlpStream) {
s.append(&self.to_be_vec());
}
}
#[cfg(test)]
mod tests {
use super::*;
use super::rlp;
#[test]
fn test_bitfield_set() {
let mut b = BooleanBitfield::new();
b.set_bit(&0, &false);
assert_eq!(b.to_be_vec(), [0]);
b = BooleanBitfield::new();
b.set_bit(&7, &true);
assert_eq!(b.to_be_vec(), [128]);
b.set_bit(&7, &false);
assert_eq!(b.to_be_vec(), [0]);
b = BooleanBitfield::new();
b.set_bit(&7, &true);
b.set_bit(&0, &true);
assert_eq!(b.to_be_vec(), [129]);
b.set_bit(&7, &false);
assert_eq!(b.to_be_vec(), [1]);
b = BooleanBitfield::new();
b.set_bit(&8, &true);
assert_eq!(b.to_be_vec(), [1, 0]);
b.set_bit(&8, &false);
assert_eq!(b.to_be_vec(), [0, 0]);
b = BooleanBitfield::new();
b.set_bit(&15, &true);
assert_eq!(b.to_be_vec(), [128, 0]);
b.set_bit(&15, &false);
assert_eq!(b.to_be_vec(), [0, 0]);
b = BooleanBitfield::new();
b.set_bit(&8, &true);
b.set_bit(&15, &true);
assert_eq!(b.to_be_vec(), [129, 0]);
b.set_bit(&15, &false);
assert_eq!(b.to_be_vec(), [1, 0]);
}
#[test]
fn test_bitfield_get() {
let mut b = BooleanBitfield::new();
let test_nums = vec![0, 8, 15, 42, 1337];
for i in test_nums {
b = BooleanBitfield::new();
assert_eq!(b.get_bit(&0), false);
b.set_bit(&0, &true);
assert_eq!(b.get_bit(&0), true);
b.set_bit(&0, &true);
}
}
#[test]
fn test_bitfield_rlp_serialization() {
let mut b = BooleanBitfield::new();
b.set_bit(&15, &true);
let e = rlp::encode(&b);
assert_eq!(e[0], 130);
assert_eq!(e[1], 128);
assert_eq!(e[2], 0);
}
}

View File

@ -8,3 +8,4 @@ use super::state::crystallized_state;
pub mod types;
pub mod bls;
pub mod test_helpers;
pub mod boolean_bitfield;

View File

@ -1,6 +1,7 @@
use super::ethereum_types::{ H256, H160 };
use super::active_state::ActiveState;
use super::crystallized_state::CrystallizedState;
use super::boolean_bitfield::BooleanBitfield;
pub use super::blake2::Blake2s;
@ -33,4 +34,4 @@ impl StateHash {
}
}
pub type Bitfield = Vec<u8>;
pub type Bitfield = BooleanBitfield;