spec v0.6.0: update types
This commit is contained in:
parent
7dda85e87e
commit
1ad0024045
@ -9,7 +9,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
|
|||||||
|
|
||||||
/// Details an attestation that can be slashable.
|
/// Details an attestation that can be slashable.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
Clone,
|
Clone,
|
||||||
@ -28,7 +28,7 @@ pub struct Attestation {
|
|||||||
pub data: AttestationData,
|
pub data: AttestationData,
|
||||||
pub custody_bitfield: Bitfield,
|
pub custody_bitfield: Bitfield,
|
||||||
#[signed_root(skip_hashing)]
|
#[signed_root(skip_hashing)]
|
||||||
pub aggregate_signature: AggregateSignature,
|
pub signature: AggregateSignature,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attestation {
|
impl Attestation {
|
||||||
@ -49,8 +49,7 @@ impl Attestation {
|
|||||||
self.aggregation_bitfield
|
self.aggregation_bitfield
|
||||||
.union_inplace(&other.aggregation_bitfield);
|
.union_inplace(&other.aggregation_bitfield);
|
||||||
self.custody_bitfield.union_inplace(&other.custody_bitfield);
|
self.custody_bitfield.union_inplace(&other.custody_bitfield);
|
||||||
self.aggregate_signature
|
self.signature.add_aggregate(&other.signature);
|
||||||
.add_aggregate(&other.aggregate_signature);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
|
|||||||
|
|
||||||
/// The data upon which an attestation is based.
|
/// The data upon which an attestation is based.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
Clone,
|
Clone,
|
||||||
@ -37,7 +37,7 @@ pub struct AttestationData {
|
|||||||
|
|
||||||
// Crosslink Vote
|
// Crosslink Vote
|
||||||
pub shard: u64,
|
pub shard: u64,
|
||||||
pub previous_crosslink: Crosslink,
|
pub previous_crosslink_root: Crosslink,
|
||||||
pub crosslink_data_root: Hash256,
|
pub crosslink_data_root: Hash256,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{test_utils::TestRandom, SlashableAttestation};
|
use crate::{test_utils::TestRandom, IndexedAttestation};
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
@ -7,7 +7,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
|
|
||||||
/// Two conflicting attestations.
|
/// Two conflicting attestations.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@ -21,8 +21,8 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
TestRandom,
|
TestRandom,
|
||||||
)]
|
)]
|
||||||
pub struct AttesterSlashing {
|
pub struct AttesterSlashing {
|
||||||
pub slashable_attestation_1: SlashableAttestation,
|
pub attestation_1: IndexedAttestation,
|
||||||
pub slashable_attestation_2: SlashableAttestation,
|
pub attestation_2: IndexedAttestation,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -47,6 +47,7 @@ impl BeaconBlock {
|
|||||||
eth1_data: Eth1Data {
|
eth1_data: Eth1Data {
|
||||||
deposit_root: spec.zero_hash,
|
deposit_root: spec.zero_hash,
|
||||||
block_hash: spec.zero_hash,
|
block_hash: spec.zero_hash,
|
||||||
|
deposit_count: 0,
|
||||||
},
|
},
|
||||||
proposer_slashings: vec![],
|
proposer_slashings: vec![],
|
||||||
attester_slashings: vec![],
|
attester_slashings: vec![],
|
||||||
|
@ -69,17 +69,11 @@ pub struct BeaconState {
|
|||||||
|
|
||||||
// Validator registry
|
// Validator registry
|
||||||
pub validator_registry: Vec<Validator>,
|
pub validator_registry: Vec<Validator>,
|
||||||
pub validator_balances: Vec<u64>,
|
pub balances: Vec<u64>,
|
||||||
pub validator_registry_update_epoch: Epoch,
|
|
||||||
|
|
||||||
// Randomness and committees
|
// Randomness and committees
|
||||||
pub latest_randao_mixes: TreeHashVector<Hash256>,
|
pub latest_randao_mixes: TreeHashVector<Hash256>,
|
||||||
pub previous_shuffling_start_shard: u64,
|
pub latest_start_shard: u64,
|
||||||
pub current_shuffling_start_shard: u64,
|
|
||||||
pub previous_shuffling_epoch: Epoch,
|
|
||||||
pub current_shuffling_epoch: Epoch,
|
|
||||||
pub previous_shuffling_seed: Hash256,
|
|
||||||
pub current_shuffling_seed: Hash256,
|
|
||||||
|
|
||||||
// Finality
|
// Finality
|
||||||
pub previous_epoch_attestations: Vec<PendingAttestation>,
|
pub previous_epoch_attestations: Vec<PendingAttestation>,
|
||||||
@ -93,7 +87,8 @@ pub struct BeaconState {
|
|||||||
pub finalized_root: Hash256,
|
pub finalized_root: Hash256,
|
||||||
|
|
||||||
// Recent state
|
// Recent state
|
||||||
pub latest_crosslinks: TreeHashVector<Crosslink>,
|
pub current_crosslinks: TreeHashVector<Crosslink>,
|
||||||
|
pub previous_crosslinks: TreeHashVector<Crosslink>,
|
||||||
pub latest_block_roots: TreeHashVector<Hash256>,
|
pub latest_block_roots: TreeHashVector<Hash256>,
|
||||||
latest_state_roots: TreeHashVector<Hash256>,
|
latest_state_roots: TreeHashVector<Hash256>,
|
||||||
latest_active_index_roots: TreeHashVector<Hash256>,
|
latest_active_index_roots: TreeHashVector<Hash256>,
|
||||||
@ -103,7 +98,7 @@ pub struct BeaconState {
|
|||||||
|
|
||||||
// Ethereum 1.0 chain data
|
// Ethereum 1.0 chain data
|
||||||
pub latest_eth1_data: Eth1Data,
|
pub latest_eth1_data: Eth1Data,
|
||||||
pub eth1_data_votes: Vec<Eth1DataVote>,
|
pub eth1_data_votes: Vec<Eth1Data>,
|
||||||
pub deposit_index: u64,
|
pub deposit_index: u64,
|
||||||
|
|
||||||
// Caching (not in the spec)
|
// Caching (not in the spec)
|
||||||
@ -143,6 +138,7 @@ impl BeaconState {
|
|||||||
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,
|
||||||
|
previous_crosslink_root: spec.zero_hash,
|
||||||
crosslink_data_root: spec.zero_hash,
|
crosslink_data_root: spec.zero_hash,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -154,18 +150,12 @@ impl BeaconState {
|
|||||||
|
|
||||||
// Validator registry
|
// Validator registry
|
||||||
validator_registry: vec![], // Set later in the function.
|
validator_registry: vec![], // Set later in the function.
|
||||||
validator_balances: vec![], // Set later in the function.
|
balances: vec![], // Set later in the function.
|
||||||
validator_registry_update_epoch: spec.genesis_epoch,
|
|
||||||
|
|
||||||
// Randomness and committees
|
// Randomness and committees
|
||||||
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize]
|
latest_randao_mixes: vec![spec.zero_hash; spec.latest_randao_mixes_length as usize]
|
||||||
.into(),
|
.into(),
|
||||||
previous_shuffling_start_shard: spec.genesis_start_shard,
|
latest_start_shard: 0, // FIXME(sproul)
|
||||||
current_shuffling_start_shard: spec.genesis_start_shard,
|
|
||||||
previous_shuffling_epoch: spec.genesis_epoch,
|
|
||||||
current_shuffling_epoch: spec.genesis_epoch,
|
|
||||||
previous_shuffling_seed: spec.zero_hash,
|
|
||||||
current_shuffling_seed: spec.zero_hash,
|
|
||||||
|
|
||||||
// Finality
|
// Finality
|
||||||
previous_epoch_attestations: vec![],
|
previous_epoch_attestations: vec![],
|
||||||
@ -179,7 +169,8 @@ impl BeaconState {
|
|||||||
finalized_root: spec.zero_hash,
|
finalized_root: spec.zero_hash,
|
||||||
|
|
||||||
// Recent state
|
// Recent state
|
||||||
latest_crosslinks: vec![initial_crosslink; spec.shard_count as usize].into(),
|
current_crosslinks: vec![initial_crosslink.clone(); spec.shard_count as usize].into(),
|
||||||
|
previous_crosslinks: vec![initial_crosslink; spec.shard_count as usize].into(),
|
||||||
latest_block_roots: vec![spec.zero_hash; spec.slots_per_historical_root].into(),
|
latest_block_roots: vec![spec.zero_hash; spec.slots_per_historical_root].into(),
|
||||||
latest_state_roots: vec![spec.zero_hash; spec.slots_per_historical_root].into(),
|
latest_state_roots: vec![spec.zero_hash; spec.slots_per_historical_root].into(),
|
||||||
latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length]
|
latest_active_index_roots: vec![spec.zero_hash; spec.latest_active_index_roots_length]
|
||||||
@ -630,7 +621,7 @@ impl BeaconState {
|
|||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<u64, Error> {
|
) -> Result<u64, Error> {
|
||||||
let balance = self
|
let balance = self
|
||||||
.validator_balances
|
.balances
|
||||||
.get(validator_index)
|
.get(validator_index)
|
||||||
.ok_or_else(|| Error::UnknownValidator)?;
|
.ok_or_else(|| Error::UnknownValidator)?;
|
||||||
Ok(std::cmp::min(*balance, spec.max_deposit_amount))
|
Ok(std::cmp::min(*balance, spec.max_deposit_amount))
|
||||||
@ -647,7 +638,8 @@ impl BeaconState {
|
|||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
pub fn initiate_validator_exit(&mut self, validator_index: usize) {
|
pub fn initiate_validator_exit(&mut self, validator_index: usize) {
|
||||||
self.validator_registry[validator_index].initiated_exit = true;
|
// FIXME(sproul)
|
||||||
|
// self.validator_registry[validator_index].initiated_exit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `slot`, `shard` and `committee_index` for which a validator must produce an
|
/// Returns the `slot`, `shard` and `committee_index` for which a validator must produce an
|
||||||
|
@ -207,8 +207,9 @@ impl EpochCrosslinkCommitteesBuilder {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
epoch: state.previous_epoch(spec),
|
epoch: state.previous_epoch(spec),
|
||||||
shuffling_start_shard: state.previous_shuffling_start_shard,
|
// FIXME(sproul)
|
||||||
shuffling_seed: state.previous_shuffling_seed,
|
shuffling_start_shard: 0,
|
||||||
|
shuffling_seed: spec.zero_hash,
|
||||||
committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()),
|
committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()),
|
||||||
active_validator_indices,
|
active_validator_indices,
|
||||||
}
|
}
|
||||||
@ -222,8 +223,9 @@ impl EpochCrosslinkCommitteesBuilder {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
epoch: state.current_epoch(spec),
|
epoch: state.current_epoch(spec),
|
||||||
shuffling_start_shard: state.current_shuffling_start_shard,
|
// FIXME(sproul)
|
||||||
shuffling_seed: state.current_shuffling_seed,
|
shuffling_start_shard: 0,
|
||||||
|
shuffling_seed: spec.zero_hash,
|
||||||
committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()),
|
committees_per_epoch: spec.get_epoch_committee_count(active_validator_indices.len()),
|
||||||
active_validator_indices,
|
active_validator_indices,
|
||||||
}
|
}
|
||||||
@ -243,8 +245,9 @@ impl EpochCrosslinkCommitteesBuilder {
|
|||||||
let next_epoch = state.next_epoch(spec);
|
let next_epoch = state.next_epoch(spec);
|
||||||
let committees_per_epoch = spec.get_epoch_committee_count(active_validator_indices.len());
|
let committees_per_epoch = spec.get_epoch_committee_count(active_validator_indices.len());
|
||||||
|
|
||||||
let epochs_since_last_registry_update =
|
// FIXME(sproul)
|
||||||
current_epoch - state.validator_registry_update_epoch;
|
// current_epoch - state.validator_registry_update_epoch;
|
||||||
|
let epochs_since_last_registry_update = 0u64;
|
||||||
|
|
||||||
let (seed, shuffling_start_shard) = if registry_change {
|
let (seed, shuffling_start_shard) = if registry_change {
|
||||||
let next_seed = state
|
let next_seed = state
|
||||||
@ -252,7 +255,9 @@ impl EpochCrosslinkCommitteesBuilder {
|
|||||||
.map_err(|_| Error::UnableToGenerateSeed)?;
|
.map_err(|_| Error::UnableToGenerateSeed)?;
|
||||||
(
|
(
|
||||||
next_seed,
|
next_seed,
|
||||||
(state.current_shuffling_start_shard + committees_per_epoch) % spec.shard_count,
|
0,
|
||||||
|
// FIXME(sproul)
|
||||||
|
// (state.current_shuffling_start_shard + committees_per_epoch) % spec.shard_count,
|
||||||
)
|
)
|
||||||
} else if (epochs_since_last_registry_update > 1)
|
} else if (epochs_since_last_registry_update > 1)
|
||||||
& epochs_since_last_registry_update.is_power_of_two()
|
& epochs_since_last_registry_update.is_power_of_two()
|
||||||
@ -260,11 +265,13 @@ impl EpochCrosslinkCommitteesBuilder {
|
|||||||
let next_seed = state
|
let next_seed = state
|
||||||
.generate_seed(next_epoch, spec)
|
.generate_seed(next_epoch, spec)
|
||||||
.map_err(|_| Error::UnableToGenerateSeed)?;
|
.map_err(|_| Error::UnableToGenerateSeed)?;
|
||||||
(next_seed, state.current_shuffling_start_shard)
|
(
|
||||||
|
next_seed, 0, /* FIXME(sproul) state.current_shuffling_start_shard*/
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
state.current_shuffling_seed,
|
spec.zero_hash, // state.current_shuffling_seed,
|
||||||
state.current_shuffling_start_shard,
|
0 // state.current_shuffling_start_shard,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
|
|
||||||
/// Specifies the block hash for a shard at an epoch.
|
/// Specifies the block hash for a shard at an epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
Clone,
|
Clone,
|
||||||
@ -25,6 +25,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
)]
|
)]
|
||||||
pub struct Crosslink {
|
pub struct Crosslink {
|
||||||
pub epoch: Epoch,
|
pub epoch: Epoch,
|
||||||
|
pub previous_crosslink_root: Hash256,
|
||||||
pub crosslink_data_root: Hash256,
|
pub crosslink_data_root: Hash256,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
|
|
||||||
/// A deposit to potentially become a beacon chain validator.
|
/// A deposit to potentially become a beacon chain validator.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@ -24,7 +24,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
pub struct Deposit {
|
pub struct Deposit {
|
||||||
pub proof: TreeHashVector<Hash256>,
|
pub proof: TreeHashVector<Hash256>,
|
||||||
pub index: u64,
|
pub index: u64,
|
||||||
pub deposit_data: DepositData,
|
pub data: DepositData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
use super::DepositInput;
|
|
||||||
use crate::test_utils::TestRandom;
|
use crate::test_utils::TestRandom;
|
||||||
|
use crate::*;
|
||||||
|
use bls::{PublicKey, Signature};
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
use test_random_derive::TestRandom;
|
use test_random_derive::TestRandom;
|
||||||
use tree_hash_derive::{CachedTreeHash, TreeHash};
|
use tree_hash::{SignedRoot, TreeHash};
|
||||||
|
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
|
||||||
|
|
||||||
/// Data generated by the deposit contract.
|
/// The data supplied by the user to the deposit contract.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@ -17,14 +19,45 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
Deserialize,
|
Deserialize,
|
||||||
Encode,
|
Encode,
|
||||||
Decode,
|
Decode,
|
||||||
|
SignedRoot,
|
||||||
TreeHash,
|
TreeHash,
|
||||||
CachedTreeHash,
|
CachedTreeHash,
|
||||||
TestRandom,
|
TestRandom,
|
||||||
)]
|
)]
|
||||||
pub struct DepositData {
|
pub struct DepositData {
|
||||||
|
pub pubkey: PublicKey,
|
||||||
|
pub withdrawal_credentials: Hash256,
|
||||||
pub amount: u64,
|
pub amount: u64,
|
||||||
pub timestamp: u64,
|
#[signed_root(skip_hashing)]
|
||||||
pub deposit_input: DepositInput,
|
pub signature: Signature,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DepositData {
|
||||||
|
/// Generate the signature for a given DepositData details.
|
||||||
|
///
|
||||||
|
/// Spec v0.5.1
|
||||||
|
pub fn create_signature(
|
||||||
|
&self,
|
||||||
|
secret_key: &SecretKey,
|
||||||
|
epoch: Epoch,
|
||||||
|
fork: &Fork,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Signature {
|
||||||
|
let msg = self.signed_root();
|
||||||
|
let domain = spec.get_domain(epoch, Domain::Deposit, fork);
|
||||||
|
|
||||||
|
Signature::new(msg.as_slice(), domain, secret_key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Verify that proof-of-possession is valid.
|
||||||
|
///
|
||||||
|
/// Spec v0.5.1
|
||||||
|
pub fn validate_signature(&self, epoch: Epoch, fork: &Fork, spec: &ChainSpec) -> bool {
|
||||||
|
let msg = self.signed_root();
|
||||||
|
let domain = spec.get_domain(epoch, Domain::Deposit, fork);
|
||||||
|
|
||||||
|
self.signature.verify(&msg, domain, &self.pubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -33,4 +66,22 @@ mod tests {
|
|||||||
|
|
||||||
ssz_tests!(DepositData);
|
ssz_tests!(DepositData);
|
||||||
cached_tree_hash_tests!(DepositData);
|
cached_tree_hash_tests!(DepositData);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_create_and_validate() {
|
||||||
|
let spec = ChainSpec::foundation();
|
||||||
|
let fork = Fork::genesis(&spec);
|
||||||
|
let keypair = Keypair::random();
|
||||||
|
let epoch = Epoch::new(0);
|
||||||
|
|
||||||
|
let mut deposit_input = DepositData {
|
||||||
|
pubkey: keypair.pk.clone(),
|
||||||
|
withdrawal_credentials: Hash256::zero(),
|
||||||
|
signature: Signature::empty_signature(),
|
||||||
|
};
|
||||||
|
|
||||||
|
deposit_input.signature = deposit_input.create_signature(&keypair.sk, epoch, &fork, &spec);
|
||||||
|
|
||||||
|
assert!(deposit_input.validate_signature(epoch, &fork, &spec));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
use crate::test_utils::TestRandom;
|
|
||||||
use crate::*;
|
|
||||||
use bls::{PublicKey, Signature};
|
|
||||||
use rand::RngCore;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
use ssz_derive::{Decode, Encode};
|
|
||||||
use test_random_derive::TestRandom;
|
|
||||||
use tree_hash::{SignedRoot, TreeHash};
|
|
||||||
use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
|
|
||||||
|
|
||||||
/// The data supplied by the user to the deposit contract.
|
|
||||||
///
|
|
||||||
/// Spec v0.5.1
|
|
||||||
#[derive(
|
|
||||||
Debug,
|
|
||||||
PartialEq,
|
|
||||||
Clone,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
Encode,
|
|
||||||
Decode,
|
|
||||||
SignedRoot,
|
|
||||||
TreeHash,
|
|
||||||
CachedTreeHash,
|
|
||||||
TestRandom,
|
|
||||||
)]
|
|
||||||
pub struct DepositInput {
|
|
||||||
pub pubkey: PublicKey,
|
|
||||||
pub withdrawal_credentials: Hash256,
|
|
||||||
#[signed_root(skip_hashing)]
|
|
||||||
pub proof_of_possession: Signature,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DepositInput {
|
|
||||||
/// Generate the 'proof_of_posession' signature for a given DepositInput details.
|
|
||||||
///
|
|
||||||
/// Spec v0.5.1
|
|
||||||
pub fn create_proof_of_possession(
|
|
||||||
&self,
|
|
||||||
secret_key: &SecretKey,
|
|
||||||
epoch: Epoch,
|
|
||||||
fork: &Fork,
|
|
||||||
spec: &ChainSpec,
|
|
||||||
) -> Signature {
|
|
||||||
let msg = self.signed_root();
|
|
||||||
let domain = spec.get_domain(epoch, Domain::Deposit, fork);
|
|
||||||
|
|
||||||
Signature::new(msg.as_slice(), domain, secret_key)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Verify that proof-of-possession is valid.
|
|
||||||
///
|
|
||||||
/// Spec v0.5.1
|
|
||||||
pub fn validate_proof_of_possession(
|
|
||||||
&self,
|
|
||||||
epoch: Epoch,
|
|
||||||
fork: &Fork,
|
|
||||||
spec: &ChainSpec,
|
|
||||||
) -> bool {
|
|
||||||
let msg = self.signed_root();
|
|
||||||
let domain = spec.get_domain(epoch, Domain::Deposit, fork);
|
|
||||||
|
|
||||||
self.proof_of_possession.verify(&msg, domain, &self.pubkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
ssz_tests!(DepositInput);
|
|
||||||
cached_tree_hash_tests!(DepositInput);
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_create_and_validate() {
|
|
||||||
let spec = ChainSpec::foundation();
|
|
||||||
let fork = Fork::genesis(&spec);
|
|
||||||
let keypair = Keypair::random();
|
|
||||||
let epoch = Epoch::new(0);
|
|
||||||
|
|
||||||
let mut deposit_input = DepositInput {
|
|
||||||
pubkey: keypair.pk.clone(),
|
|
||||||
withdrawal_credentials: Hash256::zero(),
|
|
||||||
proof_of_possession: Signature::empty_signature(),
|
|
||||||
};
|
|
||||||
|
|
||||||
deposit_input.proof_of_possession =
|
|
||||||
deposit_input.create_proof_of_possession(&keypair.sk, epoch, &fork, &spec);
|
|
||||||
|
|
||||||
assert!(deposit_input.validate_proof_of_possession(epoch, &fork, &spec));
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
|
|
||||||
/// Contains data obtained from the Eth1 chain.
|
/// Contains data obtained from the Eth1 chain.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@ -24,6 +24,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
)]
|
)]
|
||||||
pub struct Eth1Data {
|
pub struct Eth1Data {
|
||||||
pub deposit_root: Hash256,
|
pub deposit_root: Hash256,
|
||||||
|
pub deposit_count: u64,
|
||||||
pub block_hash: Hash256,
|
pub block_hash: Hash256,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
use super::Eth1Data;
|
|
||||||
use crate::test_utils::TestRandom;
|
|
||||||
use rand::RngCore;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
use ssz_derive::{Decode, Encode};
|
|
||||||
use test_random_derive::TestRandom;
|
|
||||||
use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|
||||||
|
|
||||||
/// A summation of votes for some `Eth1Data`.
|
|
||||||
///
|
|
||||||
/// Spec v0.5.1
|
|
||||||
#[derive(
|
|
||||||
Debug,
|
|
||||||
PartialEq,
|
|
||||||
Clone,
|
|
||||||
Default,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
Encode,
|
|
||||||
Decode,
|
|
||||||
TreeHash,
|
|
||||||
CachedTreeHash,
|
|
||||||
TestRandom,
|
|
||||||
)]
|
|
||||||
pub struct Eth1DataVote {
|
|
||||||
pub eth1_data: Eth1Data,
|
|
||||||
pub vote_count: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
ssz_tests!(Eth1DataVote);
|
|
||||||
cached_tree_hash_tests!(Eth1DataVote);
|
|
||||||
}
|
|
@ -10,7 +10,7 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
|
|||||||
///
|
///
|
||||||
/// To be included in an `AttesterSlashing`.
|
/// To be included in an `AttesterSlashing`.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@ -24,27 +24,28 @@ use tree_hash_derive::{CachedTreeHash, SignedRoot, TreeHash};
|
|||||||
TestRandom,
|
TestRandom,
|
||||||
SignedRoot,
|
SignedRoot,
|
||||||
)]
|
)]
|
||||||
pub struct SlashableAttestation {
|
pub struct IndexedAttestation {
|
||||||
/// Lists validator registry indices, not committee indices.
|
/// Lists validator registry indices, not committee indices.
|
||||||
pub validator_indices: Vec<u64>,
|
pub custody_bit_0_indices: Vec<u64>,
|
||||||
|
pub custody_bit_1_indices: Vec<u64>,
|
||||||
pub data: AttestationData,
|
pub data: AttestationData,
|
||||||
pub custody_bitfield: Bitfield,
|
pub custody_bitfield: Bitfield,
|
||||||
#[signed_root(skip_hashing)]
|
#[signed_root(skip_hashing)]
|
||||||
pub aggregate_signature: AggregateSignature,
|
pub signature: AggregateSignature,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SlashableAttestation {
|
impl IndexedAttestation {
|
||||||
/// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target.
|
/// Check if ``attestation_data_1`` and ``attestation_data_2`` have the same target.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
pub fn is_double_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
|
pub fn is_double_vote(&self, other: &IndexedAttestation, spec: &ChainSpec) -> bool {
|
||||||
self.data.slot.epoch(spec.slots_per_epoch) == other.data.slot.epoch(spec.slots_per_epoch)
|
self.data.slot.epoch(spec.slots_per_epoch) == other.data.slot.epoch(spec.slots_per_epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
|
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.5.1
|
||||||
pub fn is_surround_vote(&self, other: &SlashableAttestation, spec: &ChainSpec) -> bool {
|
pub fn is_surround_vote(&self, other: &IndexedAttestation, spec: &ChainSpec) -> bool {
|
||||||
let source_epoch_1 = self.data.source_epoch;
|
let source_epoch_1 = self.data.source_epoch;
|
||||||
let source_epoch_2 = other.data.source_epoch;
|
let source_epoch_2 = other.data.source_epoch;
|
||||||
let target_epoch_1 = self.data.slot.epoch(spec.slots_per_epoch);
|
let target_epoch_1 = self.data.slot.epoch(spec.slots_per_epoch);
|
||||||
@ -64,11 +65,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
pub fn test_is_double_vote_true() {
|
pub fn test_is_double_vote_true() {
|
||||||
let spec = ChainSpec::foundation();
|
let spec = ChainSpec::foundation();
|
||||||
let slashable_vote_first = create_slashable_attestation(1, 1, &spec);
|
let indexed_vote_first = create_indexed_attestation(1, 1, &spec);
|
||||||
let slashable_vote_second = create_slashable_attestation(1, 1, &spec);
|
let indexed_vote_second = create_indexed_attestation(1, 1, &spec);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slashable_vote_first.is_double_vote(&slashable_vote_second, &spec),
|
indexed_vote_first.is_double_vote(&indexed_vote_second, &spec),
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -76,11 +77,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
pub fn test_is_double_vote_false() {
|
pub fn test_is_double_vote_false() {
|
||||||
let spec = ChainSpec::foundation();
|
let spec = ChainSpec::foundation();
|
||||||
let slashable_vote_first = create_slashable_attestation(1, 1, &spec);
|
let indexed_vote_first = create_indexed_attestation(1, 1, &spec);
|
||||||
let slashable_vote_second = create_slashable_attestation(2, 1, &spec);
|
let indexed_vote_second = create_indexed_attestation(2, 1, &spec);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slashable_vote_first.is_double_vote(&slashable_vote_second, &spec),
|
indexed_vote_first.is_double_vote(&indexed_vote_second, &spec),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -88,11 +89,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
pub fn test_is_surround_vote_true() {
|
pub fn test_is_surround_vote_true() {
|
||||||
let spec = ChainSpec::foundation();
|
let spec = ChainSpec::foundation();
|
||||||
let slashable_vote_first = create_slashable_attestation(2, 1, &spec);
|
let indexed_vote_first = create_indexed_attestation(2, 1, &spec);
|
||||||
let slashable_vote_second = create_slashable_attestation(1, 2, &spec);
|
let indexed_vote_second = create_indexed_attestation(1, 2, &spec);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
|
indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -100,11 +101,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
pub fn test_is_surround_vote_true_realistic() {
|
pub fn test_is_surround_vote_true_realistic() {
|
||||||
let spec = ChainSpec::foundation();
|
let spec = ChainSpec::foundation();
|
||||||
let slashable_vote_first = create_slashable_attestation(4, 1, &spec);
|
let indexed_vote_first = create_indexed_attestation(4, 1, &spec);
|
||||||
let slashable_vote_second = create_slashable_attestation(3, 2, &spec);
|
let indexed_vote_second = create_indexed_attestation(3, 2, &spec);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
|
indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -112,11 +113,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
pub fn test_is_surround_vote_false_source_epoch_fails() {
|
pub fn test_is_surround_vote_false_source_epoch_fails() {
|
||||||
let spec = ChainSpec::foundation();
|
let spec = ChainSpec::foundation();
|
||||||
let slashable_vote_first = create_slashable_attestation(2, 2, &spec);
|
let indexed_vote_first = create_indexed_attestation(2, 2, &spec);
|
||||||
let slashable_vote_second = create_slashable_attestation(1, 1, &spec);
|
let indexed_vote_second = create_indexed_attestation(1, 1, &spec);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
|
indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -124,28 +125,28 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
pub fn test_is_surround_vote_false_target_epoch_fails() {
|
pub fn test_is_surround_vote_false_target_epoch_fails() {
|
||||||
let spec = ChainSpec::foundation();
|
let spec = ChainSpec::foundation();
|
||||||
let slashable_vote_first = create_slashable_attestation(1, 1, &spec);
|
let indexed_vote_first = create_indexed_attestation(1, 1, &spec);
|
||||||
let slashable_vote_second = create_slashable_attestation(2, 2, &spec);
|
let indexed_vote_second = create_indexed_attestation(2, 2, &spec);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
slashable_vote_first.is_surround_vote(&slashable_vote_second, &spec),
|
indexed_vote_first.is_surround_vote(&indexed_vote_second, &spec),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssz_tests!(SlashableAttestation);
|
ssz_tests!(IndexedAttestation);
|
||||||
cached_tree_hash_tests!(SlashableAttestation);
|
cached_tree_hash_tests!(IndexedAttestation);
|
||||||
|
|
||||||
fn create_slashable_attestation(
|
fn create_indexed_attestation(
|
||||||
slot_factor: u64,
|
slot_factor: u64,
|
||||||
source_epoch: u64,
|
source_epoch: u64,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> SlashableAttestation {
|
) -> IndexedAttestation {
|
||||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||||
let mut slashable_vote = SlashableAttestation::random_for_test(&mut rng);
|
let mut indexed_vote = IndexedAttestation::random_for_test(&mut rng);
|
||||||
|
|
||||||
slashable_vote.data.slot = Slot::new(slot_factor * spec.slots_per_epoch);
|
indexed_vote.data.slot = Slot::new(slot_factor * spec.slots_per_epoch);
|
||||||
slashable_vote.data.source_epoch = Epoch::new(source_epoch);
|
indexed_vote.data.source_epoch = Epoch::new(source_epoch);
|
||||||
slashable_vote
|
indexed_vote
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,15 +17,13 @@ pub mod crosslink;
|
|||||||
pub mod crosslink_committee;
|
pub mod crosslink_committee;
|
||||||
pub mod deposit;
|
pub mod deposit;
|
||||||
pub mod deposit_data;
|
pub mod deposit_data;
|
||||||
pub mod deposit_input;
|
|
||||||
pub mod eth1_data;
|
pub mod eth1_data;
|
||||||
pub mod eth1_data_vote;
|
|
||||||
pub mod fork;
|
pub mod fork;
|
||||||
pub mod free_attestation;
|
pub mod free_attestation;
|
||||||
pub mod historical_batch;
|
pub mod historical_batch;
|
||||||
|
pub mod indexed_attestation;
|
||||||
pub mod pending_attestation;
|
pub mod pending_attestation;
|
||||||
pub mod proposer_slashing;
|
pub mod proposer_slashing;
|
||||||
pub mod slashable_attestation;
|
|
||||||
pub mod transfer;
|
pub mod transfer;
|
||||||
pub mod tree_hash_vector;
|
pub mod tree_hash_vector;
|
||||||
pub mod voluntary_exit;
|
pub mod voluntary_exit;
|
||||||
@ -53,16 +51,14 @@ pub use crate::crosslink::Crosslink;
|
|||||||
pub use crate::crosslink_committee::CrosslinkCommittee;
|
pub use crate::crosslink_committee::CrosslinkCommittee;
|
||||||
pub use crate::deposit::Deposit;
|
pub use crate::deposit::Deposit;
|
||||||
pub use crate::deposit_data::DepositData;
|
pub use crate::deposit_data::DepositData;
|
||||||
pub use crate::deposit_input::DepositInput;
|
|
||||||
pub use crate::eth1_data::Eth1Data;
|
pub use crate::eth1_data::Eth1Data;
|
||||||
pub use crate::eth1_data_vote::Eth1DataVote;
|
|
||||||
pub use crate::fork::Fork;
|
pub use crate::fork::Fork;
|
||||||
pub use crate::free_attestation::FreeAttestation;
|
pub use crate::free_attestation::FreeAttestation;
|
||||||
pub use crate::historical_batch::HistoricalBatch;
|
pub use crate::historical_batch::HistoricalBatch;
|
||||||
|
pub use crate::indexed_attestation::IndexedAttestation;
|
||||||
pub use crate::pending_attestation::PendingAttestation;
|
pub use crate::pending_attestation::PendingAttestation;
|
||||||
pub use crate::proposer_slashing::ProposerSlashing;
|
pub use crate::proposer_slashing::ProposerSlashing;
|
||||||
pub use crate::relative_epoch::{Error as RelativeEpochError, RelativeEpoch};
|
pub use crate::relative_epoch::{Error as RelativeEpochError, RelativeEpoch};
|
||||||
pub use crate::slashable_attestation::SlashableAttestation;
|
|
||||||
pub use crate::slot_epoch::{Epoch, Slot};
|
pub use crate::slot_epoch::{Epoch, Slot};
|
||||||
pub use crate::slot_height::SlotHeight;
|
pub use crate::slot_height::SlotHeight;
|
||||||
pub use crate::transfer::Transfer;
|
pub use crate::transfer::Transfer;
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
|
|
||||||
/// An attestation that has been included in the state but not yet fully processed.
|
/// An attestation that has been included in the state but not yet fully processed.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
Clone,
|
Clone,
|
||||||
@ -24,18 +24,22 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
pub struct PendingAttestation {
|
pub struct PendingAttestation {
|
||||||
pub aggregation_bitfield: Bitfield,
|
pub aggregation_bitfield: Bitfield,
|
||||||
pub data: AttestationData,
|
pub data: AttestationData,
|
||||||
pub custody_bitfield: Bitfield,
|
|
||||||
pub inclusion_slot: Slot,
|
pub inclusion_slot: Slot,
|
||||||
|
pub proposer_index: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PendingAttestation {
|
impl PendingAttestation {
|
||||||
/// Create a `PendingAttestation` from an `Attestation`, at the given `inclusion_slot`.
|
/// Create a `PendingAttestation` from an `Attestation`.
|
||||||
pub fn from_attestation(attestation: &Attestation, inclusion_slot: Slot) -> Self {
|
pub fn from_attestation(
|
||||||
|
attestation: &Attestation,
|
||||||
|
inclusion_slot: Slot,
|
||||||
|
proposer_index: u64,
|
||||||
|
) -> Self {
|
||||||
PendingAttestation {
|
PendingAttestation {
|
||||||
data: attestation.data.clone(),
|
data: attestation.data.clone(),
|
||||||
aggregation_bitfield: attestation.aggregation_bitfield.clone(),
|
aggregation_bitfield: attestation.aggregation_bitfield.clone(),
|
||||||
custody_bitfield: attestation.custody_bitfield.clone(),
|
|
||||||
inclusion_slot,
|
inclusion_slot,
|
||||||
|
proposer_index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ impl TestingAttestationBuilder {
|
|||||||
aggregation_bitfield,
|
aggregation_bitfield,
|
||||||
data: data_builder.build(),
|
data: data_builder.build(),
|
||||||
custody_bitfield,
|
custody_bitfield,
|
||||||
aggregate_signature: AggregateSignature::new(),
|
signature: AggregateSignature::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -83,7 +83,7 @@ impl TestingAttestationBuilder {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let signature = Signature::new(&message, domain, secret_keys[key_index]);
|
let signature = Signature::new(&message, domain, secret_keys[key_index]);
|
||||||
self.attestation.aggregate_signature.add(&signature)
|
self.attestation.signature.add(&signature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +49,9 @@ impl TestingAttestationDataBuilder {
|
|||||||
|
|
||||||
// Crosslink vote
|
// Crosslink vote
|
||||||
shard,
|
shard,
|
||||||
previous_crosslink: Crosslink {
|
previous_crosslink_root: Crosslink {
|
||||||
epoch: slot.epoch(spec.slots_per_epoch),
|
epoch: slot.epoch(spec.slots_per_epoch),
|
||||||
|
previous_crosslink_root: spec.zero_hash,
|
||||||
crosslink_data_root: spec.zero_hash,
|
crosslink_data_root: spec.zero_hash,
|
||||||
},
|
},
|
||||||
crosslink_data_root: spec.zero_hash,
|
crosslink_data_root: spec.zero_hash,
|
||||||
|
@ -34,8 +34,9 @@ impl TestingAttesterSlashingBuilder {
|
|||||||
source_root: hash_1,
|
source_root: hash_1,
|
||||||
target_root: hash_1,
|
target_root: hash_1,
|
||||||
shard,
|
shard,
|
||||||
previous_crosslink: Crosslink {
|
previous_crosslink_root: Crosslink {
|
||||||
epoch,
|
epoch,
|
||||||
|
previous_crosslink_root: hash_1,
|
||||||
crosslink_data_root: hash_1,
|
crosslink_data_root: hash_1,
|
||||||
},
|
},
|
||||||
crosslink_data_root: hash_1,
|
crosslink_data_root: hash_1,
|
||||||
@ -46,21 +47,23 @@ impl TestingAttesterSlashingBuilder {
|
|||||||
..data_1.clone()
|
..data_1.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut slashable_attestation_1 = SlashableAttestation {
|
let mut attestation_1 = IndexedAttestation {
|
||||||
validator_indices: validator_indices.to_vec(),
|
custody_bit_0_indices: validator_indices.to_vec(),
|
||||||
|
custody_bit_1_indices: vec![],
|
||||||
data: data_1,
|
data: data_1,
|
||||||
custody_bitfield: Bitfield::new(),
|
custody_bitfield: Bitfield::new(),
|
||||||
aggregate_signature: AggregateSignature::new(),
|
signature: AggregateSignature::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut slashable_attestation_2 = SlashableAttestation {
|
let mut attestation_2 = IndexedAttestation {
|
||||||
validator_indices: validator_indices.to_vec(),
|
custody_bit_0_indices: validator_indices.to_vec(),
|
||||||
|
custody_bit_1_indices: vec![],
|
||||||
data: data_2,
|
data: data_2,
|
||||||
custody_bitfield: Bitfield::new(),
|
custody_bitfield: Bitfield::new(),
|
||||||
aggregate_signature: AggregateSignature::new(),
|
signature: AggregateSignature::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let add_signatures = |attestation: &mut SlashableAttestation| {
|
let add_signatures = |attestation: &mut IndexedAttestation| {
|
||||||
// All validators sign with a `false` custody bit.
|
// All validators sign with a `false` custody bit.
|
||||||
let attestation_data_and_custody_bit = AttestationDataAndCustodyBit {
|
let attestation_data_and_custody_bit = AttestationDataAndCustodyBit {
|
||||||
data: attestation.data.clone(),
|
data: attestation.data.clone(),
|
||||||
@ -71,16 +74,16 @@ impl TestingAttesterSlashingBuilder {
|
|||||||
for (i, validator_index) in validator_indices.iter().enumerate() {
|
for (i, validator_index) in validator_indices.iter().enumerate() {
|
||||||
attestation.custody_bitfield.set(i, false);
|
attestation.custody_bitfield.set(i, false);
|
||||||
let signature = signer(*validator_index, &message[..], epoch, Domain::Attestation);
|
let signature = signer(*validator_index, &message[..], epoch, Domain::Attestation);
|
||||||
attestation.aggregate_signature.add(&signature);
|
attestation.signature.add(&signature);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
add_signatures(&mut slashable_attestation_1);
|
add_signatures(&mut attestation_1);
|
||||||
add_signatures(&mut slashable_attestation_2);
|
add_signatures(&mut attestation_2);
|
||||||
|
|
||||||
AttesterSlashing {
|
AttesterSlashing {
|
||||||
slashable_attestation_1,
|
attestation_1,
|
||||||
slashable_attestation_2,
|
attestation_2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,7 @@ impl TestingBeaconStateBuilder {
|
|||||||
/// Creates the builder from an existing set of keypairs.
|
/// Creates the builder from an existing set of keypairs.
|
||||||
pub fn from_keypairs(keypairs: Vec<Keypair>, spec: &ChainSpec) -> Self {
|
pub fn from_keypairs(keypairs: Vec<Keypair>, spec: &ChainSpec) -> Self {
|
||||||
let validator_count = keypairs.len();
|
let validator_count = keypairs.len();
|
||||||
|
let starting_balance = 32_000_000_000;
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Building {} Validator objects from keypairs...",
|
"Building {} Validator objects from keypairs...",
|
||||||
@ -112,11 +113,12 @@ impl TestingBeaconStateBuilder {
|
|||||||
pubkey: keypair.pk.clone(),
|
pubkey: keypair.pk.clone(),
|
||||||
withdrawal_credentials,
|
withdrawal_credentials,
|
||||||
// All validators start active.
|
// All validators start active.
|
||||||
|
activation_eligibility_epoch: spec.genesis_epoch,
|
||||||
activation_epoch: spec.genesis_epoch,
|
activation_epoch: spec.genesis_epoch,
|
||||||
exit_epoch: spec.far_future_epoch,
|
exit_epoch: spec.far_future_epoch,
|
||||||
withdrawable_epoch: spec.far_future_epoch,
|
withdrawable_epoch: spec.far_future_epoch,
|
||||||
initiated_exit: false,
|
|
||||||
slashed: false,
|
slashed: false,
|
||||||
|
effective_balance: starting_balance,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -137,16 +139,17 @@ impl TestingBeaconStateBuilder {
|
|||||||
genesis_time,
|
genesis_time,
|
||||||
Eth1Data {
|
Eth1Data {
|
||||||
deposit_root: Hash256::zero(),
|
deposit_root: Hash256::zero(),
|
||||||
|
deposit_count: 0,
|
||||||
block_hash: Hash256::zero(),
|
block_hash: Hash256::zero(),
|
||||||
},
|
},
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
let balances = vec![32_000_000_000; validator_count];
|
let balances = vec![starting_balance; validator_count];
|
||||||
|
|
||||||
debug!("Importing {} existing validators...", validator_count);
|
debug!("Importing {} existing validators...", validator_count);
|
||||||
state.validator_registry = validators;
|
state.validator_registry = validators;
|
||||||
state.validator_balances = balances;
|
state.balances = balances;
|
||||||
|
|
||||||
debug!("BeaconState initialized.");
|
debug!("BeaconState initialized.");
|
||||||
|
|
||||||
@ -192,18 +195,13 @@ impl TestingBeaconStateBuilder {
|
|||||||
|
|
||||||
state.slot = slot;
|
state.slot = slot;
|
||||||
|
|
||||||
state.previous_shuffling_epoch = epoch - 1;
|
// FIXME(sproul): update latest_start_shard?
|
||||||
state.current_shuffling_epoch = epoch;
|
|
||||||
|
|
||||||
state.previous_shuffling_seed = Hash256::from_low_u64_le(0);
|
|
||||||
state.current_shuffling_seed = Hash256::from_low_u64_le(1);
|
|
||||||
|
|
||||||
state.previous_justified_epoch = epoch - 3;
|
state.previous_justified_epoch = epoch - 3;
|
||||||
state.current_justified_epoch = epoch - 2;
|
state.current_justified_epoch = epoch - 2;
|
||||||
state.justification_bitfield = u64::max_value();
|
state.justification_bitfield = u64::max_value();
|
||||||
|
|
||||||
state.finalized_epoch = epoch - 3;
|
state.finalized_epoch = epoch - 3;
|
||||||
state.validator_registry_update_epoch = epoch - 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a full set of attestations for the `BeaconState`. Each attestation has full
|
/// Creates a full set of attestations for the `BeaconState`. Each attestation has full
|
||||||
|
@ -14,14 +14,11 @@ impl TestingDepositBuilder {
|
|||||||
let deposit = Deposit {
|
let deposit = Deposit {
|
||||||
proof: vec![].into(),
|
proof: vec![].into(),
|
||||||
index: 0,
|
index: 0,
|
||||||
deposit_data: DepositData {
|
data: DepositData {
|
||||||
amount,
|
|
||||||
timestamp: 1,
|
|
||||||
deposit_input: DepositInput {
|
|
||||||
pubkey,
|
pubkey,
|
||||||
withdrawal_credentials: Hash256::zero(),
|
withdrawal_credentials: Hash256::zero(),
|
||||||
proof_of_possession: Signature::empty_signature(),
|
amount,
|
||||||
},
|
signature: Signature::empty_signature(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,17 +40,13 @@ impl TestingDepositBuilder {
|
|||||||
&get_withdrawal_credentials(&keypair.pk, spec.bls_withdrawal_prefix_byte)[..],
|
&get_withdrawal_credentials(&keypair.pk, spec.bls_withdrawal_prefix_byte)[..],
|
||||||
);
|
);
|
||||||
|
|
||||||
self.deposit.deposit_data.deposit_input.pubkey = keypair.pk.clone();
|
self.deposit.data.pubkey = keypair.pk.clone();
|
||||||
self.deposit
|
self.deposit.data.withdrawal_credentials = withdrawal_credentials;
|
||||||
.deposit_data
|
|
||||||
.deposit_input
|
|
||||||
.withdrawal_credentials = withdrawal_credentials;
|
|
||||||
|
|
||||||
self.deposit.deposit_data.deposit_input.proof_of_possession = self
|
self.deposit.data.signature =
|
||||||
.deposit
|
self.deposit
|
||||||
.deposit_data
|
.data
|
||||||
.deposit_input
|
.create_signature(&keypair.sk, epoch, fork, spec);
|
||||||
.create_proof_of_possession(&keypair.sk, epoch, fork, spec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the deposit, consuming the builder.
|
/// Builds the deposit, consuming the builder.
|
||||||
|
@ -22,8 +22,9 @@ impl TestingPendingAttestationBuilder {
|
|||||||
let pending_attestation = PendingAttestation {
|
let pending_attestation = PendingAttestation {
|
||||||
aggregation_bitfield: Bitfield::new(),
|
aggregation_bitfield: Bitfield::new(),
|
||||||
data: data_builder.build(),
|
data: data_builder.build(),
|
||||||
custody_bitfield: Bitfield::new(),
|
|
||||||
inclusion_slot: slot + spec.min_attestation_inclusion_delay,
|
inclusion_slot: slot + spec.min_attestation_inclusion_delay,
|
||||||
|
// FIXME(sproul)
|
||||||
|
proposer_index: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -37,15 +38,12 @@ impl TestingPendingAttestationBuilder {
|
|||||||
/// `signers` is true.
|
/// `signers` is true.
|
||||||
pub fn add_committee_participation(&mut self, signers: Vec<bool>) {
|
pub fn add_committee_participation(&mut self, signers: Vec<bool>) {
|
||||||
let mut aggregation_bitfield = Bitfield::new();
|
let mut aggregation_bitfield = Bitfield::new();
|
||||||
let mut custody_bitfield = Bitfield::new();
|
|
||||||
|
|
||||||
for (i, signed) in signers.iter().enumerate() {
|
for (i, signed) in signers.iter().enumerate() {
|
||||||
aggregation_bitfield.set(i, *signed);
|
aggregation_bitfield.set(i, *signed);
|
||||||
custody_bitfield.set(i, false); // Fixed to `false` for phase 0.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pending_attestation.aggregation_bitfield = aggregation_bitfield;
|
self.pending_attestation.aggregation_bitfield = aggregation_bitfield;
|
||||||
self.pending_attestation.custody_bitfield = custody_bitfield;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `PendingAttestation`, consuming the builder.
|
/// Returns the `PendingAttestation`, consuming the builder.
|
||||||
|
@ -7,7 +7,7 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
|
|
||||||
/// Information about a `BeaconChain` validator.
|
/// Information about a `BeaconChain` validator.
|
||||||
///
|
///
|
||||||
/// Spec v0.5.1
|
/// Spec v0.6.0
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
Clone,
|
Clone,
|
||||||
@ -23,11 +23,12 @@ use tree_hash_derive::{CachedTreeHash, TreeHash};
|
|||||||
pub struct Validator {
|
pub struct Validator {
|
||||||
pub pubkey: PublicKey,
|
pub pubkey: PublicKey,
|
||||||
pub withdrawal_credentials: Hash256,
|
pub withdrawal_credentials: Hash256,
|
||||||
|
pub activation_eligibility_epoch: Epoch,
|
||||||
pub activation_epoch: Epoch,
|
pub activation_epoch: Epoch,
|
||||||
pub exit_epoch: Epoch,
|
pub exit_epoch: Epoch,
|
||||||
pub withdrawable_epoch: Epoch,
|
pub withdrawable_epoch: Epoch,
|
||||||
pub initiated_exit: bool,
|
|
||||||
pub slashed: bool,
|
pub slashed: bool,
|
||||||
|
pub effective_balance: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validator {
|
impl Validator {
|
||||||
@ -53,11 +54,12 @@ impl Default for Validator {
|
|||||||
Self {
|
Self {
|
||||||
pubkey: PublicKey::default(),
|
pubkey: PublicKey::default(),
|
||||||
withdrawal_credentials: Hash256::default(),
|
withdrawal_credentials: Hash256::default(),
|
||||||
|
activation_eligibility_epoch: Epoch::from(std::u64::MAX),
|
||||||
activation_epoch: Epoch::from(std::u64::MAX),
|
activation_epoch: Epoch::from(std::u64::MAX),
|
||||||
exit_epoch: Epoch::from(std::u64::MAX),
|
exit_epoch: Epoch::from(std::u64::MAX),
|
||||||
withdrawable_epoch: Epoch::from(std::u64::MAX),
|
withdrawable_epoch: Epoch::from(std::u64::MAX),
|
||||||
initiated_exit: false,
|
|
||||||
slashed: false,
|
slashed: false,
|
||||||
|
effective_balance: std::u64::MAX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user