Create new "transition" mod, add untested fn
Untested fn is process_ffg_deposits. Will add tests now.
This commit is contained in:
parent
0448fd5ace
commit
b1679af191
@ -40,6 +40,11 @@ impl CrystallizedState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn finality_distance(&self) -> u64 {
|
||||||
|
assert!(self.current_epoch >= self.last_finalized_epoch);
|
||||||
|
self.current_epoch - self.last_finalized_epoch
|
||||||
|
}
|
||||||
|
|
||||||
pub fn num_active_validators(&self) -> usize {
|
pub fn num_active_validators(&self) -> usize {
|
||||||
self.active_validators.len()
|
self.active_validators.len()
|
||||||
}
|
}
|
||||||
|
@ -14,4 +14,5 @@ pub mod crosslink_record;
|
|||||||
pub mod partial_crosslink_record;
|
pub mod partial_crosslink_record;
|
||||||
pub mod recent_proposer_record;
|
pub mod recent_proposer_record;
|
||||||
pub mod state_transition;
|
pub mod state_transition;
|
||||||
|
pub mod transition;
|
||||||
pub mod validator_record;
|
pub mod validator_record;
|
||||||
|
@ -1,56 +1,14 @@
|
|||||||
use super::utils::types::{ Sha256Digest };
|
use super::utils::types::{ Bitfield, U256 };
|
||||||
use super::blake2::{ Blake2s, Digest };
|
|
||||||
use super::bytes::{ BytesMut, BufMut };
|
use super::bytes::{ BytesMut, BufMut };
|
||||||
use super::crystallized_state::CrystallizedState;
|
use super::crystallized_state::CrystallizedState;
|
||||||
use super::active_state::ActiveState;
|
use super::active_state::ActiveState;
|
||||||
use super::aggregate_vote::AggregateVote;
|
use super::aggregate_vote::AggregateVote;
|
||||||
|
|
||||||
|
use super::transition::shuffling::get_shuffling;
|
||||||
use super::config::Config;
|
use super::config::Config;
|
||||||
|
|
||||||
const AGG_VOTE_MSG_SIZE: i32 = 2 + 32 + 32 + 8 + 8;
|
const AGG_VOTE_MSG_SIZE: i32 = 2 + 32 + 32 + 8 + 8;
|
||||||
|
|
||||||
// Interprets a 3-byte slice from a [u8] as an integer.
|
|
||||||
fn get_shift_from_source(source: &[u8], offset: usize) -> usize {
|
|
||||||
(source[offset + 2] as usize) |
|
|
||||||
((source[offset + 1] as usize) << 8) |
|
|
||||||
((source[offset ] as usize) << 16)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given entropy in the form of `seed`, return a shuffled list of validators
|
|
||||||
// indicies of size `validator_count` or `sample`.
|
|
||||||
pub fn get_shuffling(
|
|
||||||
seed: &Sha256Digest,
|
|
||||||
validator_count: &usize,
|
|
||||||
config: &Config)
|
|
||||||
-> Vec<usize>
|
|
||||||
{
|
|
||||||
assert!(*validator_count > 0, "cannot shuffle 0 validators");
|
|
||||||
let mut output: Vec<usize> = (0..*validator_count).collect();
|
|
||||||
assert!(*validator_count <= (config.max_validators as usize),
|
|
||||||
"validator_count exceeds max_validators");
|
|
||||||
|
|
||||||
// Do the first blake hash round
|
|
||||||
let mut source = Blake2s::new();
|
|
||||||
source.input(&seed);
|
|
||||||
|
|
||||||
let mut v = 0;
|
|
||||||
while v < *validator_count {
|
|
||||||
let current_source = source.result();
|
|
||||||
let mut source_offset = 0;
|
|
||||||
while source_offset < 30 {
|
|
||||||
let m = get_shift_from_source(¤t_source, source_offset);
|
|
||||||
let shuffled_position: usize = (m % (validator_count - v)) + v;
|
|
||||||
output.swap(v as usize, shuffled_position as usize);
|
|
||||||
v += 1;
|
|
||||||
if v >= *validator_count { break; }
|
|
||||||
source_offset += 3;
|
|
||||||
}
|
|
||||||
// Re-hash the source (TODO: this does one extra hash, can be optimised)
|
|
||||||
source = Blake2s::new();
|
|
||||||
source.input(¤t_source);
|
|
||||||
}
|
|
||||||
output
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given an aggregate_vote and a crystallized_state,
|
// Given an aggregate_vote and a crystallized_state,
|
||||||
// return a byte array for signing or verification.
|
// return a byte array for signing or verification.
|
||||||
pub fn get_crosslink_aggvote_msg(
|
pub fn get_crosslink_aggvote_msg(
|
||||||
@ -96,63 +54,49 @@ pub fn get_attesters_and_proposer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn process_ffg_deposits(
|
||||||
|
cry_state: &CrystallizedState,
|
||||||
|
ffg_vote_bitfield: Bitfield)
|
||||||
|
-> (Vec<u64>, u64, U256, bool, bool)
|
||||||
|
{
|
||||||
|
let active_validators: usize = cry_state.num_active_validators();
|
||||||
|
let finality_distance: u64 = cry_state.finality_distance();
|
||||||
|
let online_reward: u64 = if finality_distance <= 2 { 6 } else { 0 };
|
||||||
|
let offline_penalty: u64 = finality_distance.saturating_mul(3);
|
||||||
|
let mut total_vote_count: u64 = 0;
|
||||||
|
let mut total_vote_deposits = U256::zero();
|
||||||
|
|
||||||
|
let mut deltas = vec![0_u64; active_validators];
|
||||||
|
for i in 0..active_validators {
|
||||||
|
if ffg_vote_bitfield.get_bit(&i) {
|
||||||
|
total_vote_deposits = total_vote_deposits
|
||||||
|
.saturating_add(cry_state.active_validators[i].balance);
|
||||||
|
deltas[i] += online_reward;
|
||||||
|
total_vote_count += 1;
|
||||||
|
} else {
|
||||||
|
deltas[i] = deltas[i].saturating_sub(offline_penalty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut should_finalize = false;
|
||||||
|
let should_justify = total_vote_deposits.saturating_mul(U256::from(3))
|
||||||
|
>= cry_state.total_deposits.saturating_mul(U256::from(2));
|
||||||
|
if should_justify {
|
||||||
|
if cry_state.last_justified_epoch == cry_state.current_epoch - 1 {
|
||||||
|
should_finalize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(deltas, total_vote_count, total_vote_deposits, should_justify, should_finalize)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::super::validator_record::ValidatorRecord;
|
use super::super::validator_record::ValidatorRecord;
|
||||||
use super::super::utils::types::Address;
|
use super::super::utils::types::{ Address, Sha256Digest };
|
||||||
use super::super::
|
use super::super::
|
||||||
utils::test_helpers::get_dangerous_test_keypair;
|
utils::test_helpers::get_dangerous_test_keypair;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_shuffling_shift_fn() {
|
|
||||||
let mut x = get_shift_from_source(
|
|
||||||
&vec![0_u8, 0, 1],
|
|
||||||
0);
|
|
||||||
assert_eq!((x as u32), 1);
|
|
||||||
|
|
||||||
x = get_shift_from_source(
|
|
||||||
&vec![0_u8, 1, 1],
|
|
||||||
0);
|
|
||||||
assert_eq!(x, 257);
|
|
||||||
|
|
||||||
x = get_shift_from_source(
|
|
||||||
&vec![1_u8, 1, 1],
|
|
||||||
0);
|
|
||||||
assert_eq!(x, 65793);
|
|
||||||
|
|
||||||
x = get_shift_from_source(
|
|
||||||
&vec![255_u8, 1, 1],
|
|
||||||
0);
|
|
||||||
assert_eq!(x, 16711937);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_shuffling() {
|
|
||||||
let s = get_shuffling(
|
|
||||||
&Sha256Digest::zero(),
|
|
||||||
&10,
|
|
||||||
&Config::standard());
|
|
||||||
assert_eq!(s,
|
|
||||||
vec!(0, 9, 7, 6, 4, 1, 8, 5, 2, 3),
|
|
||||||
"10 validator shuffle was not as expected");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_shuffling_with_gt_half_max_validators() {
|
|
||||||
let mut config = Config::standard();
|
|
||||||
config.max_validators = 19;
|
|
||||||
let s = get_shuffling(
|
|
||||||
&Sha256Digest::zero(),
|
|
||||||
&10,
|
|
||||||
&Config::standard());
|
|
||||||
assert_eq!(s,
|
|
||||||
vec!(0, 9, 7, 6, 4, 1, 8, 5, 2, 3),
|
|
||||||
"10 validator shuffle was not as expected");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_crosslink_aggvote_msg() {
|
fn test_crosslink_aggvote_msg() {
|
||||||
let mut cs_state = CrystallizedState::zero();
|
let mut cs_state = CrystallizedState::zero();
|
||||||
@ -183,7 +127,7 @@ mod tests {
|
|||||||
withdrawal_shard: 0,
|
withdrawal_shard: 0,
|
||||||
withdrawal_address: Address::zero(),
|
withdrawal_address: Address::zero(),
|
||||||
randao_commitment: Sha256Digest::zero(),
|
randao_commitment: Sha256Digest::zero(),
|
||||||
balance: 0,
|
balance: U256::zero(),
|
||||||
switch_dynasty: 0
|
switch_dynasty: 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
5
src/state/transition/mod.rs
Normal file
5
src/state/transition/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use super::config;
|
||||||
|
use super::utils;
|
||||||
|
use super::blake2;
|
||||||
|
|
||||||
|
pub mod shuffling;
|
99
src/state/transition/shuffling.rs
Normal file
99
src/state/transition/shuffling.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
use super::config::Config;
|
||||||
|
use super::blake2::{ Blake2s, Digest };
|
||||||
|
use super::utils::types::Sha256Digest;
|
||||||
|
|
||||||
|
// Interprets a 3-byte slice from a [u8] as an integer.
|
||||||
|
fn get_shift_from_source(source: &[u8], offset: usize) -> usize {
|
||||||
|
(source[offset + 2] as usize) |
|
||||||
|
((source[offset + 1] as usize) << 8) |
|
||||||
|
((source[offset ] as usize) << 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given entropy in the form of `seed`, return a shuffled list of validators
|
||||||
|
// indicies of size `validator_count` or `sample`.
|
||||||
|
pub fn get_shuffling(
|
||||||
|
seed: &Sha256Digest,
|
||||||
|
validator_count: &usize,
|
||||||
|
config: &Config)
|
||||||
|
-> Vec<usize>
|
||||||
|
{
|
||||||
|
assert!(*validator_count > 0, "cannot shuffle 0 validators");
|
||||||
|
let mut output: Vec<usize> = (0..*validator_count).collect();
|
||||||
|
assert!(*validator_count <= (config.max_validators as usize),
|
||||||
|
"validator_count exceeds max_validators");
|
||||||
|
|
||||||
|
// Do the first blake hash round
|
||||||
|
let mut source = Blake2s::new();
|
||||||
|
source.input(&seed);
|
||||||
|
|
||||||
|
let mut v = 0;
|
||||||
|
while v < *validator_count {
|
||||||
|
let current_source = source.result();
|
||||||
|
let mut source_offset = 0;
|
||||||
|
while source_offset < 30 {
|
||||||
|
let m = get_shift_from_source(¤t_source, source_offset);
|
||||||
|
let shuffled_position: usize = (m % (validator_count - v)) + v;
|
||||||
|
output.swap(v as usize, shuffled_position as usize);
|
||||||
|
v += 1;
|
||||||
|
if v >= *validator_count { break; }
|
||||||
|
source_offset += 3;
|
||||||
|
}
|
||||||
|
// Re-hash the source (TODO: this does one extra hash, can be optimised)
|
||||||
|
source = Blake2s::new();
|
||||||
|
source.input(¤t_source);
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_shuffling_shift_fn() {
|
||||||
|
let mut x = get_shift_from_source(
|
||||||
|
&vec![0_u8, 0, 1],
|
||||||
|
0);
|
||||||
|
assert_eq!((x as u32), 1);
|
||||||
|
|
||||||
|
x = get_shift_from_source(
|
||||||
|
&vec![0_u8, 1, 1],
|
||||||
|
0);
|
||||||
|
assert_eq!(x, 257);
|
||||||
|
|
||||||
|
x = get_shift_from_source(
|
||||||
|
&vec![1_u8, 1, 1],
|
||||||
|
0);
|
||||||
|
assert_eq!(x, 65793);
|
||||||
|
|
||||||
|
x = get_shift_from_source(
|
||||||
|
&vec![255_u8, 1, 1],
|
||||||
|
0);
|
||||||
|
assert_eq!(x, 16711937);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_shuffling() {
|
||||||
|
let s = get_shuffling(
|
||||||
|
&Sha256Digest::zero(),
|
||||||
|
&10,
|
||||||
|
&Config::standard());
|
||||||
|
assert_eq!(s,
|
||||||
|
vec!(0, 9, 7, 6, 4, 1, 8, 5, 2, 3),
|
||||||
|
"10 validator shuffle was not as expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_shuffling_with_gt_half_max_validators() {
|
||||||
|
let mut config = Config::standard();
|
||||||
|
config.max_validators = 19;
|
||||||
|
let s = get_shuffling(
|
||||||
|
&Sha256Digest::zero(),
|
||||||
|
&10,
|
||||||
|
&Config::standard());
|
||||||
|
assert_eq!(s,
|
||||||
|
vec!(0, 9, 7, 6, 4, 1, 8, 5, 2, 3),
|
||||||
|
"10 validator shuffle was not as expected");
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use super::utils::types::{ Sha256Digest, Address };
|
use super::utils::types::{ Sha256Digest, Address, U256 };
|
||||||
use super::utils::bls::PublicKey;
|
use super::utils::bls::PublicKey;
|
||||||
use super::rlp::{ RlpStream, Encodable };
|
use super::rlp::{ RlpStream, Encodable };
|
||||||
|
|
||||||
@ -7,7 +7,7 @@ pub struct ValidatorRecord {
|
|||||||
pub withdrawal_shard: u16,
|
pub withdrawal_shard: u16,
|
||||||
pub withdrawal_address: Address,
|
pub withdrawal_address: Address,
|
||||||
pub randao_commitment: Sha256Digest,
|
pub randao_commitment: Sha256Digest,
|
||||||
pub balance: u64,
|
pub balance: U256,
|
||||||
pub switch_dynasty: u64
|
pub switch_dynasty: u64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,17 +16,17 @@ impl ValidatorRecord {
|
|||||||
withdrawal_shard: u16,
|
withdrawal_shard: u16,
|
||||||
withdrawal_address: Address,
|
withdrawal_address: Address,
|
||||||
randao_commitment: Sha256Digest,
|
randao_commitment: Sha256Digest,
|
||||||
balance: u64,
|
balance: U256,
|
||||||
switch_dynasty: u64)
|
switch_dynasty: u64)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
pubkey: pubkey,
|
pubkey,
|
||||||
withdrawal_shard: withdrawal_shard,
|
withdrawal_shard,
|
||||||
withdrawal_address: withdrawal_address,
|
withdrawal_address,
|
||||||
randao_commitment: randao_commitment,
|
randao_commitment,
|
||||||
balance: balance,
|
balance,
|
||||||
switch_dynasty: switch_dynasty
|
switch_dynasty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ mod tests {
|
|||||||
let withdrawal_shard = 1;
|
let withdrawal_shard = 1;
|
||||||
let withdrawal_address = Address::random();
|
let withdrawal_address = Address::random();
|
||||||
let randao_commitment = Sha256Digest::random();
|
let randao_commitment = Sha256Digest::random();
|
||||||
let balance = 100;
|
let balance = U256::from(100);
|
||||||
let switch_dynasty = 10;
|
let switch_dynasty = 10;
|
||||||
|
|
||||||
let v = ValidatorRecord::new(
|
let v = ValidatorRecord::new(
|
||||||
@ -88,7 +88,7 @@ mod tests {
|
|||||||
withdrawal_shard: 100,
|
withdrawal_shard: 100,
|
||||||
withdrawal_address: Address::zero(),
|
withdrawal_address: Address::zero(),
|
||||||
randao_commitment: Sha256Digest::zero(),
|
randao_commitment: Sha256Digest::zero(),
|
||||||
balance: 120,
|
balance: U256::from(120),
|
||||||
switch_dynasty: 30
|
switch_dynasty: 30
|
||||||
};
|
};
|
||||||
let e = rlp::encode(&v);
|
let e = rlp::encode(&v);
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
use super::bls::Keypair;
|
use super::bls::Keypair;
|
||||||
use self::rand::{ SeedableRng, XorShiftRng };
|
use self::rand::thread_rng;
|
||||||
|
|
||||||
// Returns a keypair for use in testing purposes.
|
// Returns a keypair for use in testing purposes.
|
||||||
pub fn get_dangerous_test_keypair() -> Keypair {
|
pub fn get_dangerous_test_keypair() -> Keypair {
|
||||||
let mut rng = XorShiftRng::from_seed([0xbc4f6d44,
|
let mut rng = thread_rng();
|
||||||
0xd62f276c,
|
|
||||||
0xb963afd0,
|
|
||||||
0x5455863d]);
|
|
||||||
Keypair::generate(&mut rng)
|
Keypair::generate(&mut rng)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use super::crystallized_state::CrystallizedState;
|
|||||||
use super::boolean_bitfield::BooleanBitfield;
|
use super::boolean_bitfield::BooleanBitfield;
|
||||||
|
|
||||||
pub use super::blake2::Blake2s;
|
pub use super::blake2::Blake2s;
|
||||||
|
pub use super::ethereum_types::U256;
|
||||||
|
|
||||||
// TODO: presently the compiler accepts these two types
|
// TODO: presently the compiler accepts these two types
|
||||||
// as interchangable. This is somewhat loose typing,
|
// as interchangable. This is somewhat loose typing,
|
||||||
|
Loading…
Reference in New Issue
Block a user