Add BooleanBitfield struct
This commit is contained in:
parent
4c7b2eec2c
commit
5e362567e6
@ -20,7 +20,7 @@ impl ActiveState {
|
|||||||
Self {
|
Self {
|
||||||
height: 0,
|
height: 0,
|
||||||
randao: Sha256Digest::zero(),
|
randao: Sha256Digest::zero(),
|
||||||
ffg_voter_bitfield: Vec::new(),
|
ffg_voter_bitfield: Bitfield::new(),
|
||||||
recent_attesters: Vec::new(),
|
recent_attesters: Vec::new(),
|
||||||
partial_crosslinks: Vec::new(),
|
partial_crosslinks: Vec::new(),
|
||||||
total_skip_count: 0,
|
total_skip_count: 0,
|
||||||
@ -96,11 +96,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialization() {
|
fn test_rlp_serialization() {
|
||||||
let a = ActiveState {
|
let a = ActiveState {
|
||||||
height: 100,
|
height: 100,
|
||||||
randao: Sha256Digest::zero(),
|
randao: Sha256Digest::zero(),
|
||||||
ffg_voter_bitfield: Vec::new(),
|
ffg_voter_bitfield: Bitfield::new(),
|
||||||
recent_attesters: Vec::new(),
|
recent_attesters: Vec::new(),
|
||||||
partial_crosslinks: Vec::new(),
|
partial_crosslinks: Vec::new(),
|
||||||
total_skip_count: 99,
|
total_skip_count: 99,
|
||||||
|
@ -14,7 +14,7 @@ impl AggregateVote {
|
|||||||
Self {
|
Self {
|
||||||
shard_id: 0,
|
shard_id: 0,
|
||||||
shard_block_hash: Sha256Digest::zero(),
|
shard_block_hash: Sha256Digest::zero(),
|
||||||
notary_bitfield: Vec::new(),
|
notary_bitfield: Bitfield::new(),
|
||||||
aggregate_sig: AggregateSignature::new()
|
aggregate_sig: AggregateSignature::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,11 +46,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialization() {
|
fn test_rlp_serialization() {
|
||||||
let a = AggregateVote {
|
let a = AggregateVote {
|
||||||
shard_id: 100,
|
shard_id: 100,
|
||||||
shard_block_hash: Sha256Digest::zero(),
|
shard_block_hash: Sha256Digest::zero(),
|
||||||
notary_bitfield: Vec::new(),
|
notary_bitfield: Bitfield::new(),
|
||||||
aggregate_sig: AggregateSignature::new()
|
aggregate_sig: AggregateSignature::new()
|
||||||
};
|
};
|
||||||
let e = rlp::encode(&a);
|
let e = rlp::encode(&a);
|
||||||
|
@ -23,7 +23,7 @@ impl Block {
|
|||||||
parent_hash: parent_hash,
|
parent_hash: parent_hash,
|
||||||
skip_count: 0,
|
skip_count: 0,
|
||||||
randao_reveal: randao_reveal,
|
randao_reveal: randao_reveal,
|
||||||
attestation_bitfield: Vec::new(),
|
attestation_bitfield: Bitfield::new(),
|
||||||
attestation_aggregate_sig: AggregateSignature::new(),
|
attestation_aggregate_sig: AggregateSignature::new(),
|
||||||
shard_aggregate_votes: Vec::new(),
|
shard_aggregate_votes: Vec::new(),
|
||||||
main_chain_ref: main_chain_ref,
|
main_chain_ref: main_chain_ref,
|
||||||
@ -147,12 +147,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialization() {
|
fn test_rlp_serialization() {
|
||||||
let b = Block {
|
let b = Block {
|
||||||
parent_hash: Sha256Digest::zero(),
|
parent_hash: Sha256Digest::zero(),
|
||||||
skip_count: 100,
|
skip_count: 100,
|
||||||
randao_reveal: Sha256Digest::zero(),
|
randao_reveal: Sha256Digest::zero(),
|
||||||
attestation_bitfield: Vec::new(),
|
attestation_bitfield: Bitfield::new(),
|
||||||
attestation_aggregate_sig: AggregateSignature::new(),
|
attestation_aggregate_sig: AggregateSignature::new(),
|
||||||
shard_aggregate_votes: Vec::new(),
|
shard_aggregate_votes: Vec::new(),
|
||||||
main_chain_ref: Sha256Digest::zero(),
|
main_chain_ref: Sha256Digest::zero(),
|
||||||
|
@ -40,7 +40,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialization() {
|
fn test_rlp_serialization() {
|
||||||
let c = CrosslinkRecord {
|
let c = CrosslinkRecord {
|
||||||
epoch: 100,
|
epoch: 100,
|
||||||
hash: Sha256Digest::zero()
|
hash: Sha256Digest::zero()
|
||||||
|
@ -92,7 +92,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialization() {
|
fn test_rlp_serialization() {
|
||||||
let a = CrystallizedState {
|
let a = CrystallizedState {
|
||||||
active_validators: Vec::new(),
|
active_validators: Vec::new(),
|
||||||
queued_validators: Vec::new(),
|
queued_validators: Vec::new(),
|
||||||
|
@ -13,7 +13,7 @@ impl PartialCrosslinkRecord {
|
|||||||
PartialCrosslinkRecord {
|
PartialCrosslinkRecord {
|
||||||
shard_id: shard_id,
|
shard_id: shard_id,
|
||||||
shard_block_hash: shard_block_hash,
|
shard_block_hash: shard_block_hash,
|
||||||
voter_bitfield: Vec::new()
|
voter_bitfield: Bitfield::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,11 +45,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialization() {
|
fn test_rlp_serialization() {
|
||||||
let p = PartialCrosslinkRecord {
|
let p = PartialCrosslinkRecord {
|
||||||
shard_id: 1,
|
shard_id: 1,
|
||||||
shard_block_hash: Sha256Digest::zero(),
|
shard_block_hash: Sha256Digest::zero(),
|
||||||
voter_bitfield: Vec::new()
|
voter_bitfield: Bitfield::new()
|
||||||
};
|
};
|
||||||
let e = rlp::encode(&p);
|
let e = rlp::encode(&p);
|
||||||
assert_eq!(e.len(), 35);
|
assert_eq!(e.len(), 35);
|
||||||
|
@ -37,7 +37,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialization() {
|
fn test_rlp_serialization() {
|
||||||
let index = 1;
|
let index = 1;
|
||||||
let randao_commitment = Sha256Digest::zero();
|
let randao_commitment = Sha256Digest::zero();
|
||||||
let balance_delta = 99;
|
let balance_delta = 99;
|
||||||
|
@ -81,7 +81,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialization() {
|
fn test_rlp_serialization() {
|
||||||
let keypair = get_dangerous_test_keypair();
|
let keypair = get_dangerous_test_keypair();
|
||||||
let v = ValidatorRecord {
|
let v = ValidatorRecord {
|
||||||
pubkey: keypair.public,
|
pubkey: keypair.public,
|
||||||
|
142
src/utils/boolean_bitfield.rs
Normal file
142
src/utils/boolean_bitfield.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -8,3 +8,4 @@ use super::state::crystallized_state;
|
|||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod bls;
|
pub mod bls;
|
||||||
pub mod test_helpers;
|
pub mod test_helpers;
|
||||||
|
pub mod boolean_bitfield;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::ethereum_types::{ H256, H160 };
|
use super::ethereum_types::{ H256, H160 };
|
||||||
use super::active_state::ActiveState;
|
use super::active_state::ActiveState;
|
||||||
use super::crystallized_state::CrystallizedState;
|
use super::crystallized_state::CrystallizedState;
|
||||||
|
use super::boolean_bitfield::BooleanBitfield;
|
||||||
|
|
||||||
pub use super::blake2::Blake2s;
|
pub use super::blake2::Blake2s;
|
||||||
|
|
||||||
@ -33,4 +34,4 @@ impl StateHash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Bitfield = Vec<u8>;
|
pub type Bitfield = BooleanBitfield;
|
||||||
|
Loading…
Reference in New Issue
Block a user