Add comments to new functions/structs.

This commit is contained in:
Paul Hauner 2019-03-12 18:26:41 +11:00
parent f949919b9b
commit 2be0373f01
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
11 changed files with 80 additions and 44 deletions

View File

@ -23,6 +23,8 @@ pub struct BeaconBlock {
impl BeaconBlock { impl BeaconBlock {
/// Produce the first block of the Beacon Chain. /// Produce the first block of the Beacon Chain.
///
/// Spec v0.4.0
pub fn genesis(state_root: Hash256, spec: &ChainSpec) -> BeaconBlock { pub fn genesis(state_root: Hash256, spec: &ChainSpec) -> BeaconBlock {
BeaconBlock { BeaconBlock {
slot: spec.genesis_slot, slot: spec.genesis_slot,
@ -46,11 +48,15 @@ impl BeaconBlock {
} }
/// Returns the `hash_tree_root` of the block. /// Returns the `hash_tree_root` of the block.
///
/// Spec v0.4.0
pub fn canonical_root(&self) -> Hash256 { pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..]) Hash256::from_slice(&self.hash_tree_root()[..])
} }
/// Returns an unsigned proposal for block. /// Returns an unsigned proposal for block.
///
/// Spec v0.4.0
pub fn proposal(&self, spec: &ChainSpec) -> Proposal { pub fn proposal(&self, spec: &ChainSpec) -> Proposal {
Proposal { Proposal {
slot: self.slot, slot: self.slot,

View File

@ -6,7 +6,6 @@ use honey_badger_split::SplitExt;
use int_to_bytes::int_to_bytes32; use int_to_bytes::int_to_bytes32;
use log::{debug, error, trace}; use log::{debug, error, trace};
use rand::RngCore; use rand::RngCore;
use rayon::prelude::*;
use serde_derive::Serialize; use serde_derive::Serialize;
use ssz::{hash, Decodable, DecodeError, Encodable, SignedRoot, SszStream, TreeHash}; use ssz::{hash, Decodable, DecodeError, Encodable, SignedRoot, SszStream, TreeHash};
use std::collections::HashMap; use std::collections::HashMap;
@ -113,6 +112,11 @@ pub struct BeaconState {
impl BeaconState { impl BeaconState {
/// Produce the first state of the Beacon Chain. /// Produce the first state of the Beacon Chain.
///
/// This does not fully build a genesis beacon state, it omits processing of initial validator
/// deposits. To obtain a full genesis beacon state, use the `BeaconStateBuilder`.
///
/// Spec v0.4.0
pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState { pub fn genesis(genesis_time: u64, latest_eth1_data: Eth1Data, spec: &ChainSpec) -> BeaconState {
let initial_crosslink = Crosslink { let initial_crosslink = Crosslink {
epoch: spec.genesis_epoch, epoch: spec.genesis_epoch,
@ -185,44 +189,9 @@ impl BeaconState {
} }
} }
/// Produce the first state of the Beacon Chain.
pub fn process_initial_deposits(
&mut self,
initial_validator_deposits: Vec<Deposit>,
spec: &ChainSpec,
) -> Result<(), Error> {
debug!("Processing genesis deposits...");
let deposit_data = initial_validator_deposits
.par_iter()
.map(|deposit| &deposit.deposit_data)
.collect();
self.process_deposits(deposit_data, spec);
trace!("Processed genesis deposits.");
for validator_index in 0..self.validator_registry.len() {
if self.get_effective_balance(validator_index, spec) >= spec.max_deposit_amount {
self.activate_validator(validator_index, true, spec);
}
}
self.deposit_index = initial_validator_deposits.len() as u64;
let genesis_active_index_root = hash_tree_root(get_active_validator_indices(
&self.validator_registry,
spec.genesis_epoch,
));
self.latest_active_index_roots =
vec![genesis_active_index_root; spec.latest_active_index_roots_length];
self.current_shuffling_seed = self.generate_seed(spec.genesis_epoch, spec)?;
Ok(())
}
/// Returns the `hash_tree_root` of the state. /// Returns the `hash_tree_root` of the state.
///
/// Spec v0.4.0
pub fn canonical_root(&self) -> Hash256 { pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..]) Hash256::from_slice(&self.hash_tree_root()[..])
} }
@ -1129,10 +1098,6 @@ impl BeaconState {
} }
} }
fn hash_tree_root<T: TreeHash>(input: Vec<T>) -> Hash256 {
Hash256::from_slice(&input.hash_tree_root()[..])
}
impl Encodable for BeaconState { impl Encodable for BeaconState {
fn ssz_append(&self, s: &mut SszStream) { fn ssz_append(&self, s: &mut SszStream) {
s.append(&self.slot); s.append(&self.slot);

View File

@ -12,12 +12,17 @@ pub const BATCH_SIZE: usize = 1_000; // ~15MB
pub const KEYPAIR_BYTES_LEN: usize = PUBLIC_KEY_BYTES_LEN + SECRET_KEY_BYTES_LEN; pub const KEYPAIR_BYTES_LEN: usize = PUBLIC_KEY_BYTES_LEN + SECRET_KEY_BYTES_LEN;
pub const BATCH_BYTE_LEN: usize = KEYPAIR_BYTES_LEN * BATCH_SIZE; pub const BATCH_BYTE_LEN: usize = KEYPAIR_BYTES_LEN * BATCH_SIZE;
/// Defines a trait that allows reading/writing a vec of `Keypair` from/to a file.
pub trait KeypairsFile { pub trait KeypairsFile {
/// Write to file, without guaranteeing interoperability with other clients.
fn to_raw_file(&self, path: &Path, keypairs: &[Keypair]) -> Result<(), Error>; fn to_raw_file(&self, path: &Path, keypairs: &[Keypair]) -> Result<(), Error>;
/// Read from file, without guaranteeing interoperability with other clients.
fn from_raw_file(path: &Path, count: usize) -> Result<Vec<Keypair>, Error>; fn from_raw_file(path: &Path, count: usize) -> Result<Vec<Keypair>, Error>;
} }
impl KeypairsFile for Vec<Keypair> { impl KeypairsFile for Vec<Keypair> {
/// Write the keypairs to file, using the fastest possible method without guaranteeing
/// interoperability with other clients.
fn to_raw_file(&self, path: &Path, keypairs: &[Keypair]) -> Result<(), Error> { fn to_raw_file(&self, path: &Path, keypairs: &[Keypair]) -> Result<(), Error> {
let mut keypairs_file = File::create(path)?; let mut keypairs_file = File::create(path)?;
@ -35,6 +40,8 @@ impl KeypairsFile for Vec<Keypair> {
Ok(()) Ok(())
} }
/// Read the keypairs from file, using the fastest possible method without guaranteeing
/// interoperability with other clients.
fn from_raw_file(path: &Path, count: usize) -> Result<Vec<Keypair>, Error> { fn from_raw_file(path: &Path, count: usize) -> Result<Vec<Keypair>, Error> {
let mut keypairs_file = File::open(path)?; let mut keypairs_file = File::open(path)?;

View File

@ -1,12 +1,16 @@
use crate::*; use crate::*;
use ssz::TreeHash; use ssz::TreeHash;
/// Builds an attestation to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
pub struct TestingAttestationBuilder { pub struct TestingAttestationBuilder {
committee: Vec<usize>, committee: Vec<usize>,
attestation: Attestation, attestation: Attestation,
} }
impl TestingAttestationBuilder { impl TestingAttestationBuilder {
/// Create a new attestation builder.
pub fn new( pub fn new(
state: &BeaconState, state: &BeaconState,
committee: &[usize], committee: &[usize],
@ -70,6 +74,10 @@ impl TestingAttestationBuilder {
} }
} }
/// Signs the attestation with a subset (or all) committee members.
///
/// `secret_keys` must be supplied in the same order as `signing_validators`. I.e., the first
/// keypair must be that of the first signing validator.
pub fn sign( pub fn sign(
&mut self, &mut self,
signing_validators: &[usize], signing_validators: &[usize],
@ -111,6 +119,7 @@ impl TestingAttestationBuilder {
} }
} }
/// Consume the builder and return the attestation.
pub fn build(self) -> Attestation { pub fn build(self) -> Attestation {
self.attestation self.attestation
} }

View File

@ -2,6 +2,8 @@ use crate::*;
use ssz::TreeHash; use ssz::TreeHash;
/// Builds an `AttesterSlashing`. /// Builds an `AttesterSlashing`.
///
/// This struct should **never be used for production purposes.**
pub struct TestingAttesterSlashingBuilder(); pub struct TestingAttesterSlashingBuilder();
impl TestingAttesterSlashingBuilder { impl TestingAttesterSlashingBuilder {

View File

@ -8,22 +8,29 @@ use crate::{
use rayon::prelude::*; use rayon::prelude::*;
use ssz::{SignedRoot, TreeHash}; use ssz::{SignedRoot, TreeHash};
/// Builds a beacon block to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
pub struct TestingBeaconBlockBuilder { pub struct TestingBeaconBlockBuilder {
block: BeaconBlock, block: BeaconBlock,
} }
impl TestingBeaconBlockBuilder { impl TestingBeaconBlockBuilder {
/// Create a new builder from genesis.
pub fn new(spec: &ChainSpec) -> Self { pub fn new(spec: &ChainSpec) -> Self {
Self { Self {
block: BeaconBlock::genesis(spec.zero_hash, spec), block: BeaconBlock::genesis(spec.zero_hash, spec),
} }
} }
/// Set the slot of the block.
pub fn set_slot(&mut self, slot: Slot) { pub fn set_slot(&mut self, slot: Slot) {
self.block.slot = slot; self.block.slot = slot;
} }
/// Signs the block. /// Signs the block.
///
/// Modifying the block after signing may invalidate the signature.
pub fn sign(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { pub fn sign(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) {
let proposal = self.block.proposal(spec); let proposal = self.block.proposal(spec);
let message = proposal.signed_root(); let message = proposal.signed_root();
@ -33,6 +40,8 @@ impl TestingBeaconBlockBuilder {
} }
/// Sets the randao to be a signature across the blocks epoch. /// Sets the randao to be a signature across the blocks epoch.
///
/// Modifying the block's slot after signing may invalidate the signature.
pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) { pub fn set_randao_reveal(&mut self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) {
let epoch = self.block.slot.epoch(spec.slots_per_epoch); let epoch = self.block.slot.epoch(spec.slots_per_epoch);
let message = epoch.hash_tree_root(); let message = epoch.hash_tree_root();
@ -65,9 +74,15 @@ impl TestingBeaconBlockBuilder {
self.block.body.attester_slashings.push(attester_slashing); self.block.body.attester_slashings.push(attester_slashing);
} }
/// Fills the block with as many attestations as possible. /// Fills the block with `MAX_ATTESTATIONS` attestations.
/// ///
/// Note: this will not perform well when `jepoch_committees_count % slots_per_epoch != 0` /// It will first go and get each committee that is able to include an attestation in this
/// block. If there are enough committees, it will produce an attestation for each. If there
/// are _not_ enough committees, it will start splitting the committees in half until it
/// achieves the target. It will then produce separate attestations for each split committee.
///
/// Note: the signed messages of the split committees will be identical -- it would be possible
/// to aggregate these split attestations.
pub fn fill_with_attestations( pub fn fill_with_attestations(
&mut self, &mut self,
state: &BeaconState, state: &BeaconState,

View File

@ -20,6 +20,9 @@ pub fn keypairs_path() -> PathBuf {
dir.join(KEYPAIRS_FILE) dir.join(KEYPAIRS_FILE)
} }
/// Builds a beacon state to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
pub struct TestingBeaconStateBuilder { pub struct TestingBeaconStateBuilder {
state: BeaconState, state: BeaconState,
keypairs: Vec<Keypair>, keypairs: Vec<Keypair>,

View File

@ -1,11 +1,15 @@
use crate::*; use crate::*;
use bls::get_withdrawal_credentials; use bls::get_withdrawal_credentials;
/// Builds an deposit to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
pub struct TestingDepositBuilder { pub struct TestingDepositBuilder {
deposit: Deposit, deposit: Deposit,
} }
impl TestingDepositBuilder { impl TestingDepositBuilder {
/// Instantiates a new builder.
pub fn new(amount: u64) -> Self { pub fn new(amount: u64) -> Self {
let keypair = Keypair::random(); let keypair = Keypair::random();
@ -26,10 +30,16 @@ impl TestingDepositBuilder {
Self { deposit } Self { deposit }
} }
/// Set the `deposit.index` value.
pub fn set_index(&mut self, index: u64) { pub fn set_index(&mut self, index: u64) {
self.deposit.index = index; self.deposit.index = index;
} }
/// Signs the deposit, also setting the following values:
///
/// - `pubkey` to the signing pubkey.
/// - `withdrawal_credentials` to the signing pubkey.
/// - `proof_of_possesssion`
pub fn sign(&mut self, keypair: &Keypair, state: &BeaconState, spec: &ChainSpec) { pub fn sign(&mut self, keypair: &Keypair, state: &BeaconState, spec: &ChainSpec) {
let withdrawal_credentials = Hash256::from_slice( let withdrawal_credentials = Hash256::from_slice(
&get_withdrawal_credentials(&keypair.pk, spec.bls_withdrawal_prefix_byte)[..], &get_withdrawal_credentials(&keypair.pk, spec.bls_withdrawal_prefix_byte)[..],
@ -47,6 +57,7 @@ impl TestingDepositBuilder {
DepositInput::create_proof_of_possession(&keypair, &withdrawal_credentials, domain); DepositInput::create_proof_of_possession(&keypair, &withdrawal_credentials, domain);
} }
/// Builds the deposit, consuming the builder.
pub fn build(self) -> Deposit { pub fn build(self) -> Deposit {
self.deposit self.deposit
} }

View File

@ -2,6 +2,8 @@ use crate::*;
use ssz::SignedRoot; use ssz::SignedRoot;
/// Builds a `ProposerSlashing`. /// Builds a `ProposerSlashing`.
///
/// This struct should **never be used for production purposes.**
pub struct TestingProposerSlashingBuilder(); pub struct TestingProposerSlashingBuilder();
impl TestingProposerSlashingBuilder { impl TestingProposerSlashingBuilder {

View File

@ -1,11 +1,15 @@
use crate::*; use crate::*;
use ssz::SignedRoot; use ssz::SignedRoot;
/// Builds a transfer to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
pub struct TestingTransferBuilder { pub struct TestingTransferBuilder {
transfer: Transfer, transfer: Transfer,
} }
impl TestingTransferBuilder { impl TestingTransferBuilder {
/// Instantiates a new builder.
pub fn new(from: u64, to: u64, amount: u64, slot: Slot) -> Self { pub fn new(from: u64, to: u64, amount: u64, slot: Slot) -> Self {
let keypair = Keypair::random(); let keypair = Keypair::random();
@ -22,6 +26,9 @@ impl TestingTransferBuilder {
Self { transfer } Self { transfer }
} }
/// Signs the transfer.
///
/// The keypair must match that of the `from` validator index.
pub fn sign(&mut self, keypair: Keypair, fork: &Fork, spec: &ChainSpec) { pub fn sign(&mut self, keypair: Keypair, fork: &Fork, spec: &ChainSpec) {
self.transfer.pubkey = keypair.pk; self.transfer.pubkey = keypair.pk;
let message = self.transfer.signed_root(); let message = self.transfer.signed_root();
@ -31,6 +38,7 @@ impl TestingTransferBuilder {
self.transfer.signature = Signature::new(&message, domain, &keypair.sk); self.transfer.signature = Signature::new(&message, domain, &keypair.sk);
} }
/// Builds the transfer, consuming the builder.
pub fn build(self) -> Transfer { pub fn build(self) -> Transfer {
self.transfer self.transfer
} }

View File

@ -1,11 +1,15 @@
use crate::*; use crate::*;
use ssz::SignedRoot; use ssz::SignedRoot;
/// Builds an exit to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
pub struct TestingVoluntaryExitBuilder { pub struct TestingVoluntaryExitBuilder {
exit: VoluntaryExit, exit: VoluntaryExit,
} }
impl TestingVoluntaryExitBuilder { impl TestingVoluntaryExitBuilder {
/// Instantiates a new builder.
pub fn new(epoch: Epoch, validator_index: u64) -> Self { pub fn new(epoch: Epoch, validator_index: u64) -> Self {
let exit = VoluntaryExit { let exit = VoluntaryExit {
epoch, epoch,
@ -16,6 +20,9 @@ impl TestingVoluntaryExitBuilder {
Self { exit } Self { exit }
} }
/// Signs the exit.
///
/// The signing secret key must match that of the exiting validator.
pub fn sign(&mut self, secret_key: &SecretKey, fork: &Fork, spec: &ChainSpec) { pub fn sign(&mut self, secret_key: &SecretKey, fork: &Fork, spec: &ChainSpec) {
let message = self.exit.signed_root(); let message = self.exit.signed_root();
let domain = spec.get_domain(self.exit.epoch, Domain::Exit, fork); let domain = spec.get_domain(self.exit.epoch, Domain::Exit, fork);
@ -23,6 +30,7 @@ impl TestingVoluntaryExitBuilder {
self.exit.signature = Signature::new(&message, domain, secret_key); self.exit.signature = Signature::new(&message, domain, secret_key);
} }
/// Builds the exit, consuming the builder.
pub fn build(self) -> VoluntaryExit { pub fn build(self) -> VoluntaryExit {
self.exit self.exit
} }