Update to spec v0.11 (#959)
* Update process_final_updates() hysteresis computation * Update core to v0.11.1 * Bump tags to v0.11.1 * Update docs and deposit contract * Add compute_fork_digest * Address review comments Co-authored-by: Herman Alonso Junge <alonso.junge@gmail.com>
This commit is contained in:
parent
e04fc8ddb4
commit
26bdc2927b
@ -39,7 +39,7 @@ Like all Ethereum 2.0 clients, Lighthouse is a work-in-progress.
|
|||||||
|
|
||||||
Current development overview:
|
Current development overview:
|
||||||
|
|
||||||
- Specification `v0.10.1` implemented, optimized and passing test vectors.
|
- Specification `v0.11.1` implemented, optimized and passing test vectors.
|
||||||
- Rust-native libp2p with Gossipsub and Discv5.
|
- Rust-native libp2p with Gossipsub and Discv5.
|
||||||
- RESTful JSON API via HTTP server.
|
- RESTful JSON API via HTTP server.
|
||||||
- Events via WebSocket.
|
- Events via WebSocket.
|
||||||
|
@ -153,6 +153,8 @@ pub struct HeadInfo {
|
|||||||
pub current_justified_checkpoint: types::Checkpoint,
|
pub current_justified_checkpoint: types::Checkpoint,
|
||||||
pub finalized_checkpoint: types::Checkpoint,
|
pub finalized_checkpoint: types::Checkpoint,
|
||||||
pub fork: Fork,
|
pub fork: Fork,
|
||||||
|
pub genesis_time: u64,
|
||||||
|
pub genesis_validators_root: Hash256,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BeaconChainTypes: Send + Sync + 'static {
|
pub trait BeaconChainTypes: Send + Sync + 'static {
|
||||||
@ -492,6 +494,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
current_justified_checkpoint: head.beacon_state.current_justified_checkpoint.clone(),
|
current_justified_checkpoint: head.beacon_state.current_justified_checkpoint.clone(),
|
||||||
finalized_checkpoint: head.beacon_state.finalized_checkpoint.clone(),
|
finalized_checkpoint: head.beacon_state.finalized_checkpoint.clone(),
|
||||||
fork: head.beacon_state.fork.clone(),
|
fork: head.beacon_state.fork.clone(),
|
||||||
|
genesis_time: head.beacon_state.genesis_time,
|
||||||
|
genesis_validators_root: head.beacon_state.genesis_validators_root,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,17 +1035,23 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
})
|
})
|
||||||
.collect::<Result<Vec<&PublicKey>, Error>>()?;
|
.collect::<Result<Vec<&PublicKey>, Error>>()?;
|
||||||
|
|
||||||
let fork = self
|
let (fork, genesis_validators_root) = self
|
||||||
.canonical_head
|
.canonical_head
|
||||||
.try_read_for(HEAD_LOCK_TIMEOUT)
|
.try_read_for(HEAD_LOCK_TIMEOUT)
|
||||||
.ok_or_else(|| Error::CanonicalHeadLockTimeout)
|
.ok_or_else(|| Error::CanonicalHeadLockTimeout)
|
||||||
.map(|head| head.beacon_state.fork.clone())?;
|
.map(|head| {
|
||||||
|
(
|
||||||
|
head.beacon_state.fork.clone(),
|
||||||
|
head.beacon_state.genesis_validators_root,
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
let signature_set = indexed_attestation_signature_set_from_pubkeys(
|
let signature_set = indexed_attestation_signature_set_from_pubkeys(
|
||||||
pubkeys,
|
pubkeys,
|
||||||
&attestation.signature,
|
&attestation.signature,
|
||||||
&indexed_attestation,
|
&indexed_attestation,
|
||||||
&fork,
|
&fork,
|
||||||
|
genesis_validators_root,
|
||||||
&self.spec,
|
&self.spec,
|
||||||
)
|
)
|
||||||
.map_err(Error::SignatureSetError)?;
|
.map_err(Error::SignatureSetError)?;
|
||||||
@ -1074,8 +1084,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
// Provide the valid attestation to op pool, which may choose to retain the
|
// Provide the valid attestation to op pool, which may choose to retain the
|
||||||
// attestation for inclusion in a future block.
|
// attestation for inclusion in a future block.
|
||||||
if self.eth1_chain.is_some() {
|
if self.eth1_chain.is_some() {
|
||||||
self.op_pool
|
self.op_pool.insert_attestation(
|
||||||
.insert_attestation(attestation, &fork, &self.spec)?;
|
attestation,
|
||||||
|
&fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
&self.spec,
|
||||||
|
)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(AttestationProcessingOutcome::Processed)
|
Ok(AttestationProcessingOutcome::Processed)
|
||||||
@ -1547,6 +1561,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
let mut block = SignedBeaconBlock {
|
let mut block = SignedBeaconBlock {
|
||||||
message: BeaconBlock {
|
message: BeaconBlock {
|
||||||
slot: state.slot,
|
slot: state.slot,
|
||||||
|
proposer_index: state.get_beacon_proposer_index(state.slot, &self.spec)? as u64,
|
||||||
parent_root,
|
parent_root,
|
||||||
state_root: Hash256::zero(),
|
state_root: Hash256::zero(),
|
||||||
body: BeaconBlockBody {
|
body: BeaconBlockBody {
|
||||||
|
@ -313,7 +313,9 @@ where
|
|||||||
|
|
||||||
let randao_reveal = {
|
let randao_reveal = {
|
||||||
let epoch = slot.epoch(E::slots_per_epoch());
|
let epoch = slot.epoch(E::slots_per_epoch());
|
||||||
let domain = self.spec.get_domain(epoch, Domain::Randao, fork);
|
let domain =
|
||||||
|
self.spec
|
||||||
|
.get_domain(epoch, Domain::Randao, fork, state.genesis_validators_root);
|
||||||
let message = epoch.signing_root(domain);
|
let message = epoch.signing_root(domain);
|
||||||
Signature::new(message.as_bytes(), sk)
|
Signature::new(message.as_bytes(), sk)
|
||||||
};
|
};
|
||||||
@ -323,7 +325,7 @@ where
|
|||||||
.produce_block_on_state(state, slot, randao_reveal)
|
.produce_block_on_state(state, slot, randao_reveal)
|
||||||
.expect("should produce block");
|
.expect("should produce block");
|
||||||
|
|
||||||
let signed_block = block.sign(sk, &state.fork, &self.spec);
|
let signed_block = block.sign(sk, &state.fork, state.genesis_validators_root, &self.spec);
|
||||||
|
|
||||||
(signed_block, state)
|
(signed_block, state)
|
||||||
}
|
}
|
||||||
@ -408,6 +410,7 @@ where
|
|||||||
attestation.data.target.epoch,
|
attestation.data.target.epoch,
|
||||||
Domain::BeaconAttester,
|
Domain::BeaconAttester,
|
||||||
fork,
|
fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = attestation.data.signing_root(domain);
|
let message = attestation.data.signing_root(domain);
|
||||||
|
@ -494,7 +494,15 @@ pub fn get_genesis_time<T: BeaconChainTypes>(
|
|||||||
req: Request<Body>,
|
req: Request<Body>,
|
||||||
beacon_chain: Arc<BeaconChain<T>>,
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
) -> ApiResult {
|
) -> ApiResult {
|
||||||
ResponseBuilder::new(&req)?.body(&beacon_chain.head()?.beacon_state.genesis_time)
|
ResponseBuilder::new(&req)?.body(&beacon_chain.head_info()?.genesis_time)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the `genesis_validators_root` from the current beacon chain state.
|
||||||
|
pub fn get_genesis_validators_root<T: BeaconChainTypes>(
|
||||||
|
req: Request<Body>,
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
|
ResponseBuilder::new(&req)?.body(&beacon_chain.head_info()?.genesis_validators_root)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn proposer_slashing<T: BeaconChainTypes>(
|
pub fn proposer_slashing<T: BeaconChainTypes>(
|
||||||
|
@ -37,13 +37,13 @@ pub struct VoteCount {
|
|||||||
impl Into<VoteCount> for TotalBalances {
|
impl Into<VoteCount> for TotalBalances {
|
||||||
fn into(self) -> VoteCount {
|
fn into(self) -> VoteCount {
|
||||||
VoteCount {
|
VoteCount {
|
||||||
current_epoch_active_gwei: self.current_epoch,
|
current_epoch_active_gwei: self.current_epoch(),
|
||||||
previous_epoch_active_gwei: self.previous_epoch,
|
previous_epoch_active_gwei: self.previous_epoch(),
|
||||||
current_epoch_attesting_gwei: self.current_epoch_attesters,
|
current_epoch_attesting_gwei: self.current_epoch_attesters(),
|
||||||
current_epoch_target_attesting_gwei: self.current_epoch_target_attesters,
|
current_epoch_target_attesting_gwei: self.current_epoch_target_attesters(),
|
||||||
previous_epoch_attesting_gwei: self.previous_epoch_attesters,
|
previous_epoch_attesting_gwei: self.previous_epoch_attesters(),
|
||||||
previous_epoch_target_attesting_gwei: self.previous_epoch_target_attesters,
|
previous_epoch_target_attesting_gwei: self.previous_epoch_target_attesters(),
|
||||||
previous_epoch_head_attesting_gwei: self.previous_epoch_head_attesters,
|
previous_epoch_head_attesting_gwei: self.previous_epoch_head_attesters(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,9 @@ pub fn route<T: BeaconChainTypes>(
|
|||||||
(&Method::GET, "/beacon/genesis_time") => {
|
(&Method::GET, "/beacon/genesis_time") => {
|
||||||
into_boxfut(beacon::get_genesis_time::<T>(req, beacon_chain))
|
into_boxfut(beacon::get_genesis_time::<T>(req, beacon_chain))
|
||||||
}
|
}
|
||||||
|
(&Method::GET, "/beacon/genesis_validators_root") => {
|
||||||
|
into_boxfut(beacon::get_genesis_validators_root::<T>(req, beacon_chain))
|
||||||
|
}
|
||||||
(&Method::GET, "/beacon/validators") => {
|
(&Method::GET, "/beacon/validators") => {
|
||||||
into_boxfut(beacon::get_validators::<T>(req, beacon_chain))
|
into_boxfut(beacon::get_validators::<T>(req, beacon_chain))
|
||||||
}
|
}
|
||||||
|
@ -47,17 +47,15 @@ fn get_randao_reveal<T: BeaconChainTypes>(
|
|||||||
slot: Slot,
|
slot: Slot,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Signature {
|
) -> Signature {
|
||||||
let fork = beacon_chain
|
let head = beacon_chain.head().expect("should get head");
|
||||||
.head()
|
let fork = head.beacon_state.fork;
|
||||||
.expect("should get head")
|
let genesis_validators_root = head.beacon_state.genesis_validators_root;
|
||||||
.beacon_state
|
|
||||||
.fork;
|
|
||||||
let proposer_index = beacon_chain
|
let proposer_index = beacon_chain
|
||||||
.block_proposer(slot)
|
.block_proposer(slot)
|
||||||
.expect("should get proposer index");
|
.expect("should get proposer index");
|
||||||
let keypair = generate_deterministic_keypair(proposer_index);
|
let keypair = generate_deterministic_keypair(proposer_index);
|
||||||
let epoch = slot.epoch(E::slots_per_epoch());
|
let epoch = slot.epoch(E::slots_per_epoch());
|
||||||
let domain = spec.get_domain(epoch, Domain::Randao, &fork);
|
let domain = spec.get_domain(epoch, Domain::Randao, &fork, genesis_validators_root);
|
||||||
let message = epoch.signing_root(domain);
|
let message = epoch.signing_root(domain);
|
||||||
Signature::new(message.as_bytes(), &keypair.sk)
|
Signature::new(message.as_bytes(), &keypair.sk)
|
||||||
}
|
}
|
||||||
@ -68,16 +66,14 @@ fn sign_block<T: BeaconChainTypes>(
|
|||||||
block: BeaconBlock<T::EthSpec>,
|
block: BeaconBlock<T::EthSpec>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> SignedBeaconBlock<T::EthSpec> {
|
) -> SignedBeaconBlock<T::EthSpec> {
|
||||||
let fork = beacon_chain
|
let head = beacon_chain.head().expect("should get head");
|
||||||
.head()
|
let fork = head.beacon_state.fork;
|
||||||
.expect("should get head")
|
let genesis_validators_root = head.beacon_state.genesis_validators_root;
|
||||||
.beacon_state
|
|
||||||
.fork;
|
|
||||||
let proposer_index = beacon_chain
|
let proposer_index = beacon_chain
|
||||||
.block_proposer(block.slot)
|
.block_proposer(block.slot)
|
||||||
.expect("should get proposer index");
|
.expect("should get proposer index");
|
||||||
let keypair = generate_deterministic_keypair(proposer_index);
|
let keypair = generate_deterministic_keypair(proposer_index);
|
||||||
block.sign(&keypair.sk, &fork, spec)
|
block.sign(&keypair.sk, &fork, genesis_validators_root, spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -156,6 +152,7 @@ fn validator_produce_attestation() {
|
|||||||
.attestation_committee_position
|
.attestation_committee_position
|
||||||
.expect("should have committee position"),
|
.expect("should have committee position"),
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
)
|
)
|
||||||
.expect("should sign attestation");
|
.expect("should sign attestation");
|
||||||
@ -564,6 +561,31 @@ fn genesis_time() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn genesis_validators_root() {
|
||||||
|
let mut env = build_env();
|
||||||
|
|
||||||
|
let node = build_node(&mut env, testing_client_config());
|
||||||
|
let remote_node = node.remote_node().expect("should produce remote node");
|
||||||
|
|
||||||
|
let genesis_validators_root = env
|
||||||
|
.runtime()
|
||||||
|
.block_on(remote_node.http.beacon().get_genesis_validators_root())
|
||||||
|
.expect("should fetch genesis time from http api");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
node.client
|
||||||
|
.beacon_chain()
|
||||||
|
.expect("should have beacon chain")
|
||||||
|
.head()
|
||||||
|
.expect("should get head")
|
||||||
|
.beacon_state
|
||||||
|
.genesis_validators_root,
|
||||||
|
genesis_validators_root,
|
||||||
|
"should match genesis time from head state"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fork() {
|
fn fork() {
|
||||||
let mut env = build_env();
|
let mut env = build_env();
|
||||||
@ -903,6 +925,7 @@ fn proposer_slashing() {
|
|||||||
proposer_index as u64,
|
proposer_index as u64,
|
||||||
&key,
|
&key,
|
||||||
fork,
|
fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -927,6 +950,7 @@ fn proposer_slashing() {
|
|||||||
proposer_index as u64,
|
proposer_index as u64,
|
||||||
&key,
|
&key,
|
||||||
fork,
|
fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
invalid_proposer_slashing.signed_header_2 = invalid_proposer_slashing.signed_header_1.clone();
|
invalid_proposer_slashing.signed_header_2 = invalid_proposer_slashing.signed_header_1.clone();
|
||||||
@ -981,6 +1005,7 @@ fn attester_slashing() {
|
|||||||
&validator_indices[..],
|
&validator_indices[..],
|
||||||
&secret_keys[..],
|
&secret_keys[..],
|
||||||
fork,
|
fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1006,6 +1031,7 @@ fn attester_slashing() {
|
|||||||
&validator_indices[..],
|
&validator_indices[..],
|
||||||
&secret_keys[..],
|
&secret_keys[..],
|
||||||
fork,
|
fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
invalid_attester_slashing.attestation_2 = invalid_attester_slashing.attestation_1.clone();
|
invalid_attester_slashing.attestation_2 = invalid_attester_slashing.attestation_1.clone();
|
||||||
|
@ -11,7 +11,7 @@ use types::*;
|
|||||||
///
|
///
|
||||||
/// Utilises lazy-loading from separate storage for its vector fields.
|
/// Utilises lazy-loading from separate storage for its vector fields.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Encode, Decode)]
|
#[derive(Debug, PartialEq, Clone, Encode, Decode)]
|
||||||
pub struct PartialBeaconState<T>
|
pub struct PartialBeaconState<T>
|
||||||
where
|
where
|
||||||
@ -19,6 +19,7 @@ where
|
|||||||
{
|
{
|
||||||
// Versioning
|
// Versioning
|
||||||
pub genesis_time: u64,
|
pub genesis_time: u64,
|
||||||
|
pub genesis_validators_root: Hash256,
|
||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
pub fork: Fork,
|
pub fork: Fork,
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ impl<T: EthSpec> PartialBeaconState<T> {
|
|||||||
// TODO: could use references/Cow for fields to avoid cloning
|
// TODO: could use references/Cow for fields to avoid cloning
|
||||||
PartialBeaconState {
|
PartialBeaconState {
|
||||||
genesis_time: s.genesis_time,
|
genesis_time: s.genesis_time,
|
||||||
|
genesis_validators_root: s.genesis_validators_root,
|
||||||
slot: s.slot,
|
slot: s.slot,
|
||||||
fork: s.fork.clone(),
|
fork: s.fork.clone(),
|
||||||
|
|
||||||
@ -181,6 +183,7 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {
|
|||||||
|
|
||||||
Ok(BeaconState {
|
Ok(BeaconState {
|
||||||
genesis_time: self.genesis_time,
|
genesis_time: self.genesis_time,
|
||||||
|
genesis_validators_root: self.genesis_validators_root,
|
||||||
slot: self.slot,
|
slot: self.slot,
|
||||||
fork: self.fork,
|
fork: self.fork,
|
||||||
|
|
||||||
|
@ -166,6 +166,7 @@ Returns an object containing a single [`SignedBeaconBlock`](https://github.com/e
|
|||||||
"beacon_block": {
|
"beacon_block": {
|
||||||
"message": {
|
"message": {
|
||||||
"slot": 0,
|
"slot": 0,
|
||||||
|
"proposer_index": 14,
|
||||||
"parent_root": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parent_root": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"state_root": "0xf15690b6be4ed42ea1ee0741eb4bfd4619d37be8229b84b4ddd480fb028dcc8f",
|
"state_root": "0xf15690b6be4ed42ea1ee0741eb4bfd4619d37be8229b84b4ddd480fb028dcc8f",
|
||||||
"body": {
|
"body": {
|
||||||
@ -444,7 +445,7 @@ canonical chain.
|
|||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
Returns an object containing a single
|
Returns an object containing a single
|
||||||
[`BeaconState`](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#beaconstate)
|
[`BeaconState`](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#beaconstate)
|
||||||
and its tree hash root.
|
and its tree hash root.
|
||||||
|
|
||||||
### Example Response
|
### Example Response
|
||||||
@ -454,6 +455,7 @@ and its tree hash root.
|
|||||||
"root": "0x528e54ca5d4c957729a73f40fc513ae312e054c7295775c4a2b21f423416a72b",
|
"root": "0x528e54ca5d4c957729a73f40fc513ae312e054c7295775c4a2b21f423416a72b",
|
||||||
"beacon_state": {
|
"beacon_state": {
|
||||||
"genesis_time": 1575652800,
|
"genesis_time": 1575652800,
|
||||||
|
"genesis_validators_root": "0xa8a9226edee1b2627fb4117d7dea4996e64dec2998f37f6e824f74f2ce39a538",
|
||||||
"slot": 18478
|
"slot": 18478
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -505,7 +507,7 @@ Typical Responses | 200
|
|||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
Returns an object containing the genesis
|
Returns an object containing the genesis
|
||||||
[`BeaconState`](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#beaconstate).
|
[`BeaconState`](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#beaconstate).
|
||||||
|
|
||||||
### Example Response
|
### Example Response
|
||||||
|
|
||||||
@ -565,7 +567,7 @@ Typical Responses | 200
|
|||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
Returns an object containing the [`Fork`](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#fork) of the current head.
|
Returns an object containing the [`Fork`](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#fork) of the current head.
|
||||||
|
|
||||||
### Example Response
|
### Example Response
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use int_to_bytes::int_to_bytes8;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use ssz::ssz_encode;
|
use ssz::ssz_encode;
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
use types::{AttestationData, ChainSpec, Domain, Epoch, Fork};
|
use types::{AttestationData, ChainSpec, Domain, Epoch, Fork, Hash256};
|
||||||
|
|
||||||
/// Serialized `AttestationData` augmented with a domain to encode the fork info.
|
/// Serialized `AttestationData` augmented with a domain to encode the fork info.
|
||||||
#[derive(
|
#[derive(
|
||||||
@ -13,21 +12,34 @@ pub struct AttestationId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Number of domain bytes that the end of an attestation ID is padded with.
|
/// Number of domain bytes that the end of an attestation ID is padded with.
|
||||||
const DOMAIN_BYTES_LEN: usize = 8;
|
const DOMAIN_BYTES_LEN: usize = std::mem::size_of::<Hash256>();
|
||||||
|
|
||||||
impl AttestationId {
|
impl AttestationId {
|
||||||
pub fn from_data(attestation: &AttestationData, fork: &Fork, spec: &ChainSpec) -> Self {
|
pub fn from_data(
|
||||||
|
attestation: &AttestationData,
|
||||||
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Self {
|
||||||
let mut bytes = ssz_encode(attestation);
|
let mut bytes = ssz_encode(attestation);
|
||||||
let epoch = attestation.target.epoch;
|
let epoch = attestation.target.epoch;
|
||||||
bytes.extend_from_slice(&AttestationId::compute_domain_bytes(epoch, fork, spec));
|
bytes.extend_from_slice(
|
||||||
|
AttestationId::compute_domain_bytes(epoch, fork, genesis_validators_root, spec)
|
||||||
|
.as_bytes(),
|
||||||
|
);
|
||||||
AttestationId { v: bytes }
|
AttestationId { v: bytes }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_domain_bytes(epoch: Epoch, fork: &Fork, spec: &ChainSpec) -> Vec<u8> {
|
pub fn compute_domain_bytes(
|
||||||
int_to_bytes8(spec.get_domain(epoch, Domain::BeaconAttester, fork))
|
epoch: Epoch,
|
||||||
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Hash256 {
|
||||||
|
spec.get_domain(epoch, Domain::BeaconAttester, fork, genesis_validators_root)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn domain_bytes_match(&self, domain_bytes: &[u8]) -> bool {
|
pub fn domain_bytes_match(&self, domain_bytes: &Hash256) -> bool {
|
||||||
&self.v[self.v.len() - DOMAIN_BYTES_LEN..] == domain_bytes
|
&self.v[self.v.len() - DOMAIN_BYTES_LEN..] == domain_bytes.as_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ use std::collections::{hash_map, HashMap, HashSet};
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use types::{
|
use types::{
|
||||||
typenum::Unsigned, Attestation, AttesterSlashing, BeaconState, BeaconStateError, ChainSpec,
|
typenum::Unsigned, Attestation, AttesterSlashing, BeaconState, BeaconStateError, ChainSpec,
|
||||||
EthSpec, Fork, ProposerSlashing, RelativeEpoch, SignedVoluntaryExit, Validator,
|
EthSpec, Fork, Hash256, ProposerSlashing, RelativeEpoch, SignedVoluntaryExit, Validator,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
@ -58,9 +58,10 @@ impl<T: EthSpec> OperationPool<T> {
|
|||||||
&self,
|
&self,
|
||||||
attestation: Attestation<T>,
|
attestation: Attestation<T>,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), AttestationValidationError> {
|
) -> Result<(), AttestationValidationError> {
|
||||||
let id = AttestationId::from_data(&attestation.data, fork, spec);
|
let id = AttestationId::from_data(&attestation.data, fork, genesis_validators_root, spec);
|
||||||
|
|
||||||
// Take a write lock on the attestations map.
|
// Take a write lock on the attestations map.
|
||||||
let mut attestations = self.attestations.write();
|
let mut attestations = self.attestations.write();
|
||||||
@ -106,9 +107,18 @@ impl<T: EthSpec> OperationPool<T> {
|
|||||||
// Attestations for the current fork, which may be from the current or previous epoch.
|
// Attestations for the current fork, which may be from the current or previous epoch.
|
||||||
let prev_epoch = state.previous_epoch();
|
let prev_epoch = state.previous_epoch();
|
||||||
let current_epoch = state.current_epoch();
|
let current_epoch = state.current_epoch();
|
||||||
let prev_domain_bytes = AttestationId::compute_domain_bytes(prev_epoch, &state.fork, spec);
|
let prev_domain_bytes = AttestationId::compute_domain_bytes(
|
||||||
let curr_domain_bytes =
|
prev_epoch,
|
||||||
AttestationId::compute_domain_bytes(current_epoch, &state.fork, spec);
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
let curr_domain_bytes = AttestationId::compute_domain_bytes(
|
||||||
|
current_epoch,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
let reader = self.attestations.read();
|
let reader = self.attestations.read();
|
||||||
let active_indices = state
|
let active_indices = state
|
||||||
.get_cached_active_validator_indices(RelativeEpoch::Current)
|
.get_cached_active_validator_indices(RelativeEpoch::Current)
|
||||||
@ -168,7 +178,7 @@ impl<T: EthSpec> OperationPool<T> {
|
|||||||
verify_proposer_slashing(&slashing, state, VerifySignatures::True, spec)?;
|
verify_proposer_slashing(&slashing, state, VerifySignatures::True, spec)?;
|
||||||
self.proposer_slashings
|
self.proposer_slashings
|
||||||
.write()
|
.write()
|
||||||
.insert(slashing.proposer_index, slashing);
|
.insert(slashing.signed_header_1.message.proposer_index, slashing);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,8 +191,18 @@ impl<T: EthSpec> OperationPool<T> {
|
|||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> (AttestationId, AttestationId) {
|
) -> (AttestationId, AttestationId) {
|
||||||
(
|
(
|
||||||
AttestationId::from_data(&slashing.attestation_1.data, &state.fork, spec),
|
AttestationId::from_data(
|
||||||
AttestationId::from_data(&slashing.attestation_2.data, &state.fork, spec),
|
&slashing.attestation_1.data,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
|
AttestationId::from_data(
|
||||||
|
&slashing.attestation_2.data,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +234,7 @@ impl<T: EthSpec> OperationPool<T> {
|
|||||||
|slashing| {
|
|slashing| {
|
||||||
state
|
state
|
||||||
.validators
|
.validators
|
||||||
.get(slashing.proposer_index as usize)
|
.get(slashing.signed_header_1.message.proposer_index as usize)
|
||||||
.map_or(false, |validator| !validator.slashed)
|
.map_or(false, |validator| !validator.slashed)
|
||||||
},
|
},
|
||||||
T::MaxProposerSlashings::to_usize(),
|
T::MaxProposerSlashings::to_usize(),
|
||||||
@ -224,7 +244,7 @@ impl<T: EthSpec> OperationPool<T> {
|
|||||||
// slashings.
|
// slashings.
|
||||||
let mut to_be_slashed = proposer_slashings
|
let mut to_be_slashed = proposer_slashings
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.proposer_index)
|
.map(|s| s.signed_header_1.message.proposer_index)
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
let epoch = state.current_epoch();
|
let epoch = state.current_epoch();
|
||||||
@ -427,6 +447,7 @@ mod release_tests {
|
|||||||
signers,
|
signers,
|
||||||
&committee_keys,
|
&committee_keys,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
extra_signer.map(|c_idx| {
|
extra_signer.map(|c_idx| {
|
||||||
@ -436,6 +457,7 @@ mod release_tests {
|
|||||||
&[validator_index],
|
&[validator_index],
|
||||||
&[&keypairs[validator_index].sk],
|
&[&keypairs[validator_index].sk],
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -548,7 +570,9 @@ mod release_tests {
|
|||||||
spec,
|
spec,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
op_pool.insert_attestation(att, &state.fork, spec).unwrap();
|
op_pool
|
||||||
|
.insert_attestation(att, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,9 +641,16 @@ mod release_tests {
|
|||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
op_pool
|
op_pool
|
||||||
.insert_attestation(att.clone(), &state.fork, spec)
|
.insert_attestation(
|
||||||
|
att.clone(),
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
op_pool
|
||||||
|
.insert_attestation(att, &state.fork, state.genesis_validators_root, spec)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
op_pool.insert_attestation(att, &state.fork, spec).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(op_pool.num_attestations(), committees.len());
|
assert_eq!(op_pool.num_attestations(), committees.len());
|
||||||
@ -656,7 +687,9 @@ mod release_tests {
|
|||||||
spec,
|
spec,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
op_pool.insert_attestation(att, &state.fork, spec).unwrap();
|
op_pool
|
||||||
|
.insert_attestation(att, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,7 +737,9 @@ mod release_tests {
|
|||||||
spec,
|
spec,
|
||||||
if i == 0 { None } else { Some(0) },
|
if i == 0 { None } else { Some(0) },
|
||||||
);
|
);
|
||||||
op_pool.insert_attestation(att, &state.fork, spec).unwrap();
|
op_pool
|
||||||
|
.insert_attestation(att, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -777,7 +812,9 @@ mod release_tests {
|
|||||||
spec,
|
spec,
|
||||||
if i == 0 { None } else { Some(0) },
|
if i == 0 { None } else { Some(0) },
|
||||||
);
|
);
|
||||||
op_pool.insert_attestation(att, &state.fork, spec).unwrap();
|
op_pool
|
||||||
|
.insert_attestation(att, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ impl<T: EthSpec> PersistedOperationPool<T> {
|
|||||||
let proposer_slashings = RwLock::new(
|
let proposer_slashings = RwLock::new(
|
||||||
self.proposer_slashings
|
self.proposer_slashings
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|slashing| (slashing.proposer_index, slashing))
|
.map(|slashing| (slashing.signed_header_1.message.proposer_index, slashing))
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
let voluntary_exits = RwLock::new(
|
let voluntary_exits = RwLock::new(
|
||||||
|
@ -3,7 +3,7 @@ use types::*;
|
|||||||
|
|
||||||
/// Returns validator indices which participated in the attestation, sorted by increasing index.
|
/// Returns validator indices which participated in the attestation, sorted by increasing index.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_attesting_indices<T: EthSpec>(
|
pub fn get_attesting_indices<T: EthSpec>(
|
||||||
committee: &[usize],
|
committee: &[usize],
|
||||||
bitlist: &BitList<T::MaxValidatorsPerCommittee>,
|
bitlist: &BitList<T::MaxValidatorsPerCommittee>,
|
||||||
|
@ -3,7 +3,7 @@ use types::*;
|
|||||||
|
|
||||||
/// Returns the base reward for some validator.
|
/// Returns the base reward for some validator.
|
||||||
///
|
///
|
||||||
/// Spec v0.9.1
|
/// Spec v0.11.1
|
||||||
pub fn get_base_reward<T: EthSpec>(
|
pub fn get_base_reward<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -6,7 +6,7 @@ type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;
|
|||||||
|
|
||||||
/// Convert `attestation` to (almost) indexed-verifiable form.
|
/// Convert `attestation` to (almost) indexed-verifiable form.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_indexed_attestation<T: EthSpec>(
|
pub fn get_indexed_attestation<T: EthSpec>(
|
||||||
committee: &[usize],
|
committee: &[usize],
|
||||||
attestation: &Attestation<T>,
|
attestation: &Attestation<T>,
|
||||||
|
@ -3,7 +3,7 @@ use types::{BeaconStateError as Error, *};
|
|||||||
|
|
||||||
/// Initiate the exit of the validator of the given `index`.
|
/// Initiate the exit of the validator of the given `index`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn initiate_validator_exit<T: EthSpec>(
|
pub fn initiate_validator_exit<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
index: usize,
|
index: usize,
|
||||||
|
@ -4,7 +4,7 @@ use types::{BeaconStateError as Error, *};
|
|||||||
|
|
||||||
/// Slash the validator with index ``index``.
|
/// Slash the validator with index ``index``.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn slash_validator<T: EthSpec>(
|
pub fn slash_validator<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
slashed_index: usize,
|
slashed_index: usize,
|
||||||
|
@ -6,7 +6,7 @@ use types::*;
|
|||||||
|
|
||||||
/// Initialize a `BeaconState` from genesis data.
|
/// Initialize a `BeaconState` from genesis data.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
// TODO: this is quite inefficient and we probably want to rethink how we do this
|
// TODO: this is quite inefficient and we probably want to rethink how we do this
|
||||||
pub fn initialize_beacon_state_from_eth1<T: EthSpec>(
|
pub fn initialize_beacon_state_from_eth1<T: EthSpec>(
|
||||||
eth1_block_hash: Hash256,
|
eth1_block_hash: Hash256,
|
||||||
@ -42,12 +42,15 @@ pub fn initialize_beacon_state_from_eth1<T: EthSpec>(
|
|||||||
// Now that we have our validators, initialize the caches (including the committees)
|
// Now that we have our validators, initialize the caches (including the committees)
|
||||||
state.build_all_caches(spec)?;
|
state.build_all_caches(spec)?;
|
||||||
|
|
||||||
|
// Set genesis validators root for domain separation and chain versioning
|
||||||
|
state.genesis_validators_root = state.update_validators_tree_hash_cache()?;
|
||||||
|
|
||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether a candidate genesis state is suitable for starting the chain.
|
/// Determine whether a candidate genesis state is suitable for starting the chain.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn is_valid_genesis_state<T: EthSpec>(state: &BeaconState<T>, spec: &ChainSpec) -> bool {
|
pub fn is_valid_genesis_state<T: EthSpec>(state: &BeaconState<T>, spec: &ChainSpec) -> bool {
|
||||||
state.genesis_time >= spec.min_genesis_time
|
state.genesis_time >= spec.min_genesis_time
|
||||||
&& state.get_active_validator_indices(T::genesis_epoch()).len() as u64
|
&& state.get_active_validator_indices(T::genesis_epoch()).len() as u64
|
||||||
@ -56,7 +59,7 @@ pub fn is_valid_genesis_state<T: EthSpec>(state: &BeaconState<T>, spec: &ChainSp
|
|||||||
|
|
||||||
/// Activate genesis validators, if their balance is acceptable.
|
/// Activate genesis validators, if their balance is acceptable.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_activations<T: EthSpec>(state: &mut BeaconState<T>, spec: &ChainSpec) {
|
pub fn process_activations<T: EthSpec>(state: &mut BeaconState<T>, spec: &ChainSpec) {
|
||||||
for (index, validator) in state.validators.iter_mut().enumerate() {
|
for (index, validator) in state.validators.iter_mut().enumerate() {
|
||||||
let balance = state.balances[index];
|
let balance = state.balances[index];
|
||||||
|
@ -70,7 +70,7 @@ impl VerifySignatures {
|
|||||||
/// tree hash root of the block, NOT the signing root of the block. This function takes
|
/// tree hash root of the block, NOT the signing root of the block. This function takes
|
||||||
/// care of mixing in the domain.
|
/// care of mixing in the domain.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn per_block_processing<T: EthSpec>(
|
pub fn per_block_processing<T: EthSpec>(
|
||||||
mut state: &mut BeaconState<T>,
|
mut state: &mut BeaconState<T>,
|
||||||
signed_block: &SignedBeaconBlock<T>,
|
signed_block: &SignedBeaconBlock<T>,
|
||||||
@ -136,14 +136,26 @@ pub fn per_block_processing<T: EthSpec>(
|
|||||||
|
|
||||||
/// Processes the block header.
|
/// Processes the block header.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_block_header<T: EthSpec>(
|
pub fn process_block_header<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
block: &BeaconBlock<T>,
|
block: &BeaconBlock<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockOperationError<HeaderInvalid>> {
|
) -> Result<(), BlockOperationError<HeaderInvalid>> {
|
||||||
|
// Verify that the slots match
|
||||||
verify!(block.slot == state.slot, HeaderInvalid::StateSlotMismatch);
|
verify!(block.slot == state.slot, HeaderInvalid::StateSlotMismatch);
|
||||||
|
|
||||||
|
// Verify that proposer index is the correct index
|
||||||
|
let proposer_index = block.proposer_index as usize;
|
||||||
|
let state_proposer_index = state.get_beacon_proposer_index(block.slot, spec)?;
|
||||||
|
verify!(
|
||||||
|
proposer_index == state_proposer_index,
|
||||||
|
HeaderInvalid::ProposerIndexMismatch {
|
||||||
|
block_proposer_index: proposer_index,
|
||||||
|
state_proposer_index,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let expected_previous_block_root = state.latest_block_header.tree_hash_root();
|
let expected_previous_block_root = state.latest_block_header.tree_hash_root();
|
||||||
verify!(
|
verify!(
|
||||||
block.parent_root == expected_previous_block_root,
|
block.parent_root == expected_previous_block_root,
|
||||||
@ -156,11 +168,10 @@ pub fn process_block_header<T: EthSpec>(
|
|||||||
state.latest_block_header = block.temporary_block_header();
|
state.latest_block_header = block.temporary_block_header();
|
||||||
|
|
||||||
// Verify proposer is not slashed
|
// Verify proposer is not slashed
|
||||||
let proposer_idx = state.get_beacon_proposer_index(block.slot, spec)?;
|
let proposer = &state.validators[proposer_index];
|
||||||
let proposer = &state.validators[proposer_idx];
|
|
||||||
verify!(
|
verify!(
|
||||||
!proposer.slashed,
|
!proposer.slashed,
|
||||||
HeaderInvalid::ProposerSlashed(proposer_idx)
|
HeaderInvalid::ProposerSlashed(proposer_index)
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -168,7 +179,7 @@ pub fn process_block_header<T: EthSpec>(
|
|||||||
|
|
||||||
/// Verifies the signature of a block.
|
/// Verifies the signature of a block.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_block_signature<T: EthSpec>(
|
pub fn verify_block_signature<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
block: &SignedBeaconBlock<T>,
|
block: &SignedBeaconBlock<T>,
|
||||||
@ -186,7 +197,7 @@ pub fn verify_block_signature<T: EthSpec>(
|
|||||||
/// Verifies the `randao_reveal` against the block's proposer pubkey and updates
|
/// Verifies the `randao_reveal` against the block's proposer pubkey and updates
|
||||||
/// `state.latest_randao_mixes`.
|
/// `state.latest_randao_mixes`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_randao<T: EthSpec>(
|
pub fn process_randao<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
block: &BeaconBlock<T>,
|
block: &BeaconBlock<T>,
|
||||||
@ -209,7 +220,7 @@ pub fn process_randao<T: EthSpec>(
|
|||||||
|
|
||||||
/// Update the `state.eth1_data_votes` based upon the `eth1_data` provided.
|
/// Update the `state.eth1_data_votes` based upon the `eth1_data` provided.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_eth1_data<T: EthSpec>(
|
pub fn process_eth1_data<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
eth1_data: &Eth1Data,
|
eth1_data: &Eth1Data,
|
||||||
@ -226,7 +237,7 @@ pub fn process_eth1_data<T: EthSpec>(
|
|||||||
/// Returns `Some(eth1_data)` if adding the given `eth1_data` to `state.eth1_data_votes` would
|
/// Returns `Some(eth1_data)` if adding the given `eth1_data` to `state.eth1_data_votes` would
|
||||||
/// result in a change to `state.eth1_data`.
|
/// result in a change to `state.eth1_data`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_new_eth1_data<T: EthSpec>(
|
pub fn get_new_eth1_data<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
eth1_data: &Eth1Data,
|
eth1_data: &Eth1Data,
|
||||||
@ -250,7 +261,7 @@ pub fn get_new_eth1_data<T: EthSpec>(
|
|||||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||||
/// an `Err` describing the invalid object or cause of failure.
|
/// an `Err` describing the invalid object or cause of failure.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_proposer_slashings<T: EthSpec>(
|
pub fn process_proposer_slashings<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
proposer_slashings: &[ProposerSlashing],
|
proposer_slashings: &[ProposerSlashing],
|
||||||
@ -268,7 +279,12 @@ pub fn process_proposer_slashings<T: EthSpec>(
|
|||||||
|
|
||||||
// Update the state.
|
// Update the state.
|
||||||
for proposer_slashing in proposer_slashings {
|
for proposer_slashing in proposer_slashings {
|
||||||
slash_validator(state, proposer_slashing.proposer_index as usize, None, spec)?;
|
slash_validator(
|
||||||
|
state,
|
||||||
|
proposer_slashing.signed_header_1.message.proposer_index as usize,
|
||||||
|
None,
|
||||||
|
spec,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -279,7 +295,7 @@ pub fn process_proposer_slashings<T: EthSpec>(
|
|||||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||||
/// an `Err` describing the invalid object or cause of failure.
|
/// an `Err` describing the invalid object or cause of failure.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_attester_slashings<T: EthSpec>(
|
pub fn process_attester_slashings<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
attester_slashings: &[AttesterSlashing<T>],
|
attester_slashings: &[AttesterSlashing<T>],
|
||||||
@ -333,7 +349,7 @@ pub fn process_attester_slashings<T: EthSpec>(
|
|||||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||||
/// an `Err` describing the invalid object or cause of failure.
|
/// an `Err` describing the invalid object or cause of failure.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_attestations<T: EthSpec>(
|
pub fn process_attestations<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
attestations: &[Attestation<T>],
|
attestations: &[Attestation<T>],
|
||||||
@ -379,7 +395,7 @@ pub fn process_attestations<T: EthSpec>(
|
|||||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||||
/// an `Err` describing the invalid object or cause of failure.
|
/// an `Err` describing the invalid object or cause of failure.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_deposits<T: EthSpec>(
|
pub fn process_deposits<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
deposits: &[Deposit],
|
deposits: &[Deposit],
|
||||||
@ -416,7 +432,7 @@ pub fn process_deposits<T: EthSpec>(
|
|||||||
|
|
||||||
/// Process a single deposit, optionally verifying its merkle proof.
|
/// Process a single deposit, optionally verifying its merkle proof.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_deposit<T: EthSpec>(
|
pub fn process_deposit<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
deposit: &Deposit,
|
deposit: &Deposit,
|
||||||
@ -482,7 +498,7 @@ pub fn process_deposit<T: EthSpec>(
|
|||||||
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
/// Returns `Ok(())` if the validation and state updates completed successfully, otherwise returns
|
||||||
/// an `Err` describing the invalid object or cause of failure.
|
/// an `Err` describing the invalid object or cause of failure.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_exits<T: EthSpec>(
|
pub fn process_exits<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
voluntary_exits: &[SignedVoluntaryExit],
|
voluntary_exits: &[SignedVoluntaryExit],
|
||||||
|
@ -56,9 +56,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||||
let keypair = &keypairs[proposer_index];
|
let keypair = &keypairs[proposer_index];
|
||||||
|
|
||||||
|
builder.set_proposer_index(proposer_index as u64);
|
||||||
|
|
||||||
match randao_sk {
|
match randao_sk {
|
||||||
Some(sk) => builder.set_randao_reveal(&sk, &state.fork, spec),
|
Some(sk) => {
|
||||||
None => builder.set_randao_reveal(&keypair.sk, &state.fork, spec),
|
builder.set_randao_reveal(&sk, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
}
|
||||||
|
None => builder.set_randao_reveal(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.block_builder.insert_deposits(
|
self.block_builder.insert_deposits(
|
||||||
@ -70,7 +79,12 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
let block = self.block_builder.build(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
(block, state)
|
(block, state)
|
||||||
}
|
}
|
||||||
@ -96,9 +110,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||||
let keypair = &keypairs[proposer_index];
|
let keypair = &keypairs[proposer_index];
|
||||||
|
|
||||||
|
builder.set_proposer_index(proposer_index as u64);
|
||||||
|
|
||||||
match randao_sk {
|
match randao_sk {
|
||||||
Some(sk) => builder.set_randao_reveal(&sk, &state.fork, spec),
|
Some(sk) => {
|
||||||
None => builder.set_randao_reveal(&keypair.sk, &state.fork, spec),
|
builder.set_randao_reveal(&sk, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
}
|
||||||
|
None => builder.set_randao_reveal(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
match test_task {
|
match test_task {
|
||||||
ExitTestTask::AlreadyInitiated => {
|
ExitTestTask::AlreadyInitiated => {
|
||||||
@ -125,7 +148,12 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
let block = self.block_builder.build(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
(block, state)
|
(block, state)
|
||||||
}
|
}
|
||||||
@ -151,9 +179,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||||
let keypair = &keypairs[proposer_index];
|
let keypair = &keypairs[proposer_index];
|
||||||
|
|
||||||
|
builder.set_proposer_index(proposer_index as u64);
|
||||||
|
|
||||||
match randao_sk {
|
match randao_sk {
|
||||||
Some(sk) => builder.set_randao_reveal(&sk, &state.fork, spec),
|
Some(sk) => {
|
||||||
None => builder.set_randao_reveal(&keypair.sk, &state.fork, spec),
|
builder.set_randao_reveal(&sk, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
}
|
||||||
|
None => builder.set_randao_reveal(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
let all_secret_keys: Vec<&SecretKey> = keypairs.iter().map(|keypair| &keypair.sk).collect();
|
let all_secret_keys: Vec<&SecretKey> = keypairs.iter().map(|keypair| &keypair.sk).collect();
|
||||||
@ -166,7 +203,12 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
spec,
|
spec,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
let block = self.block_builder.build(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
(block, state)
|
(block, state)
|
||||||
}
|
}
|
||||||
@ -192,9 +234,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||||
let keypair = &keypairs[proposer_index];
|
let keypair = &keypairs[proposer_index];
|
||||||
|
|
||||||
|
builder.set_proposer_index(proposer_index as u64);
|
||||||
|
|
||||||
match randao_sk {
|
match randao_sk {
|
||||||
Some(sk) => builder.set_randao_reveal(&sk, &state.fork, spec),
|
Some(sk) => {
|
||||||
None => builder.set_randao_reveal(&keypair.sk, &state.fork, spec),
|
builder.set_randao_reveal(&sk, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
}
|
||||||
|
None => builder.set_randao_reveal(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut validator_indices = vec![];
|
let mut validator_indices = vec![];
|
||||||
@ -210,10 +261,16 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
&validator_indices,
|
&validator_indices,
|
||||||
&secret_keys,
|
&secret_keys,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
let block = self.block_builder.build(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
(block, state)
|
(block, state)
|
||||||
}
|
}
|
||||||
@ -239,9 +296,18 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||||
let keypair = &keypairs[proposer_index];
|
let keypair = &keypairs[proposer_index];
|
||||||
|
|
||||||
|
builder.set_proposer_index(proposer_index as u64);
|
||||||
|
|
||||||
match randao_sk {
|
match randao_sk {
|
||||||
Some(sk) => builder.set_randao_reveal(&sk, &state.fork, spec),
|
Some(sk) => {
|
||||||
None => builder.set_randao_reveal(&keypair.sk, &state.fork, spec),
|
builder.set_randao_reveal(&sk, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
}
|
||||||
|
None => builder.set_randao_reveal(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..num_proposer_slashings {
|
for i in 0..num_proposer_slashings {
|
||||||
@ -252,10 +318,16 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
validator_indices,
|
validator_indices,
|
||||||
&secret_keys,
|
&secret_keys,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
let block = self.block_builder.build(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
(block, state)
|
(block, state)
|
||||||
}
|
}
|
||||||
@ -279,12 +351,26 @@ impl<T: EthSpec> BlockProcessingBuilder<T> {
|
|||||||
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
let proposer_index = state.get_beacon_proposer_index(state.slot, spec).unwrap();
|
||||||
let keypair = &keypairs[proposer_index];
|
let keypair = &keypairs[proposer_index];
|
||||||
|
|
||||||
|
builder.set_proposer_index(proposer_index as u64);
|
||||||
|
|
||||||
match randao_sk {
|
match randao_sk {
|
||||||
Some(sk) => builder.set_randao_reveal(&sk, &state.fork, spec),
|
Some(sk) => {
|
||||||
None => builder.set_randao_reveal(&keypair.sk, &state.fork, spec),
|
builder.set_randao_reveal(&sk, &state.fork, state.genesis_validators_root, spec)
|
||||||
|
}
|
||||||
|
None => builder.set_randao_reveal(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
let block = self.block_builder.build(&keypair.sk, &state.fork, spec);
|
let block = self.block_builder.build(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
(block, state)
|
(block, state)
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,14 @@ impl<T> From<ssz_types::Error> for BlockOperationError<T> {
|
|||||||
pub enum HeaderInvalid {
|
pub enum HeaderInvalid {
|
||||||
ProposalSignatureInvalid,
|
ProposalSignatureInvalid,
|
||||||
StateSlotMismatch,
|
StateSlotMismatch,
|
||||||
ParentBlockRootMismatch { state: Hash256, block: Hash256 },
|
ProposerIndexMismatch {
|
||||||
|
block_proposer_index: usize,
|
||||||
|
state_proposer_index: usize,
|
||||||
|
},
|
||||||
|
ParentBlockRootMismatch {
|
||||||
|
state: Hash256,
|
||||||
|
block: Hash256,
|
||||||
|
},
|
||||||
ProposerSlashed(usize),
|
ProposerSlashed(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +178,10 @@ pub enum ProposerSlashingInvalid {
|
|||||||
///
|
///
|
||||||
/// (proposal_1_slot, proposal_2_slot)
|
/// (proposal_1_slot, proposal_2_slot)
|
||||||
ProposalSlotMismatch(Slot, Slot),
|
ProposalSlotMismatch(Slot, Slot),
|
||||||
|
/// The two proposals have different proposer indices.
|
||||||
|
///
|
||||||
|
/// (proposer_index_1, proposer_index_2)
|
||||||
|
ProposerIndexMismatch(u64, u64),
|
||||||
/// The proposals are identical and therefore not slashable.
|
/// The proposals are identical and therefore not slashable.
|
||||||
ProposalsIdentical,
|
ProposalsIdentical,
|
||||||
/// The specified proposer cannot be slashed because they are already slashed, or not active.
|
/// The specified proposer cannot be slashed because they are already slashed, or not active.
|
||||||
|
@ -11,7 +11,7 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
|||||||
|
|
||||||
/// Verify an `IndexedAttestation`.
|
/// Verify an `IndexedAttestation`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn is_valid_indexed_attestation<T: EthSpec>(
|
pub fn is_valid_indexed_attestation<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
indexed_attestation: &IndexedAttestation<T>,
|
indexed_attestation: &IndexedAttestation<T>,
|
||||||
|
@ -53,6 +53,7 @@ pub fn block_proposal_signature_set<'a, T: EthSpec>(
|
|||||||
block.slot.epoch(T::slots_per_epoch()),
|
block.slot.epoch(T::slots_per_epoch()),
|
||||||
Domain::BeaconProposer,
|
Domain::BeaconProposer,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = if let Some(root) = block_root {
|
let message = if let Some(root) = block_root {
|
||||||
@ -84,6 +85,7 @@ pub fn randao_signature_set<'a, T: EthSpec>(
|
|||||||
block.slot.epoch(T::slots_per_epoch()),
|
block.slot.epoch(T::slots_per_epoch()),
|
||||||
Domain::Randao,
|
Domain::Randao,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = state.current_epoch().signing_root(domain);
|
let message = state.current_epoch().signing_root(domain);
|
||||||
@ -101,7 +103,7 @@ pub fn proposer_slashing_signature_set<'a, T: EthSpec>(
|
|||||||
proposer_slashing: &'a ProposerSlashing,
|
proposer_slashing: &'a ProposerSlashing,
|
||||||
spec: &'a ChainSpec,
|
spec: &'a ChainSpec,
|
||||||
) -> Result<(SignatureSet<'a>, SignatureSet<'a>)> {
|
) -> Result<(SignatureSet<'a>, SignatureSet<'a>)> {
|
||||||
let proposer_index = proposer_slashing.proposer_index as usize;
|
let proposer_index = proposer_slashing.signed_header_1.message.proposer_index as usize;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
block_header_signature_set(
|
block_header_signature_set(
|
||||||
@ -130,6 +132,7 @@ fn block_header_signature_set<'a, T: EthSpec>(
|
|||||||
signed_header.message.slot.epoch(T::slots_per_epoch()),
|
signed_header.message.slot.epoch(T::slots_per_epoch()),
|
||||||
Domain::BeaconProposer,
|
Domain::BeaconProposer,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = signed_header
|
let message = signed_header
|
||||||
@ -162,6 +165,7 @@ pub fn indexed_attestation_signature_set<'a, 'b, T: EthSpec>(
|
|||||||
indexed_attestation.data.target.epoch,
|
indexed_attestation.data.target.epoch,
|
||||||
Domain::BeaconAttester,
|
Domain::BeaconAttester,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = indexed_attestation.data.signing_root(domain);
|
let message = indexed_attestation.data.signing_root(domain);
|
||||||
@ -177,6 +181,7 @@ pub fn indexed_attestation_signature_set_from_pubkeys<'a, 'b, T: EthSpec>(
|
|||||||
signature: &'a AggregateSignature,
|
signature: &'a AggregateSignature,
|
||||||
indexed_attestation: &'b IndexedAttestation<T>,
|
indexed_attestation: &'b IndexedAttestation<T>,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &'a ChainSpec,
|
spec: &'a ChainSpec,
|
||||||
) -> Result<SignatureSet<'a>> {
|
) -> Result<SignatureSet<'a>> {
|
||||||
let pubkeys = pubkeys
|
let pubkeys = pubkeys
|
||||||
@ -188,6 +193,7 @@ pub fn indexed_attestation_signature_set_from_pubkeys<'a, 'b, T: EthSpec>(
|
|||||||
indexed_attestation.data.target.epoch,
|
indexed_attestation.data.target.epoch,
|
||||||
Domain::BeaconAttester,
|
Domain::BeaconAttester,
|
||||||
&fork,
|
&fork,
|
||||||
|
genesis_validators_root,
|
||||||
);
|
);
|
||||||
|
|
||||||
let message = indexed_attestation.data.signing_root(domain);
|
let message = indexed_attestation.data.signing_root(domain);
|
||||||
@ -258,7 +264,12 @@ pub fn exit_signature_set<'a, T: EthSpec>(
|
|||||||
let exit = &signed_exit.message;
|
let exit = &signed_exit.message;
|
||||||
let proposer_index = exit.validator_index as usize;
|
let proposer_index = exit.validator_index as usize;
|
||||||
|
|
||||||
let domain = spec.get_domain(exit.epoch, Domain::VoluntaryExit, &state.fork);
|
let domain = spec.get_domain(
|
||||||
|
exit.epoch,
|
||||||
|
Domain::VoluntaryExit,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
);
|
||||||
|
|
||||||
let message = exit.signing_root(domain).as_bytes().to_vec();
|
let message = exit.signing_root(domain).as_bytes().to_vec();
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use types::test_utils::{
|
|||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
pub const NUM_DEPOSITS: u64 = 1;
|
pub const NUM_DEPOSITS: u64 = 1;
|
||||||
pub const VALIDATOR_COUNT: usize = 10;
|
pub const VALIDATOR_COUNT: usize = 64;
|
||||||
pub const SLOT_OFFSET: u64 = 4;
|
pub const SLOT_OFFSET: u64 = 4;
|
||||||
pub const EXIT_SLOT_OFFSET: u64 = 2048;
|
pub const EXIT_SLOT_OFFSET: u64 = 2048;
|
||||||
pub const NUM_ATTESTATIONS: u64 = 1;
|
pub const NUM_ATTESTATIONS: u64 = 1;
|
||||||
@ -93,7 +93,12 @@ fn invalid_block_signature() {
|
|||||||
|
|
||||||
// sign the block with a keypair that is not the expected proposer
|
// sign the block with a keypair that is not the expected proposer
|
||||||
let keypair = Keypair::random();
|
let keypair = Keypair::random();
|
||||||
let block = block.message.sign(&keypair.sk, &state.fork, &spec);
|
let block = block.message.sign(
|
||||||
|
&keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
&spec,
|
||||||
|
);
|
||||||
|
|
||||||
// process block with invalid block signature
|
// process block with invalid block signature
|
||||||
let result = per_block_processing(
|
let result = per_block_processing(
|
||||||
@ -630,7 +635,7 @@ fn invalid_attestation_wrong_justified_checkpoint() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn invalid_attestation_bad_indexed_attestation_bad_signature() {
|
fn invalid_attestation_bad_indexed_attestation_bad_signature() {
|
||||||
let spec = MainnetEthSpec::default_spec();
|
let spec = MainnetEthSpec::default_spec();
|
||||||
let builder = get_builder(&spec, SLOT_OFFSET, 33); // minmium number of validators required for this test
|
let builder = get_builder(&spec, SLOT_OFFSET, VALIDATOR_COUNT);
|
||||||
let test_task = AttestationTestTask::BadIndexedAttestationBadSignature;
|
let test_task = AttestationTestTask::BadIndexedAttestationBadSignature;
|
||||||
let (block, mut state) =
|
let (block, mut state) =
|
||||||
builder.build_with_n_attestations(test_task, NUM_ATTESTATIONS, None, None, &spec);
|
builder.build_with_n_attestations(test_task, NUM_ATTESTATIONS, None, None, &spec);
|
||||||
|
@ -15,7 +15,7 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
|||||||
///
|
///
|
||||||
/// Optionally verifies the aggregate signature, depending on `verify_signatures`.
|
/// Optionally verifies the aggregate signature, depending on `verify_signatures`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_attestation_for_block_inclusion<T: EthSpec>(
|
pub fn verify_attestation_for_block_inclusion<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
attestation: &Attestation<T>,
|
attestation: &Attestation<T>,
|
||||||
@ -49,7 +49,7 @@ pub fn verify_attestation_for_block_inclusion<T: EthSpec>(
|
|||||||
/// Returns a descriptive `Err` if the attestation is malformed or does not accurately reflect the
|
/// Returns a descriptive `Err` if the attestation is malformed or does not accurately reflect the
|
||||||
/// prior blocks in `state`.
|
/// prior blocks in `state`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_attestation_for_state<T: EthSpec>(
|
pub fn verify_attestation_for_state<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
attestation: &Attestation<T>,
|
attestation: &Attestation<T>,
|
||||||
@ -58,6 +58,13 @@ pub fn verify_attestation_for_state<T: EthSpec>(
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let data = &attestation.data;
|
let data = &attestation.data;
|
||||||
|
|
||||||
|
// This emptiness check is required *in addition* to the length check in `get_attesting_indices`
|
||||||
|
// because we can parse a bitfield and know its length, even if it has no bits set.
|
||||||
|
verify!(
|
||||||
|
!attestation.aggregation_bits.is_zero(),
|
||||||
|
Invalid::AggregationBitfieldIsEmpty
|
||||||
|
);
|
||||||
|
|
||||||
verify!(
|
verify!(
|
||||||
data.index < state.get_committee_count_at_slot(data.slot)?,
|
data.index < state.get_committee_count_at_slot(data.slot)?,
|
||||||
Invalid::BadCommitteeIndex
|
Invalid::BadCommitteeIndex
|
||||||
@ -76,7 +83,7 @@ pub fn verify_attestation_for_state<T: EthSpec>(
|
|||||||
|
|
||||||
/// Check target epoch and source checkpoint.
|
/// Check target epoch and source checkpoint.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn verify_casper_ffg_vote<T: EthSpec>(
|
fn verify_casper_ffg_vote<T: EthSpec>(
|
||||||
attestation: &Attestation<T>,
|
attestation: &Attestation<T>,
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
|
@ -15,7 +15,7 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
|||||||
///
|
///
|
||||||
/// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity.
|
/// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_attester_slashing<T: EthSpec>(
|
pub fn verify_attester_slashing<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
attester_slashing: &AttesterSlashing<T>,
|
attester_slashing: &AttesterSlashing<T>,
|
||||||
@ -47,7 +47,7 @@ pub fn verify_attester_slashing<T: EthSpec>(
|
|||||||
///
|
///
|
||||||
/// Returns Ok(indices) if `indices.len() > 0`.
|
/// Returns Ok(indices) if `indices.len() > 0`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_slashable_indices<T: EthSpec>(
|
pub fn get_slashable_indices<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
attester_slashing: &AttesterSlashing<T>,
|
attester_slashing: &AttesterSlashing<T>,
|
||||||
|
@ -14,7 +14,7 @@ fn error(reason: DepositInvalid) -> BlockOperationError<DepositInvalid> {
|
|||||||
|
|
||||||
/// Verify `Deposit.pubkey` signed `Deposit.signature`.
|
/// Verify `Deposit.pubkey` signed `Deposit.signature`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_deposit_signature(deposit_data: &DepositData, spec: &ChainSpec) -> Result<()> {
|
pub fn verify_deposit_signature(deposit_data: &DepositData, spec: &ChainSpec) -> Result<()> {
|
||||||
let deposit_signature_message = deposit_pubkey_signature_message(&deposit_data, spec)
|
let deposit_signature_message = deposit_pubkey_signature_message(&deposit_data, spec)
|
||||||
.ok_or_else(|| error(DepositInvalid::BadBlsBytes))?;
|
.ok_or_else(|| error(DepositInvalid::BadBlsBytes))?;
|
||||||
@ -46,7 +46,7 @@ pub fn get_existing_validator_index<T: EthSpec>(
|
|||||||
/// The deposit index is provided as a parameter so we can check proofs
|
/// The deposit index is provided as a parameter so we can check proofs
|
||||||
/// before they're due to be processed, and in parallel.
|
/// before they're due to be processed, and in parallel.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_deposit_merkle_proof<T: EthSpec>(
|
pub fn verify_deposit_merkle_proof<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
deposit: &Deposit,
|
deposit: &Deposit,
|
||||||
|
@ -13,7 +13,7 @@ fn error(reason: ExitInvalid) -> BlockOperationError<ExitInvalid> {
|
|||||||
///
|
///
|
||||||
/// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity.
|
/// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_exit<T: EthSpec>(
|
pub fn verify_exit<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
exit: &SignedVoluntaryExit,
|
exit: &SignedVoluntaryExit,
|
||||||
@ -25,7 +25,7 @@ pub fn verify_exit<T: EthSpec>(
|
|||||||
|
|
||||||
/// Like `verify_exit` but doesn't run checks which may become true in future states.
|
/// Like `verify_exit` but doesn't run checks which may become true in future states.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_exit_time_independent_only<T: EthSpec>(
|
pub fn verify_exit_time_independent_only<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
exit: &SignedVoluntaryExit,
|
exit: &SignedVoluntaryExit,
|
||||||
@ -37,7 +37,7 @@ pub fn verify_exit_time_independent_only<T: EthSpec>(
|
|||||||
|
|
||||||
/// Parametric version of `verify_exit` that skips some checks if `time_independent_only` is true.
|
/// Parametric version of `verify_exit` that skips some checks if `time_independent_only` is true.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn verify_exit_parametric<T: EthSpec>(
|
fn verify_exit_parametric<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
signed_exit: &SignedVoluntaryExit,
|
signed_exit: &SignedVoluntaryExit,
|
||||||
|
@ -14,38 +14,40 @@ fn error(reason: Invalid) -> BlockOperationError<Invalid> {
|
|||||||
///
|
///
|
||||||
/// Returns `Ok(())` if the `ProposerSlashing` is valid, otherwise indicates the reason for invalidity.
|
/// Returns `Ok(())` if the `ProposerSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn verify_proposer_slashing<T: EthSpec>(
|
pub fn verify_proposer_slashing<T: EthSpec>(
|
||||||
proposer_slashing: &ProposerSlashing,
|
proposer_slashing: &ProposerSlashing,
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
verify_signatures: VerifySignatures,
|
verify_signatures: VerifySignatures,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let proposer = state
|
let header_1 = &proposer_slashing.signed_header_1.message;
|
||||||
.validators
|
let header_2 = &proposer_slashing.signed_header_2.message;
|
||||||
.get(proposer_slashing.proposer_index as usize)
|
|
||||||
.ok_or_else(|| error(Invalid::ProposerUnknown(proposer_slashing.proposer_index)))?;
|
|
||||||
|
|
||||||
// Verify slots match
|
// Verify slots match
|
||||||
verify!(
|
verify!(
|
||||||
proposer_slashing.signed_header_1.message.slot
|
header_1.slot == header_2.slot,
|
||||||
== proposer_slashing.signed_header_2.message.slot,
|
Invalid::ProposalSlotMismatch(header_1.slot, header_2.slot)
|
||||||
Invalid::ProposalSlotMismatch(
|
);
|
||||||
proposer_slashing.signed_header_1.message.slot,
|
|
||||||
proposer_slashing.signed_header_2.message.slot
|
// Verify header proposer indices match
|
||||||
)
|
verify!(
|
||||||
|
header_1.proposer_index == header_2.proposer_index,
|
||||||
|
Invalid::ProposerIndexMismatch(header_1.proposer_index, header_2.proposer_index)
|
||||||
);
|
);
|
||||||
|
|
||||||
// But the headers are different
|
// But the headers are different
|
||||||
verify!(
|
verify!(header_1 != header_2, Invalid::ProposalsIdentical);
|
||||||
proposer_slashing.signed_header_1 != proposer_slashing.signed_header_2,
|
|
||||||
Invalid::ProposalsIdentical
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check proposer is slashable
|
// Check proposer is slashable
|
||||||
|
let proposer = state
|
||||||
|
.validators
|
||||||
|
.get(header_1.proposer_index as usize)
|
||||||
|
.ok_or_else(|| error(Invalid::ProposerUnknown(header_1.proposer_index)))?;
|
||||||
|
|
||||||
verify!(
|
verify!(
|
||||||
proposer.is_slashable_at(state.current_epoch()),
|
proposer.is_slashable_at(state.current_epoch()),
|
||||||
Invalid::ProposerNotSlashable(proposer_slashing.proposer_index)
|
Invalid::ProposerNotSlashable(header_1.proposer_index)
|
||||||
);
|
);
|
||||||
|
|
||||||
if verify_signatures.is_true() {
|
if verify_signatures.is_true() {
|
||||||
|
@ -19,7 +19,7 @@ pub use validator_statuses::{TotalBalances, ValidatorStatus, ValidatorStatuses};
|
|||||||
/// Mutates the given `BeaconState`, returning early if an error is encountered. If an error is
|
/// Mutates the given `BeaconState`, returning early if an error is encountered. If an error is
|
||||||
/// returned, a state might be "half-processed" and therefore in an invalid state.
|
/// returned, a state might be "half-processed" and therefore in an invalid state.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn per_epoch_processing<T: EthSpec>(
|
pub fn per_epoch_processing<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
@ -45,7 +45,11 @@ pub fn per_epoch_processing<T: EthSpec>(
|
|||||||
process_registry_updates(state, spec)?;
|
process_registry_updates(state, spec)?;
|
||||||
|
|
||||||
// Slashings.
|
// Slashings.
|
||||||
process_slashings(state, validator_statuses.total_balances.current_epoch, spec)?;
|
process_slashings(
|
||||||
|
state,
|
||||||
|
validator_statuses.total_balances.current_epoch(),
|
||||||
|
spec,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Final updates.
|
// Final updates.
|
||||||
process_final_updates(state, spec)?;
|
process_final_updates(state, spec)?;
|
||||||
@ -66,7 +70,7 @@ pub fn per_epoch_processing<T: EthSpec>(
|
|||||||
/// - `finalized_epoch`
|
/// - `finalized_epoch`
|
||||||
/// - `finalized_root`
|
/// - `finalized_root`
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[allow(clippy::if_same_then_else)] // For readability and consistency with spec.
|
#[allow(clippy::if_same_then_else)] // For readability and consistency with spec.
|
||||||
pub fn process_justification_and_finalization<T: EthSpec>(
|
pub fn process_justification_and_finalization<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
@ -86,7 +90,7 @@ pub fn process_justification_and_finalization<T: EthSpec>(
|
|||||||
state.previous_justified_checkpoint = state.current_justified_checkpoint.clone();
|
state.previous_justified_checkpoint = state.current_justified_checkpoint.clone();
|
||||||
state.justification_bits.shift_up(1)?;
|
state.justification_bits.shift_up(1)?;
|
||||||
|
|
||||||
if total_balances.previous_epoch_target_attesters * 3 >= total_balances.current_epoch * 2 {
|
if total_balances.previous_epoch_target_attesters() * 3 >= total_balances.current_epoch() * 2 {
|
||||||
state.current_justified_checkpoint = Checkpoint {
|
state.current_justified_checkpoint = Checkpoint {
|
||||||
epoch: previous_epoch,
|
epoch: previous_epoch,
|
||||||
root: *state.get_block_root_at_epoch(previous_epoch)?,
|
root: *state.get_block_root_at_epoch(previous_epoch)?,
|
||||||
@ -94,7 +98,7 @@ pub fn process_justification_and_finalization<T: EthSpec>(
|
|||||||
state.justification_bits.set(1, true)?;
|
state.justification_bits.set(1, true)?;
|
||||||
}
|
}
|
||||||
// If the current epoch gets justified, fill the last bit.
|
// If the current epoch gets justified, fill the last bit.
|
||||||
if total_balances.current_epoch_target_attesters * 3 >= total_balances.current_epoch * 2 {
|
if total_balances.current_epoch_target_attesters() * 3 >= total_balances.current_epoch() * 2 {
|
||||||
state.current_justified_checkpoint = Checkpoint {
|
state.current_justified_checkpoint = Checkpoint {
|
||||||
epoch: current_epoch,
|
epoch: current_epoch,
|
||||||
root: *state.get_block_root_at_epoch(current_epoch)?,
|
root: *state.get_block_root_at_epoch(current_epoch)?,
|
||||||
@ -134,7 +138,7 @@ pub fn process_justification_and_finalization<T: EthSpec>(
|
|||||||
|
|
||||||
/// Finish up an epoch update.
|
/// Finish up an epoch update.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_final_updates<T: EthSpec>(
|
pub fn process_final_updates<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
@ -148,11 +152,14 @@ pub fn process_final_updates<T: EthSpec>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update effective balances with hysteresis (lag).
|
// Update effective balances with hysteresis (lag).
|
||||||
|
let hysteresis_increment = spec.effective_balance_increment / spec.hysteresis_quotient;
|
||||||
|
let downward_threshold = hysteresis_increment * spec.hysteresis_downward_multiplier;
|
||||||
|
let upward_threshold = hysteresis_increment * spec.hysteresis_upward_multiplier;
|
||||||
for (index, validator) in state.validators.iter_mut().enumerate() {
|
for (index, validator) in state.validators.iter_mut().enumerate() {
|
||||||
let balance = state.balances[index];
|
let balance = state.balances[index];
|
||||||
let half_increment = spec.effective_balance_increment / 2;
|
|
||||||
if balance < validator.effective_balance
|
if balance + downward_threshold < validator.effective_balance
|
||||||
|| validator.effective_balance + 3 * half_increment < balance
|
|| validator.effective_balance + upward_threshold < balance
|
||||||
{
|
{
|
||||||
validator.effective_balance = std::cmp::min(
|
validator.effective_balance = std::cmp::min(
|
||||||
balance - balance % spec.effective_balance_increment,
|
balance - balance % spec.effective_balance_increment,
|
||||||
|
@ -33,7 +33,7 @@ impl std::ops::AddAssign for Delta {
|
|||||||
|
|
||||||
/// Apply attester and proposer rewards.
|
/// Apply attester and proposer rewards.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_rewards_and_penalties<T: EthSpec>(
|
pub fn process_rewards_and_penalties<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
validator_statuses: &mut ValidatorStatuses,
|
validator_statuses: &mut ValidatorStatuses,
|
||||||
@ -67,7 +67,7 @@ pub fn process_rewards_and_penalties<T: EthSpec>(
|
|||||||
|
|
||||||
/// For each attesting validator, reward the proposer who was first to include their attestation.
|
/// For each attesting validator, reward the proposer who was first to include their attestation.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn get_proposer_deltas<T: EthSpec>(
|
fn get_proposer_deltas<T: EthSpec>(
|
||||||
deltas: &mut Vec<Delta>,
|
deltas: &mut Vec<Delta>,
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
@ -83,7 +83,7 @@ fn get_proposer_deltas<T: EthSpec>(
|
|||||||
let base_reward = get_base_reward(
|
let base_reward = get_base_reward(
|
||||||
state,
|
state,
|
||||||
index,
|
index,
|
||||||
validator_statuses.total_balances.current_epoch,
|
validator_statuses.total_balances.current_epoch(),
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ fn get_proposer_deltas<T: EthSpec>(
|
|||||||
|
|
||||||
/// Apply rewards for participation in attestations during the previous epoch.
|
/// Apply rewards for participation in attestations during the previous epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn get_attestation_deltas<T: EthSpec>(
|
fn get_attestation_deltas<T: EthSpec>(
|
||||||
deltas: &mut Vec<Delta>,
|
deltas: &mut Vec<Delta>,
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
@ -113,7 +113,7 @@ fn get_attestation_deltas<T: EthSpec>(
|
|||||||
let base_reward = get_base_reward(
|
let base_reward = get_base_reward(
|
||||||
state,
|
state,
|
||||||
index,
|
index,
|
||||||
validator_statuses.total_balances.current_epoch,
|
validator_statuses.total_balances.current_epoch(),
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ fn get_attestation_deltas<T: EthSpec>(
|
|||||||
|
|
||||||
/// Determine the delta for a single validator, sans proposer rewards.
|
/// Determine the delta for a single validator, sans proposer rewards.
|
||||||
///
|
///
|
||||||
/// Spec v0.11.0
|
/// Spec v0.11.1
|
||||||
fn get_attestation_delta<T: EthSpec>(
|
fn get_attestation_delta<T: EthSpec>(
|
||||||
validator: &ValidatorStatus,
|
validator: &ValidatorStatus,
|
||||||
total_balances: &TotalBalances,
|
total_balances: &TotalBalances,
|
||||||
@ -157,13 +157,13 @@ fn get_attestation_delta<T: EthSpec>(
|
|||||||
// - increment = EFFECTIVE_BALANCE_INCREMENT
|
// - increment = EFFECTIVE_BALANCE_INCREMENT
|
||||||
// - reward_numerator = get_base_reward(state, index) * (attesting_balance // increment)
|
// - reward_numerator = get_base_reward(state, index) * (attesting_balance // increment)
|
||||||
// - rewards[index] = reward_numerator // (total_balance // increment)
|
// - rewards[index] = reward_numerator // (total_balance // increment)
|
||||||
let total_balance_ebi = total_balances.current_epoch / spec.effective_balance_increment;
|
let total_balance_ebi = total_balances.current_epoch() / spec.effective_balance_increment;
|
||||||
let total_attesting_balance_ebi =
|
let total_attesting_balance_ebi =
|
||||||
total_balances.previous_epoch_attesters / spec.effective_balance_increment;
|
total_balances.previous_epoch_attesters() / spec.effective_balance_increment;
|
||||||
let matching_target_balance_ebi =
|
let matching_target_balance_ebi =
|
||||||
total_balances.previous_epoch_target_attesters / spec.effective_balance_increment;
|
total_balances.previous_epoch_target_attesters() / spec.effective_balance_increment;
|
||||||
let matching_head_balance_ebi =
|
let matching_head_balance_ebi =
|
||||||
total_balances.previous_epoch_head_attesters / spec.effective_balance_increment;
|
total_balances.previous_epoch_head_attesters() / spec.effective_balance_increment;
|
||||||
|
|
||||||
// Expected FFG source.
|
// Expected FFG source.
|
||||||
// Spec:
|
// Spec:
|
||||||
|
@ -2,7 +2,7 @@ use types::{BeaconStateError as Error, *};
|
|||||||
|
|
||||||
/// Process slashings.
|
/// Process slashings.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_slashings<T: EthSpec>(
|
pub fn process_slashings<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
total_balance: u64,
|
total_balance: u64,
|
||||||
|
@ -5,7 +5,7 @@ use types::*;
|
|||||||
|
|
||||||
/// Performs a validator registry update, if required.
|
/// Performs a validator registry update, if required.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_registry_updates<T: EthSpec>(
|
pub fn process_registry_updates<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
|
@ -12,7 +12,7 @@ macro_rules! set_self_if_other_is_true {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The information required to reward a block producer for including an attestation in a block.
|
/// The information required to reward a block producer for including an attestation in a block.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct InclusionInfo {
|
pub struct InclusionInfo {
|
||||||
/// The distance between the attestation slot and the slot that attestation was included in a
|
/// The distance between the attestation slot and the slot that attestation was included in a
|
||||||
/// block.
|
/// block.
|
||||||
@ -43,7 +43,7 @@ impl InclusionInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Information required to reward some validator during the current and previous epoch.
|
/// Information required to reward some validator during the current and previous epoch.
|
||||||
#[derive(Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct ValidatorStatus {
|
pub struct ValidatorStatus {
|
||||||
/// True if the validator has been slashed, ever.
|
/// True if the validator has been slashed, ever.
|
||||||
pub is_slashed: bool,
|
pub is_slashed: bool,
|
||||||
@ -107,30 +107,64 @@ impl ValidatorStatus {
|
|||||||
|
|
||||||
/// The total effective balances for different sets of validators during the previous and current
|
/// The total effective balances for different sets of validators during the previous and current
|
||||||
/// epochs.
|
/// epochs.
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct TotalBalances {
|
pub struct TotalBalances {
|
||||||
|
/// The effective balance increment from the spec.
|
||||||
|
effective_balance_increment: u64,
|
||||||
/// The total effective balance of all active validators during the _current_ epoch.
|
/// The total effective balance of all active validators during the _current_ epoch.
|
||||||
pub current_epoch: u64,
|
current_epoch: u64,
|
||||||
/// The total effective balance of all active validators during the _previous_ epoch.
|
/// The total effective balance of all active validators during the _previous_ epoch.
|
||||||
pub previous_epoch: u64,
|
previous_epoch: u64,
|
||||||
/// The total effective balance of all validators who attested during the _current_ epoch.
|
/// The total effective balance of all validators who attested during the _current_ epoch.
|
||||||
pub current_epoch_attesters: u64,
|
current_epoch_attesters: u64,
|
||||||
/// The total effective balance of all validators who attested during the _current_ epoch and
|
/// The total effective balance of all validators who attested during the _current_ epoch and
|
||||||
/// agreed with the state about the beacon block at the first slot of the _current_ epoch.
|
/// agreed with the state about the beacon block at the first slot of the _current_ epoch.
|
||||||
pub current_epoch_target_attesters: u64,
|
current_epoch_target_attesters: u64,
|
||||||
/// The total effective balance of all validators who attested during the _previous_ epoch.
|
/// The total effective balance of all validators who attested during the _previous_ epoch.
|
||||||
pub previous_epoch_attesters: u64,
|
previous_epoch_attesters: u64,
|
||||||
/// The total effective balance of all validators who attested during the _previous_ epoch and
|
/// The total effective balance of all validators who attested during the _previous_ epoch and
|
||||||
/// agreed with the state about the beacon block at the first slot of the _previous_ epoch.
|
/// agreed with the state about the beacon block at the first slot of the _previous_ epoch.
|
||||||
pub previous_epoch_target_attesters: u64,
|
previous_epoch_target_attesters: u64,
|
||||||
/// The total effective balance of all validators who attested during the _previous_ epoch and
|
/// The total effective balance of all validators who attested during the _previous_ epoch and
|
||||||
/// agreed with the state about the beacon block at the time of attestation.
|
/// agreed with the state about the beacon block at the time of attestation.
|
||||||
pub previous_epoch_head_attesters: u64,
|
previous_epoch_head_attesters: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a safe accessor for a balance in `TotalBalances`, as per spec `get_total_balance`.
|
||||||
|
macro_rules! balance_accessor {
|
||||||
|
($field_name:ident) => {
|
||||||
|
pub fn $field_name(&self) -> u64 {
|
||||||
|
std::cmp::max(self.effective_balance_increment, self.$field_name)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TotalBalances {
|
||||||
|
pub fn new(spec: &ChainSpec) -> Self {
|
||||||
|
Self {
|
||||||
|
effective_balance_increment: spec.effective_balance_increment,
|
||||||
|
current_epoch: 0,
|
||||||
|
previous_epoch: 0,
|
||||||
|
current_epoch_attesters: 0,
|
||||||
|
current_epoch_target_attesters: 0,
|
||||||
|
previous_epoch_attesters: 0,
|
||||||
|
previous_epoch_target_attesters: 0,
|
||||||
|
previous_epoch_head_attesters: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
balance_accessor!(current_epoch);
|
||||||
|
balance_accessor!(previous_epoch);
|
||||||
|
balance_accessor!(current_epoch_attesters);
|
||||||
|
balance_accessor!(current_epoch_target_attesters);
|
||||||
|
balance_accessor!(previous_epoch_attesters);
|
||||||
|
balance_accessor!(previous_epoch_target_attesters);
|
||||||
|
balance_accessor!(previous_epoch_head_attesters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Summarised information about validator participation in the _previous and _current_ epochs of
|
/// Summarised information about validator participation in the _previous and _current_ epochs of
|
||||||
/// some `BeaconState`.
|
/// some `BeaconState`.
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ValidatorStatuses {
|
pub struct ValidatorStatuses {
|
||||||
/// Information about each individual validator from the state's validator registry.
|
/// Information about each individual validator from the state's validator registry.
|
||||||
pub statuses: Vec<ValidatorStatus>,
|
pub statuses: Vec<ValidatorStatus>,
|
||||||
@ -144,13 +178,13 @@ impl ValidatorStatuses {
|
|||||||
/// - Active validators
|
/// - Active validators
|
||||||
/// - Total balances for the current and previous epochs.
|
/// - Total balances for the current and previous epochs.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn new<T: EthSpec>(
|
pub fn new<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<Self, BeaconStateError> {
|
) -> Result<Self, BeaconStateError> {
|
||||||
let mut statuses = Vec::with_capacity(state.validators.len());
|
let mut statuses = Vec::with_capacity(state.validators.len());
|
||||||
let mut total_balances = TotalBalances::default();
|
let mut total_balances = TotalBalances::new(spec);
|
||||||
|
|
||||||
for (i, validator) in state.validators.iter().enumerate() {
|
for (i, validator) in state.validators.iter().enumerate() {
|
||||||
let effective_balance = state.get_effective_balance(i, spec)?;
|
let effective_balance = state.get_effective_balance(i, spec)?;
|
||||||
@ -184,7 +218,7 @@ impl ValidatorStatuses {
|
|||||||
/// Process some attestations from the given `state` updating the `statuses` and
|
/// Process some attestations from the given `state` updating the `statuses` and
|
||||||
/// `total_balances` fields.
|
/// `total_balances` fields.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn process_attestations<T: EthSpec>(
|
pub fn process_attestations<T: EthSpec>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
@ -221,10 +255,10 @@ impl ValidatorStatuses {
|
|||||||
|
|
||||||
if target_matches_epoch_start_block(a, state, state.previous_epoch())? {
|
if target_matches_epoch_start_block(a, state, state.previous_epoch())? {
|
||||||
status.is_previous_epoch_target_attester = true;
|
status.is_previous_epoch_target_attester = true;
|
||||||
}
|
|
||||||
|
|
||||||
if has_common_beacon_block_root(a, state)? {
|
if has_common_beacon_block_root(a, state)? {
|
||||||
status.is_previous_epoch_head_attester = true;
|
status.is_previous_epoch_head_attester = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +299,7 @@ impl ValidatorStatuses {
|
|||||||
/// Returns `true` if the attestation's FFG target is equal to the hash of the `state`'s first
|
/// Returns `true` if the attestation's FFG target is equal to the hash of the `state`'s first
|
||||||
/// beacon block in the given `epoch`.
|
/// beacon block in the given `epoch`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn target_matches_epoch_start_block<T: EthSpec>(
|
fn target_matches_epoch_start_block<T: EthSpec>(
|
||||||
a: &PendingAttestation<T>,
|
a: &PendingAttestation<T>,
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
@ -280,7 +314,7 @@ fn target_matches_epoch_start_block<T: EthSpec>(
|
|||||||
/// Returns `true` if a `PendingAttestation` and `BeaconState` share the same beacon block hash for
|
/// Returns `true` if a `PendingAttestation` and `BeaconState` share the same beacon block hash for
|
||||||
/// the current slot of the `PendingAttestation`.
|
/// the current slot of the `PendingAttestation`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn has_common_beacon_block_root<T: EthSpec>(
|
fn has_common_beacon_block_root<T: EthSpec>(
|
||||||
a: &PendingAttestation<T>,
|
a: &PendingAttestation<T>,
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
|
@ -13,7 +13,7 @@ pub enum Error {
|
|||||||
/// `state_root` is `None`, the root of `state` will be computed using a cached tree hash.
|
/// `state_root` is `None`, the root of `state` will be computed using a cached tree hash.
|
||||||
/// Providing the `state_root` makes this function several orders of magniude faster.
|
/// Providing the `state_root` makes this function several orders of magniude faster.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn per_slot_processing<T: EthSpec>(
|
pub fn per_slot_processing<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
state_root: Option<Hash256>,
|
state_root: Option<Hash256>,
|
||||||
|
@ -62,7 +62,14 @@ impl<T: EthSpec> BlockBuilder<T> {
|
|||||||
|
|
||||||
let proposer_keypair = &keypairs[proposer_index];
|
let proposer_keypair = &keypairs[proposer_index];
|
||||||
|
|
||||||
builder.set_randao_reveal(&proposer_keypair.sk, &state.fork, spec);
|
builder.set_proposer_index(proposer_index as u64);
|
||||||
|
|
||||||
|
builder.set_randao_reveal(
|
||||||
|
&proposer_keypair.sk,
|
||||||
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
let parent_root = state.latest_block_header.canonical_root();
|
let parent_root = state.latest_block_header.canonical_root();
|
||||||
builder.set_parent_root(parent_root);
|
builder.set_parent_root(parent_root);
|
||||||
@ -79,6 +86,7 @@ impl<T: EthSpec> BlockBuilder<T> {
|
|||||||
validator_index,
|
validator_index,
|
||||||
&keypairs[validator_index as usize].sk,
|
&keypairs[validator_index as usize].sk,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -106,6 +114,7 @@ impl<T: EthSpec> BlockBuilder<T> {
|
|||||||
&attesters,
|
&attesters,
|
||||||
&secret_keys,
|
&secret_keys,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -161,9 +170,12 @@ impl<T: EthSpec> BlockBuilder<T> {
|
|||||||
// Set the eth1 data to be different from the state.
|
// Set the eth1 data to be different from the state.
|
||||||
self.block_builder.block.body.eth1_data.block_hash = Hash256::from_slice(&[42; 32]);
|
self.block_builder.block.body.eth1_data.block_hash = Hash256::from_slice(&[42; 32]);
|
||||||
|
|
||||||
let block = self
|
let block = self.block_builder.build(
|
||||||
.block_builder
|
&proposer_keypair.sk,
|
||||||
.build(&proposer_keypair.sk, &state.fork, spec);
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
|
|
||||||
(block, state)
|
(block, state)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use super::{
|
|||||||
AggregateSignature, AttestationData, BitList, ChainSpec, Domain, EthSpec, Fork, SecretKey,
|
AggregateSignature, AttestationData, BitList, ChainSpec, Domain, EthSpec, Fork, SecretKey,
|
||||||
Signature, SignedRoot,
|
Signature, SignedRoot,
|
||||||
};
|
};
|
||||||
use crate::test_utils::TestRandom;
|
use crate::{test_utils::TestRandom, Hash256};
|
||||||
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
@ -17,7 +17,7 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Details an attestation that can be slashable.
|
/// Details an attestation that can be slashable.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
#[serde(bound = "T: EthSpec")]
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct Attestation<T: EthSpec> {
|
pub struct Attestation<T: EthSpec> {
|
||||||
@ -53,6 +53,7 @@ impl<T: EthSpec> Attestation<T> {
|
|||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
committee_position: usize,
|
committee_position: usize,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if self
|
if self
|
||||||
@ -66,7 +67,12 @@ impl<T: EthSpec> Attestation<T> {
|
|||||||
.set(committee_position, true)
|
.set(committee_position, true)
|
||||||
.map_err(Error::SszTypesError)?;
|
.map_err(Error::SszTypesError)?;
|
||||||
|
|
||||||
let domain = spec.get_domain(self.data.target.epoch, Domain::BeaconAttester, fork);
|
let domain = spec.get_domain(
|
||||||
|
self.data.target.epoch,
|
||||||
|
Domain::BeaconAttester,
|
||||||
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
);
|
||||||
let message = self.data.signing_root(domain);
|
let message = self.data.signing_root(domain);
|
||||||
|
|
||||||
self.signature
|
self.signature
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// The data upon which an attestation is based.
|
/// The data upon which an attestation is based.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Encode, Decode, TreeHash, TestRandom,
|
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, Encode, Decode, TreeHash, TestRandom,
|
||||||
)]
|
)]
|
||||||
|
@ -7,7 +7,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// Two conflicting attestations.
|
/// Two conflicting attestations.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
#[serde(bound = "T: EthSpec")]
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct AttesterSlashing<T: EthSpec> {
|
pub struct AttesterSlashing<T: EthSpec> {
|
||||||
|
@ -10,11 +10,12 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// A block of the `BeaconChain`.
|
/// A block of the `BeaconChain`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
#[serde(bound = "T: EthSpec")]
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct BeaconBlock<T: EthSpec> {
|
pub struct BeaconBlock<T: EthSpec> {
|
||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
|
pub proposer_index: u64,
|
||||||
pub parent_root: Hash256,
|
pub parent_root: Hash256,
|
||||||
pub state_root: Hash256,
|
pub state_root: Hash256,
|
||||||
pub body: BeaconBlockBody<T>,
|
pub body: BeaconBlockBody<T>,
|
||||||
@ -25,10 +26,11 @@ impl<T: EthSpec> SignedRoot for BeaconBlock<T> {}
|
|||||||
impl<T: EthSpec> BeaconBlock<T> {
|
impl<T: EthSpec> BeaconBlock<T> {
|
||||||
/// Returns an empty block to be used during genesis.
|
/// Returns an empty block to be used during genesis.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn empty(spec: &ChainSpec) -> Self {
|
pub fn empty(spec: &ChainSpec) -> Self {
|
||||||
BeaconBlock {
|
BeaconBlock {
|
||||||
slot: spec.genesis_slot,
|
slot: spec.genesis_slot,
|
||||||
|
proposer_index: 0,
|
||||||
parent_root: Hash256::zero(),
|
parent_root: Hash256::zero(),
|
||||||
state_root: Hash256::zero(),
|
state_root: Hash256::zero(),
|
||||||
body: BeaconBlockBody {
|
body: BeaconBlockBody {
|
||||||
@ -55,7 +57,7 @@ impl<T: EthSpec> BeaconBlock<T> {
|
|||||||
|
|
||||||
/// Returns the `tree_hash_root` of the block.
|
/// Returns the `tree_hash_root` of the block.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn canonical_root(&self) -> Hash256 {
|
pub fn canonical_root(&self) -> Hash256 {
|
||||||
Hash256::from_slice(&self.tree_hash_root()[..])
|
Hash256::from_slice(&self.tree_hash_root()[..])
|
||||||
}
|
}
|
||||||
@ -67,10 +69,11 @@ impl<T: EthSpec> BeaconBlock<T> {
|
|||||||
///
|
///
|
||||||
/// Note: performs a full tree-hash of `self.body`.
|
/// Note: performs a full tree-hash of `self.body`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn block_header(&self) -> BeaconBlockHeader {
|
pub fn block_header(&self) -> BeaconBlockHeader {
|
||||||
BeaconBlockHeader {
|
BeaconBlockHeader {
|
||||||
slot: self.slot,
|
slot: self.slot,
|
||||||
|
proposer_index: self.proposer_index,
|
||||||
parent_root: self.parent_root,
|
parent_root: self.parent_root,
|
||||||
state_root: self.state_root,
|
state_root: self.state_root,
|
||||||
body_root: Hash256::from_slice(&self.body.tree_hash_root()[..]),
|
body_root: Hash256::from_slice(&self.body.tree_hash_root()[..]),
|
||||||
@ -79,7 +82,7 @@ impl<T: EthSpec> BeaconBlock<T> {
|
|||||||
|
|
||||||
/// Returns a "temporary" header, where the `state_root` is `Hash256::zero()`.
|
/// Returns a "temporary" header, where the `state_root` is `Hash256::zero()`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn temporary_block_header(&self) -> BeaconBlockHeader {
|
pub fn temporary_block_header(&self) -> BeaconBlockHeader {
|
||||||
BeaconBlockHeader {
|
BeaconBlockHeader {
|
||||||
state_root: Hash256::zero(),
|
state_root: Hash256::zero(),
|
||||||
@ -92,9 +95,15 @@ impl<T: EthSpec> BeaconBlock<T> {
|
|||||||
self,
|
self,
|
||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> SignedBeaconBlock<T> {
|
) -> SignedBeaconBlock<T> {
|
||||||
let domain = spec.get_domain(self.epoch(), Domain::BeaconProposer, fork);
|
let domain = spec.get_domain(
|
||||||
|
self.epoch(),
|
||||||
|
Domain::BeaconProposer,
|
||||||
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
);
|
||||||
let message = self.signing_root(domain);
|
let message = self.signing_root(domain);
|
||||||
let signature = Signature::new(message.as_bytes(), secret_key);
|
let signature = Signature::new(message.as_bytes(), secret_key);
|
||||||
SignedBeaconBlock {
|
SignedBeaconBlock {
|
||||||
|
@ -10,7 +10,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// The body of a `BeaconChain` block, containing operations.
|
/// The body of a `BeaconChain` block, containing operations.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
#[serde(bound = "T: EthSpec")]
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct BeaconBlockBody<T: EthSpec> {
|
pub struct BeaconBlockBody<T: EthSpec> {
|
||||||
|
@ -9,10 +9,11 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// A header of a `BeaconBlock`.
|
/// A header of a `BeaconBlock`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct BeaconBlockHeader {
|
pub struct BeaconBlockHeader {
|
||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
|
pub proposer_index: u64,
|
||||||
pub parent_root: Hash256,
|
pub parent_root: Hash256,
|
||||||
pub state_root: Hash256,
|
pub state_root: Hash256,
|
||||||
pub body_root: Hash256,
|
pub body_root: Hash256,
|
||||||
@ -23,17 +24,18 @@ impl SignedRoot for BeaconBlockHeader {}
|
|||||||
impl BeaconBlockHeader {
|
impl BeaconBlockHeader {
|
||||||
/// Returns the `tree_hash_root` of the header.
|
/// Returns the `tree_hash_root` of the header.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn canonical_root(&self) -> Hash256 {
|
pub fn canonical_root(&self) -> Hash256 {
|
||||||
Hash256::from_slice(&self.tree_hash_root()[..])
|
Hash256::from_slice(&self.tree_hash_root()[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `body`, consumes `self` and returns a complete `BeaconBlock`.
|
/// Given a `body`, consumes `self` and returns a complete `BeaconBlock`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn into_block<T: EthSpec>(self, body: BeaconBlockBody<T>) -> BeaconBlock<T> {
|
pub fn into_block<T: EthSpec>(self, body: BeaconBlockBody<T>) -> BeaconBlock<T> {
|
||||||
BeaconBlock {
|
BeaconBlock {
|
||||||
slot: self.slot,
|
slot: self.slot,
|
||||||
|
proposer_index: self.proposer_index,
|
||||||
parent_root: self.parent_root,
|
parent_root: self.parent_root,
|
||||||
state_root: self.state_root,
|
state_root: self.state_root,
|
||||||
body,
|
body,
|
||||||
@ -45,10 +47,11 @@ impl BeaconBlockHeader {
|
|||||||
self,
|
self,
|
||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> SignedBeaconBlockHeader {
|
) -> SignedBeaconBlockHeader {
|
||||||
let epoch = self.slot.epoch(E::slots_per_epoch());
|
let epoch = self.slot.epoch(E::slots_per_epoch());
|
||||||
let domain = spec.get_domain(epoch, Domain::BeaconProposer, fork);
|
let domain = spec.get_domain(epoch, Domain::BeaconProposer, fork, genesis_validators_root);
|
||||||
let message = self.signing_root(domain);
|
let message = self.signing_root(domain);
|
||||||
let signature = Signature::new(message.as_bytes(), secret_key);
|
let signature = Signature::new(message.as_bytes(), secret_key);
|
||||||
SignedBeaconBlockHeader {
|
SignedBeaconBlockHeader {
|
||||||
|
@ -91,7 +91,7 @@ impl AllowNextEpoch {
|
|||||||
|
|
||||||
/// The state of the `BeaconChain` at some slot.
|
/// The state of the `BeaconChain` at some slot.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@ -111,6 +111,7 @@ where
|
|||||||
{
|
{
|
||||||
// Versioning
|
// Versioning
|
||||||
pub genesis_time: u64,
|
pub genesis_time: u64,
|
||||||
|
pub genesis_validators_root: Hash256,
|
||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
pub fork: Fork,
|
pub fork: Fork,
|
||||||
|
|
||||||
@ -182,11 +183,12 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Not a complete genesis state, see `initialize_beacon_state_from_eth1`.
|
/// Not a complete genesis state, see `initialize_beacon_state_from_eth1`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn new(genesis_time: u64, eth1_data: Eth1Data, spec: &ChainSpec) -> Self {
|
pub fn new(genesis_time: u64, eth1_data: Eth1Data, spec: &ChainSpec) -> Self {
|
||||||
BeaconState {
|
BeaconState {
|
||||||
// Versioning
|
// Versioning
|
||||||
genesis_time,
|
genesis_time,
|
||||||
|
genesis_validators_root: Hash256::zero(), // Set later.
|
||||||
slot: spec.genesis_slot,
|
slot: spec.genesis_slot,
|
||||||
fork: Fork {
|
fork: Fork {
|
||||||
previous_version: spec.genesis_fork_version,
|
previous_version: spec.genesis_fork_version,
|
||||||
@ -239,7 +241,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Returns the `tree_hash_root` of the state.
|
/// Returns the `tree_hash_root` of the state.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn canonical_root(&self) -> Hash256 {
|
pub fn canonical_root(&self) -> Hash256 {
|
||||||
Hash256::from_slice(&self.tree_hash_root()[..])
|
Hash256::from_slice(&self.tree_hash_root()[..])
|
||||||
}
|
}
|
||||||
@ -268,7 +270,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// The epoch corresponding to `self.slot`.
|
/// The epoch corresponding to `self.slot`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn current_epoch(&self) -> Epoch {
|
pub fn current_epoch(&self) -> Epoch {
|
||||||
self.slot.epoch(T::slots_per_epoch())
|
self.slot.epoch(T::slots_per_epoch())
|
||||||
}
|
}
|
||||||
@ -277,7 +279,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// If the current epoch is the genesis epoch, the genesis_epoch is returned.
|
/// If the current epoch is the genesis epoch, the genesis_epoch is returned.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn previous_epoch(&self) -> Epoch {
|
pub fn previous_epoch(&self) -> Epoch {
|
||||||
let current_epoch = self.current_epoch();
|
let current_epoch = self.current_epoch();
|
||||||
if current_epoch > T::genesis_epoch() {
|
if current_epoch > T::genesis_epoch() {
|
||||||
@ -289,7 +291,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// The epoch following `self.current_epoch()`.
|
/// The epoch following `self.current_epoch()`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn next_epoch(&self) -> Epoch {
|
pub fn next_epoch(&self) -> Epoch {
|
||||||
self.current_epoch() + 1
|
self.current_epoch() + 1
|
||||||
}
|
}
|
||||||
@ -298,7 +300,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Makes use of the committee cache and will fail if no cache exists for the slot's epoch.
|
/// Makes use of the committee cache and will fail if no cache exists for the slot's epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_committee_count_at_slot(&self, slot: Slot) -> Result<u64, Error> {
|
pub fn get_committee_count_at_slot(&self, slot: Slot) -> Result<u64, Error> {
|
||||||
let cache = self.committee_cache_at_slot(slot)?;
|
let cache = self.committee_cache_at_slot(slot)?;
|
||||||
Ok(cache.committees_per_slot() as u64)
|
Ok(cache.committees_per_slot() as u64)
|
||||||
@ -306,7 +308,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Compute the number of committees in an entire epoch.
|
/// Compute the number of committees in an entire epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_epoch_committee_count(&self, relative_epoch: RelativeEpoch) -> Result<u64, Error> {
|
pub fn get_epoch_committee_count(&self, relative_epoch: RelativeEpoch) -> Result<u64, Error> {
|
||||||
let cache = self.committee_cache(relative_epoch)?;
|
let cache = self.committee_cache(relative_epoch)?;
|
||||||
Ok(cache.epoch_committee_count() as u64)
|
Ok(cache.epoch_committee_count() as u64)
|
||||||
@ -330,7 +332,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Does not utilize the cache, performs a full iteration over the validator registry.
|
/// Does not utilize the cache, performs a full iteration over the validator registry.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_active_validator_indices(&self, epoch: Epoch) -> Vec<usize> {
|
pub fn get_active_validator_indices(&self, epoch: Epoch) -> Vec<usize> {
|
||||||
get_active_validator_indices(&self.validators, epoch)
|
get_active_validator_indices(&self.validators, epoch)
|
||||||
}
|
}
|
||||||
@ -350,7 +352,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Utilises the committee cache.
|
/// Utilises the committee cache.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_beacon_committee(
|
pub fn get_beacon_committee(
|
||||||
&self,
|
&self,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
@ -369,7 +371,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Utilises the committee cache.
|
/// Utilises the committee cache.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_beacon_committees_at_slot(&self, slot: Slot) -> Result<Vec<BeaconCommittee>, Error> {
|
pub fn get_beacon_committees_at_slot(&self, slot: Slot) -> Result<Vec<BeaconCommittee>, Error> {
|
||||||
let cache = self.committee_cache_at_slot(slot)?;
|
let cache = self.committee_cache_at_slot(slot)?;
|
||||||
cache.get_beacon_committees_at_slot(slot)
|
cache.get_beacon_committees_at_slot(slot)
|
||||||
@ -379,7 +381,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Utilises the committee cache.
|
/// Utilises the committee cache.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_beacon_committees_at_epoch(
|
pub fn get_beacon_committees_at_epoch(
|
||||||
&self,
|
&self,
|
||||||
relative_epoch: RelativeEpoch,
|
relative_epoch: RelativeEpoch,
|
||||||
@ -390,7 +392,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Compute the proposer (not necessarily for the Beacon chain) from a list of indices.
|
/// Compute the proposer (not necessarily for the Beacon chain) from a list of indices.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
// NOTE: be sure to test this bad boy.
|
// NOTE: be sure to test this bad boy.
|
||||||
pub fn compute_proposer_index(
|
pub fn compute_proposer_index(
|
||||||
&self,
|
&self,
|
||||||
@ -429,7 +431,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Returns the beacon proposer index for the `slot` in the given `relative_epoch`.
|
/// Returns the beacon proposer index for the `slot` in the given `relative_epoch`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_beacon_proposer_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
|
pub fn get_beacon_proposer_index(&self, slot: Slot, spec: &ChainSpec) -> Result<usize, Error> {
|
||||||
let epoch = slot.epoch(T::slots_per_epoch());
|
let epoch = slot.epoch(T::slots_per_epoch());
|
||||||
let seed = self.get_beacon_proposer_seed(slot, spec)?;
|
let seed = self.get_beacon_proposer_seed(slot, spec)?;
|
||||||
@ -440,7 +442,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Compute the seed to use for the beacon proposer selection at the given `slot`.
|
/// Compute the seed to use for the beacon proposer selection at the given `slot`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn get_beacon_proposer_seed(&self, slot: Slot, spec: &ChainSpec) -> Result<Vec<u8>, Error> {
|
fn get_beacon_proposer_seed(&self, slot: Slot, spec: &ChainSpec) -> Result<Vec<u8>, Error> {
|
||||||
let epoch = slot.epoch(T::slots_per_epoch());
|
let epoch = slot.epoch(T::slots_per_epoch());
|
||||||
let mut preimage = self
|
let mut preimage = self
|
||||||
@ -455,7 +457,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// It needs filling in on all slots where there isn't a skip.
|
/// It needs filling in on all slots where there isn't a skip.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_latest_block_root(&self, current_state_root: Hash256) -> Hash256 {
|
pub fn get_latest_block_root(&self, current_state_root: Hash256) -> Hash256 {
|
||||||
if self.latest_block_header.state_root.is_zero() {
|
if self.latest_block_header.state_root.is_zero() {
|
||||||
let mut latest_block_header = self.latest_block_header.clone();
|
let mut latest_block_header = self.latest_block_header.clone();
|
||||||
@ -468,7 +470,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Safely obtains the index for latest block roots, given some `slot`.
|
/// Safely obtains the index for latest block roots, given some `slot`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn get_latest_block_roots_index(&self, slot: Slot) -> Result<usize, Error> {
|
fn get_latest_block_roots_index(&self, slot: Slot) -> Result<usize, Error> {
|
||||||
if (slot < self.slot) && (self.slot <= slot + self.block_roots.len() as u64) {
|
if (slot < self.slot) && (self.slot <= slot + self.block_roots.len() as u64) {
|
||||||
Ok(slot.as_usize() % self.block_roots.len())
|
Ok(slot.as_usize() % self.block_roots.len())
|
||||||
@ -479,7 +481,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Return the block root at a recent `slot`.
|
/// Return the block root at a recent `slot`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_block_root(&self, slot: Slot) -> Result<&Hash256, BeaconStateError> {
|
pub fn get_block_root(&self, slot: Slot) -> Result<&Hash256, BeaconStateError> {
|
||||||
let i = self.get_latest_block_roots_index(slot)?;
|
let i = self.get_latest_block_roots_index(slot)?;
|
||||||
Ok(&self.block_roots[i])
|
Ok(&self.block_roots[i])
|
||||||
@ -487,7 +489,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Return the block root at a recent `epoch`.
|
/// Return the block root at a recent `epoch`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
// NOTE: the spec calls this get_block_root
|
// NOTE: the spec calls this get_block_root
|
||||||
pub fn get_block_root_at_epoch(&self, epoch: Epoch) -> Result<&Hash256, BeaconStateError> {
|
pub fn get_block_root_at_epoch(&self, epoch: Epoch) -> Result<&Hash256, BeaconStateError> {
|
||||||
self.get_block_root(epoch.start_slot(T::slots_per_epoch()))
|
self.get_block_root(epoch.start_slot(T::slots_per_epoch()))
|
||||||
@ -495,7 +497,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Sets the block root for some given slot.
|
/// Sets the block root for some given slot.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn set_block_root(
|
pub fn set_block_root(
|
||||||
&mut self,
|
&mut self,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
@ -513,7 +515,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Safely obtains the index for `randao_mixes`
|
/// Safely obtains the index for `randao_mixes`
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn get_randao_mix_index(
|
fn get_randao_mix_index(
|
||||||
&self,
|
&self,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
@ -535,7 +537,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// See `Self::get_randao_mix`.
|
/// See `Self::get_randao_mix`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn update_randao_mix(&mut self, epoch: Epoch, signature: &Signature) -> Result<(), Error> {
|
pub fn update_randao_mix(&mut self, epoch: Epoch, signature: &Signature) -> Result<(), Error> {
|
||||||
let i = epoch.as_usize() % T::EpochsPerHistoricalVector::to_usize();
|
let i = epoch.as_usize() % T::EpochsPerHistoricalVector::to_usize();
|
||||||
|
|
||||||
@ -548,7 +550,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Return the randao mix at a recent ``epoch``.
|
/// Return the randao mix at a recent ``epoch``.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_randao_mix(&self, epoch: Epoch) -> Result<&Hash256, Error> {
|
pub fn get_randao_mix(&self, epoch: Epoch) -> Result<&Hash256, Error> {
|
||||||
let i = self.get_randao_mix_index(epoch, AllowNextEpoch::False)?;
|
let i = self.get_randao_mix_index(epoch, AllowNextEpoch::False)?;
|
||||||
Ok(&self.randao_mixes[i])
|
Ok(&self.randao_mixes[i])
|
||||||
@ -556,7 +558,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Set the randao mix at a recent ``epoch``.
|
/// Set the randao mix at a recent ``epoch``.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn set_randao_mix(&mut self, epoch: Epoch, mix: Hash256) -> Result<(), Error> {
|
pub fn set_randao_mix(&mut self, epoch: Epoch, mix: Hash256) -> Result<(), Error> {
|
||||||
let i = self.get_randao_mix_index(epoch, AllowNextEpoch::True)?;
|
let i = self.get_randao_mix_index(epoch, AllowNextEpoch::True)?;
|
||||||
self.randao_mixes[i] = mix;
|
self.randao_mixes[i] = mix;
|
||||||
@ -565,7 +567,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Safely obtains the index for latest state roots, given some `slot`.
|
/// Safely obtains the index for latest state roots, given some `slot`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn get_latest_state_roots_index(&self, slot: Slot) -> Result<usize, Error> {
|
fn get_latest_state_roots_index(&self, slot: Slot) -> Result<usize, Error> {
|
||||||
if (slot < self.slot) && (self.slot <= slot + Slot::from(self.state_roots.len())) {
|
if (slot < self.slot) && (self.slot <= slot + Slot::from(self.state_roots.len())) {
|
||||||
Ok(slot.as_usize() % self.state_roots.len())
|
Ok(slot.as_usize() % self.state_roots.len())
|
||||||
@ -576,7 +578,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Gets the state root for some slot.
|
/// Gets the state root for some slot.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_state_root(&self, slot: Slot) -> Result<&Hash256, Error> {
|
pub fn get_state_root(&self, slot: Slot) -> Result<&Hash256, Error> {
|
||||||
let i = self.get_latest_state_roots_index(slot)?;
|
let i = self.get_latest_state_roots_index(slot)?;
|
||||||
Ok(&self.state_roots[i])
|
Ok(&self.state_roots[i])
|
||||||
@ -584,7 +586,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Gets the oldest (earliest slot) state root.
|
/// Gets the oldest (earliest slot) state root.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_oldest_state_root(&self) -> Result<&Hash256, Error> {
|
pub fn get_oldest_state_root(&self) -> Result<&Hash256, Error> {
|
||||||
let i =
|
let i =
|
||||||
self.get_latest_state_roots_index(self.slot - Slot::from(self.state_roots.len()))?;
|
self.get_latest_state_roots_index(self.slot - Slot::from(self.state_roots.len()))?;
|
||||||
@ -593,7 +595,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Gets the oldest (earliest slot) block root.
|
/// Gets the oldest (earliest slot) block root.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_oldest_block_root(&self) -> Result<&Hash256, Error> {
|
pub fn get_oldest_block_root(&self) -> Result<&Hash256, Error> {
|
||||||
let i = self.get_latest_block_roots_index(self.slot - self.block_roots.len() as u64)?;
|
let i = self.get_latest_block_roots_index(self.slot - self.block_roots.len() as u64)?;
|
||||||
Ok(&self.block_roots[i])
|
Ok(&self.block_roots[i])
|
||||||
@ -601,7 +603,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Sets the latest state root for slot.
|
/// Sets the latest state root for slot.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn set_state_root(&mut self, slot: Slot, state_root: Hash256) -> Result<(), Error> {
|
pub fn set_state_root(&mut self, slot: Slot, state_root: Hash256) -> Result<(), Error> {
|
||||||
let i = self.get_latest_state_roots_index(slot)?;
|
let i = self.get_latest_state_roots_index(slot)?;
|
||||||
self.state_roots[i] = state_root;
|
self.state_roots[i] = state_root;
|
||||||
@ -610,7 +612,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Safely obtain the index for `slashings`, given some `epoch`.
|
/// Safely obtain the index for `slashings`, given some `epoch`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn get_slashings_index(
|
fn get_slashings_index(
|
||||||
&self,
|
&self,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
@ -630,14 +632,14 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Get a reference to the entire `slashings` vector.
|
/// Get a reference to the entire `slashings` vector.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_all_slashings(&self) -> &[u64] {
|
pub fn get_all_slashings(&self) -> &[u64] {
|
||||||
&self.slashings
|
&self.slashings
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the total slashed balances for some epoch.
|
/// Get the total slashed balances for some epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_slashings(&self, epoch: Epoch) -> Result<u64, Error> {
|
pub fn get_slashings(&self, epoch: Epoch) -> Result<u64, Error> {
|
||||||
let i = self.get_slashings_index(epoch, AllowNextEpoch::False)?;
|
let i = self.get_slashings_index(epoch, AllowNextEpoch::False)?;
|
||||||
Ok(self.slashings[i])
|
Ok(self.slashings[i])
|
||||||
@ -645,7 +647,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Set the total slashed balances for some epoch.
|
/// Set the total slashed balances for some epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn set_slashings(&mut self, epoch: Epoch, value: u64) -> Result<(), Error> {
|
pub fn set_slashings(&mut self, epoch: Epoch, value: u64) -> Result<(), Error> {
|
||||||
let i = self.get_slashings_index(epoch, AllowNextEpoch::True)?;
|
let i = self.get_slashings_index(epoch, AllowNextEpoch::True)?;
|
||||||
self.slashings[i] = value;
|
self.slashings[i] = value;
|
||||||
@ -654,7 +656,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Get the attestations from the current or previous epoch.
|
/// Get the attestations from the current or previous epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_matching_source_attestations(
|
pub fn get_matching_source_attestations(
|
||||||
&self,
|
&self,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
@ -670,7 +672,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Generate a seed for the given `epoch`.
|
/// Generate a seed for the given `epoch`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_seed(
|
pub fn get_seed(
|
||||||
&self,
|
&self,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
@ -701,7 +703,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Return the effective balance (also known as "balance at stake") for a validator with the given ``index``.
|
/// Return the effective balance (also known as "balance at stake") for a validator with the given ``index``.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_effective_balance(
|
pub fn get_effective_balance(
|
||||||
&self,
|
&self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
@ -715,7 +717,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Return the epoch at which an activation or exit triggered in ``epoch`` takes effect.
|
/// Return the epoch at which an activation or exit triggered in ``epoch`` takes effect.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn compute_activation_exit_epoch(&self, epoch: Epoch, spec: &ChainSpec) -> Epoch {
|
pub fn compute_activation_exit_epoch(&self, epoch: Epoch, spec: &ChainSpec) -> Epoch {
|
||||||
epoch + 1 + spec.max_seed_lookahead
|
epoch + 1 + spec.max_seed_lookahead
|
||||||
}
|
}
|
||||||
@ -724,7 +726,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Uses the epoch cache, and will error if it isn't initialized.
|
/// Uses the epoch cache, and will error if it isn't initialized.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_churn_limit(&self, spec: &ChainSpec) -> Result<u64, Error> {
|
pub fn get_churn_limit(&self, spec: &ChainSpec) -> Result<u64, Error> {
|
||||||
Ok(std::cmp::max(
|
Ok(std::cmp::max(
|
||||||
spec.min_per_epoch_churn_limit,
|
spec.min_per_epoch_churn_limit,
|
||||||
@ -739,7 +741,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
///
|
///
|
||||||
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
|
/// Note: Utilizes the cache and will fail if the appropriate cache is not initialized.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_attestation_duties(
|
pub fn get_attestation_duties(
|
||||||
&self,
|
&self,
|
||||||
validator_index: usize,
|
validator_index: usize,
|
||||||
@ -752,7 +754,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
|
|
||||||
/// Return the combined effective balance of an array of validators.
|
/// Return the combined effective balance of an array of validators.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_total_balance(
|
pub fn get_total_balance(
|
||||||
&self,
|
&self,
|
||||||
validator_indices: &[usize],
|
validator_indices: &[usize],
|
||||||
@ -925,7 +927,26 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
if let Some(mut cache) = cache {
|
if let Some(mut cache) = cache {
|
||||||
// Note: we return early if the tree hash fails, leaving `self.tree_hash_cache` as
|
// Note: we return early if the tree hash fails, leaving `self.tree_hash_cache` as
|
||||||
// None. There's no need to keep a cache that fails.
|
// None. There's no need to keep a cache that fails.
|
||||||
let root = cache.recalculate_tree_hash_root(self)?;
|
let root = cache.recalculate_tree_hash_root(&self)?;
|
||||||
|
self.tree_hash_cache = Some(cache);
|
||||||
|
Ok(root)
|
||||||
|
} else {
|
||||||
|
Err(Error::TreeHashCacheNotInitialized)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute the tree hash root of the validators using the tree hash cache.
|
||||||
|
///
|
||||||
|
/// Initialize the tree hash cache if it isn't already initialized.
|
||||||
|
pub fn update_validators_tree_hash_cache(&mut self) -> Result<Hash256, Error> {
|
||||||
|
self.initialize_tree_hash_cache();
|
||||||
|
|
||||||
|
let cache = self.tree_hash_cache.take();
|
||||||
|
|
||||||
|
if let Some(mut cache) = cache {
|
||||||
|
// Note: we return early if the tree hash fails, leaving `self.tree_hash_cache` as
|
||||||
|
// None. There's no need to keep a cache that fails.
|
||||||
|
let root = cache.recalculate_validators_tree_hash_root(&self.validators)?;
|
||||||
self.tree_hash_cache = Some(cache);
|
self.tree_hash_cache = Some(cache);
|
||||||
Ok(root)
|
Ok(root)
|
||||||
} else {
|
} else {
|
||||||
@ -959,6 +980,7 @@ impl<T: EthSpec> BeaconState<T> {
|
|||||||
pub fn clone_with(&self, config: CloneConfig) -> Self {
|
pub fn clone_with(&self, config: CloneConfig) -> Self {
|
||||||
BeaconState {
|
BeaconState {
|
||||||
genesis_time: self.genesis_time,
|
genesis_time: self.genesis_time,
|
||||||
|
genesis_validators_root: self.genesis_validators_root,
|
||||||
slot: self.slot,
|
slot: self.slot,
|
||||||
fork: self.fork.clone(),
|
fork: self.fork.clone(),
|
||||||
latest_block_header: self.latest_block_header.clone(),
|
latest_block_header: self.latest_block_header.clone(),
|
||||||
|
@ -22,7 +22,7 @@ pub struct CommitteeCache {
|
|||||||
impl CommitteeCache {
|
impl CommitteeCache {
|
||||||
/// Return a new, fully initialized cache.
|
/// Return a new, fully initialized cache.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn initialized<T: EthSpec>(
|
pub fn initialized<T: EthSpec>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
@ -87,7 +87,7 @@ impl CommitteeCache {
|
|||||||
///
|
///
|
||||||
/// Always returns `&[]` for a non-initialized epoch.
|
/// Always returns `&[]` for a non-initialized epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn active_validator_indices(&self) -> &[usize] {
|
pub fn active_validator_indices(&self) -> &[usize] {
|
||||||
&self.shuffling
|
&self.shuffling
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ impl CommitteeCache {
|
|||||||
///
|
///
|
||||||
/// Always returns `&[]` for a non-initialized epoch.
|
/// Always returns `&[]` for a non-initialized epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn shuffling(&self) -> &[usize] {
|
pub fn shuffling(&self) -> &[usize] {
|
||||||
&self.shuffling
|
&self.shuffling
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ impl CommitteeCache {
|
|||||||
///
|
///
|
||||||
/// Always returns `usize::default()` for a non-initialized epoch.
|
/// Always returns `usize::default()` for a non-initialized epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn active_validator_count(&self) -> usize {
|
pub fn active_validator_count(&self) -> usize {
|
||||||
self.shuffling.len()
|
self.shuffling.len()
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ impl CommitteeCache {
|
|||||||
///
|
///
|
||||||
/// Always returns `usize::default()` for a non-initialized epoch.
|
/// Always returns `usize::default()` for a non-initialized epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn epoch_committee_count(&self) -> usize {
|
pub fn epoch_committee_count(&self) -> usize {
|
||||||
self.committees_per_slot as usize * self.slots_per_epoch as usize
|
self.committees_per_slot as usize * self.slots_per_epoch as usize
|
||||||
}
|
}
|
||||||
@ -223,7 +223,7 @@ impl CommitteeCache {
|
|||||||
|
|
||||||
/// Returns a slice of `self.shuffling` that represents the `index`'th committee in the epoch.
|
/// Returns a slice of `self.shuffling` that represents the `index`'th committee in the epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn compute_committee(&self, index: usize) -> Option<&[usize]> {
|
fn compute_committee(&self, index: usize) -> Option<&[usize]> {
|
||||||
Some(&self.shuffling[self.compute_committee_range(index)?])
|
Some(&self.shuffling[self.compute_committee_range(index)?])
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ impl CommitteeCache {
|
|||||||
///
|
///
|
||||||
/// Will also return `None` if the index is out of bounds.
|
/// Will also return `None` if the index is out of bounds.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn compute_committee_range(&self, index: usize) -> Option<Range<usize>> {
|
fn compute_committee_range(&self, index: usize) -> Option<Range<usize>> {
|
||||||
let count = self.epoch_committee_count();
|
let count = self.epoch_committee_count();
|
||||||
if count == 0 || index >= count {
|
if count == 0 || index >= count {
|
||||||
@ -261,7 +261,7 @@ impl CommitteeCache {
|
|||||||
/// Returns a list of all `validators` indices where the validator is active at the given
|
/// Returns a list of all `validators` indices where the validator is active at the given
|
||||||
/// `epoch`.
|
/// `epoch`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> Vec<usize> {
|
pub fn get_active_validator_indices(validators: &[Validator], epoch: Epoch) -> Vec<usize> {
|
||||||
let mut active = Vec::with_capacity(validators.len());
|
let mut active = Vec::with_capacity(validators.len());
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ impl BeaconTreeHashCache {
|
|||||||
let mut hasher = MerkleHasher::with_leaves(NUM_BEACON_STATE_HASHING_FIELDS);
|
let mut hasher = MerkleHasher::with_leaves(NUM_BEACON_STATE_HASHING_FIELDS);
|
||||||
|
|
||||||
hasher.write(state.genesis_time.tree_hash_root().as_bytes())?;
|
hasher.write(state.genesis_time.tree_hash_root().as_bytes())?;
|
||||||
|
hasher.write(state.genesis_validators_root.tree_hash_root().as_bytes())?;
|
||||||
hasher.write(state.slot.tree_hash_root().as_bytes())?;
|
hasher.write(state.slot.tree_hash_root().as_bytes())?;
|
||||||
hasher.write(state.fork.tree_hash_root().as_bytes())?;
|
hasher.write(state.fork.tree_hash_root().as_bytes())?;
|
||||||
hasher.write(state.latest_block_header.tree_hash_root().as_bytes())?;
|
hasher.write(state.latest_block_header.tree_hash_root().as_bytes())?;
|
||||||
@ -153,6 +154,14 @@ impl BeaconTreeHashCache {
|
|||||||
|
|
||||||
hasher.finish().map_err(Into::into)
|
hasher.finish().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the cache and provides the root of the given `validators`.
|
||||||
|
pub fn recalculate_validators_tree_hash_root(
|
||||||
|
&mut self,
|
||||||
|
validators: &[Validator],
|
||||||
|
) -> Result<Hash256, Error> {
|
||||||
|
self.validators.recalculate_tree_hash_root(validators)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A specialized cache for computing the tree hash root of `state.validators`.
|
/// A specialized cache for computing the tree hash root of `state.validators`.
|
||||||
|
@ -3,6 +3,7 @@ use int_to_bytes::int_to_bytes4;
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use tree_hash::TreeHash;
|
||||||
use utils::{
|
use utils::{
|
||||||
fork_from_hex_str, fork_to_hex_str, u32_from_hex_str, u32_to_hex_str, u8_from_hex_str,
|
fork_from_hex_str, fork_to_hex_str, u32_from_hex_str, u32_to_hex_str, u8_from_hex_str,
|
||||||
u8_to_hex_str,
|
u8_to_hex_str,
|
||||||
@ -10,18 +11,21 @@ use utils::{
|
|||||||
|
|
||||||
/// Each of the BLS signature domains.
|
/// Each of the BLS signature domains.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
pub enum Domain {
|
pub enum Domain {
|
||||||
BeaconProposer,
|
BeaconProposer,
|
||||||
BeaconAttester,
|
BeaconAttester,
|
||||||
Randao,
|
Randao,
|
||||||
Deposit,
|
Deposit,
|
||||||
VoluntaryExit,
|
VoluntaryExit,
|
||||||
|
SelectionProof,
|
||||||
|
AggregateAndProof,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds all the "constants" for a BeaconChain.
|
/// Holds all the "constants" for a BeaconChain.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct ChainSpec {
|
pub struct ChainSpec {
|
||||||
@ -44,6 +48,9 @@ pub struct ChainSpec {
|
|||||||
pub shuffle_round_count: u8,
|
pub shuffle_round_count: u8,
|
||||||
pub min_genesis_active_validator_count: u64,
|
pub min_genesis_active_validator_count: u64,
|
||||||
pub min_genesis_time: u64,
|
pub min_genesis_time: u64,
|
||||||
|
pub hysteresis_quotient: u64,
|
||||||
|
pub hysteresis_downward_multiplier: u64,
|
||||||
|
pub hysteresis_upward_multiplier: u64,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gwei values
|
* Gwei values
|
||||||
@ -93,6 +100,8 @@ pub struct ChainSpec {
|
|||||||
domain_randao: u32,
|
domain_randao: u32,
|
||||||
domain_deposit: u32,
|
domain_deposit: u32,
|
||||||
domain_voluntary_exit: u32,
|
domain_voluntary_exit: u32,
|
||||||
|
domain_selection_proof: u32,
|
||||||
|
domain_aggregate_and_proof: u32,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fork choice
|
* Fork choice
|
||||||
@ -112,7 +121,7 @@ pub struct ChainSpec {
|
|||||||
impl ChainSpec {
|
impl ChainSpec {
|
||||||
/// Get the domain number, unmodified by the fork.
|
/// Get the domain number, unmodified by the fork.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_domain_constant(&self, domain: Domain) -> u32 {
|
pub fn get_domain_constant(&self, domain: Domain) -> u32 {
|
||||||
match domain {
|
match domain {
|
||||||
Domain::BeaconProposer => self.domain_beacon_proposer,
|
Domain::BeaconProposer => self.domain_beacon_proposer,
|
||||||
@ -120,15 +129,23 @@ impl ChainSpec {
|
|||||||
Domain::Randao => self.domain_randao,
|
Domain::Randao => self.domain_randao,
|
||||||
Domain::Deposit => self.domain_deposit,
|
Domain::Deposit => self.domain_deposit,
|
||||||
Domain::VoluntaryExit => self.domain_voluntary_exit,
|
Domain::VoluntaryExit => self.domain_voluntary_exit,
|
||||||
|
Domain::SelectionProof => self.domain_selection_proof,
|
||||||
|
Domain::AggregateAndProof => self.domain_aggregate_and_proof,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the domain number that represents the fork meta and signature domain.
|
/// Get the domain that represents the fork meta and signature domain.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_domain(&self, epoch: Epoch, domain: Domain, fork: &Fork) -> u64 {
|
pub fn get_domain(
|
||||||
|
&self,
|
||||||
|
epoch: Epoch,
|
||||||
|
domain: Domain,
|
||||||
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
) -> Hash256 {
|
||||||
let fork_version = fork.get_fork_version(epoch);
|
let fork_version = fork.get_fork_version(epoch);
|
||||||
self.compute_domain(domain, fork_version)
|
self.compute_domain(domain, fork_version, genesis_validators_root)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the domain for a deposit signature.
|
/// Get the domain for a deposit signature.
|
||||||
@ -136,29 +153,64 @@ impl ChainSpec {
|
|||||||
/// Deposits are valid across forks, thus the deposit domain is computed
|
/// Deposits are valid across forks, thus the deposit domain is computed
|
||||||
/// with the genesis fork version.
|
/// with the genesis fork version.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_deposit_domain(&self) -> u64 {
|
pub fn get_deposit_domain(&self) -> Hash256 {
|
||||||
self.compute_domain(Domain::Deposit, self.genesis_fork_version)
|
self.compute_domain(Domain::Deposit, self.genesis_fork_version, Hash256::zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the 32-byte fork data root for the `current_version` and `genesis_validators_root`.
|
||||||
|
///
|
||||||
|
/// This is used primarily in signature domains to avoid collisions across forks/chains.
|
||||||
|
///
|
||||||
|
/// Spec v0.11.1
|
||||||
|
pub fn compute_fork_data_root(
|
||||||
|
current_version: [u8; 4],
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
) -> Hash256 {
|
||||||
|
ForkData {
|
||||||
|
current_version,
|
||||||
|
genesis_validators_root,
|
||||||
|
}
|
||||||
|
.tree_hash_root()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the 4-byte fork digest for the `current_version` and `genesis_validators_root`.
|
||||||
|
///
|
||||||
|
/// This is a digest primarily used for domain separation on the p2p layer.
|
||||||
|
/// 4-bytes suffices for practical separation of forks/chains.
|
||||||
|
pub fn compute_fork_digest(
|
||||||
|
current_version: [u8; 4],
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
) -> [u8; 4] {
|
||||||
|
let mut result = [0; 4];
|
||||||
|
let root = Self::compute_fork_data_root(current_version, genesis_validators_root);
|
||||||
|
result.copy_from_slice(&root.as_bytes()[0..4]);
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute a domain by applying the given `fork_version`.
|
/// Compute a domain by applying the given `fork_version`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn compute_domain(&self, domain: Domain, fork_version: [u8; 4]) -> u64 {
|
pub fn compute_domain(
|
||||||
|
&self,
|
||||||
|
domain: Domain,
|
||||||
|
fork_version: [u8; 4],
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
) -> Hash256 {
|
||||||
let domain_constant = self.get_domain_constant(domain);
|
let domain_constant = self.get_domain_constant(domain);
|
||||||
|
|
||||||
let mut bytes: Vec<u8> = int_to_bytes4(domain_constant);
|
let mut domain = [0; 32];
|
||||||
bytes.append(&mut fork_version.to_vec());
|
domain[0..4].copy_from_slice(&int_to_bytes4(domain_constant));
|
||||||
|
domain[4..].copy_from_slice(
|
||||||
|
&Self::compute_fork_data_root(fork_version, genesis_validators_root)[..28],
|
||||||
|
);
|
||||||
|
|
||||||
let mut fork_and_domain = [0; 8];
|
Hash256::from(domain)
|
||||||
fork_and_domain.copy_from_slice(&bytes);
|
|
||||||
|
|
||||||
u64::from_le_bytes(fork_and_domain)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `ChainSpec` compatible with the Ethereum Foundation specification.
|
/// Returns a `ChainSpec` compatible with the Ethereum Foundation specification.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn mainnet() -> Self {
|
pub fn mainnet() -> Self {
|
||||||
Self {
|
Self {
|
||||||
/*
|
/*
|
||||||
@ -179,6 +231,9 @@ impl ChainSpec {
|
|||||||
shuffle_round_count: 90,
|
shuffle_round_count: 90,
|
||||||
min_genesis_active_validator_count: 16_384,
|
min_genesis_active_validator_count: 16_384,
|
||||||
min_genesis_time: 1_578_009_600, // Jan 3, 2020
|
min_genesis_time: 1_578_009_600, // Jan 3, 2020
|
||||||
|
hysteresis_quotient: 4,
|
||||||
|
hysteresis_downward_multiplier: 1,
|
||||||
|
hysteresis_upward_multiplier: 5,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gwei values
|
* Gwei values
|
||||||
@ -223,6 +278,8 @@ impl ChainSpec {
|
|||||||
domain_randao: 2,
|
domain_randao: 2,
|
||||||
domain_deposit: 3,
|
domain_deposit: 3,
|
||||||
domain_voluntary_exit: 4,
|
domain_voluntary_exit: 4,
|
||||||
|
domain_selection_proof: 5,
|
||||||
|
domain_aggregate_and_proof: 6,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fork choice
|
* Fork choice
|
||||||
@ -245,7 +302,7 @@ impl ChainSpec {
|
|||||||
|
|
||||||
/// Ethereum Foundation minimal spec, as defined in the eth2.0-specs repo.
|
/// Ethereum Foundation minimal spec, as defined in the eth2.0-specs repo.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn minimal() -> Self {
|
pub fn minimal() -> Self {
|
||||||
// Note: bootnodes to be updated when static nodes exist.
|
// Note: bootnodes to be updated when static nodes exist.
|
||||||
let boot_nodes = vec![];
|
let boot_nodes = vec![];
|
||||||
@ -257,6 +314,7 @@ impl ChainSpec {
|
|||||||
min_genesis_active_validator_count: 64,
|
min_genesis_active_validator_count: 64,
|
||||||
eth1_follow_distance: 16,
|
eth1_follow_distance: 16,
|
||||||
genesis_fork_version: [0x00, 0x00, 0x00, 0x01],
|
genesis_fork_version: [0x00, 0x00, 0x00, 0x01],
|
||||||
|
persistent_committee_period: 128,
|
||||||
min_genesis_delay: 300,
|
min_genesis_delay: 300,
|
||||||
milliseconds_per_slot: 6_000,
|
milliseconds_per_slot: 6_000,
|
||||||
network_id: 2, // lighthouse testnet network id
|
network_id: 2, // lighthouse testnet network id
|
||||||
@ -291,7 +349,6 @@ impl Default for ChainSpec {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use int_to_bytes::int_to_bytes8;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mainnet_spec_can_be_constructed() {
|
fn test_mainnet_spec_can_be_constructed() {
|
||||||
@ -299,19 +356,27 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_domain(domain_type: Domain, raw_domain: u32, spec: &ChainSpec) {
|
fn test_domain(domain_type: Domain, raw_domain: u32, spec: &ChainSpec) {
|
||||||
|
let previous_version = [0, 0, 0, 1];
|
||||||
|
let current_version = [0, 0, 0, 2];
|
||||||
|
let genesis_validators_root = Hash256::from_low_u64_le(77);
|
||||||
|
let fork_epoch = Epoch::new(1024);
|
||||||
let fork = Fork {
|
let fork = Fork {
|
||||||
previous_version: spec.genesis_fork_version,
|
previous_version,
|
||||||
current_version: spec.genesis_fork_version,
|
current_version,
|
||||||
epoch: MinimalEthSpec::genesis_epoch(),
|
epoch: fork_epoch,
|
||||||
};
|
};
|
||||||
let epoch = Epoch::new(0);
|
|
||||||
|
|
||||||
let domain = spec.get_domain(epoch, domain_type, &fork);
|
for (epoch, version) in vec![
|
||||||
|
(fork_epoch - 1, previous_version),
|
||||||
|
(fork_epoch, current_version),
|
||||||
|
(fork_epoch + 1, current_version),
|
||||||
|
] {
|
||||||
|
let domain1 = spec.get_domain(epoch, domain_type, &fork, genesis_validators_root);
|
||||||
|
let domain2 = spec.compute_domain(domain_type, version, genesis_validators_root);
|
||||||
|
|
||||||
let mut expected = int_to_bytes4(raw_domain);
|
assert_eq!(domain1, domain2);
|
||||||
expected.append(&mut fork.get_fork_version(epoch).to_vec());
|
assert_eq!(&domain1.as_bytes()[0..4], &int_to_bytes4(raw_domain)[..]);
|
||||||
|
}
|
||||||
assert_eq!(int_to_bytes8(domain), expected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -323,18 +388,25 @@ mod tests {
|
|||||||
test_domain(Domain::Randao, spec.domain_randao, &spec);
|
test_domain(Domain::Randao, spec.domain_randao, &spec);
|
||||||
test_domain(Domain::Deposit, spec.domain_deposit, &spec);
|
test_domain(Domain::Deposit, spec.domain_deposit, &spec);
|
||||||
test_domain(Domain::VoluntaryExit, spec.domain_voluntary_exit, &spec);
|
test_domain(Domain::VoluntaryExit, spec.domain_voluntary_exit, &spec);
|
||||||
|
test_domain(Domain::SelectionProof, spec.domain_selection_proof, &spec);
|
||||||
|
test_domain(
|
||||||
|
Domain::AggregateAndProof,
|
||||||
|
spec.domain_aggregate_and_proof,
|
||||||
|
&spec,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Union of a ChainSpec struct and an EthSpec struct that holds constants used for the configs
|
/// Union of a ChainSpec struct and an EthSpec struct that holds constants used for the configs
|
||||||
/// from the Ethereum 2 specs repo (https://github.com/ethereum/eth2.0-specs/tree/dev/configs)
|
/// from the Ethereum 2 specs repo (https://github.com/ethereum/eth2.0-specs/tree/dev/configs)
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Doesn't include fields of the YAML that we don't need yet (e.g. Phase 1 stuff).
|
||||||
|
///
|
||||||
|
/// Spec v0.11.1
|
||||||
// Yaml Config is declared here in order to access domain fields of ChainSpec which are private.
|
// Yaml Config is declared here in order to access domain fields of ChainSpec which are private.
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||||
#[serde(rename_all = "UPPERCASE")]
|
#[serde(rename_all = "UPPERCASE")]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct YamlConfig {
|
pub struct YamlConfig {
|
||||||
// ChainSpec
|
// ChainSpec
|
||||||
far_future_epoch: u64,
|
far_future_epoch: u64,
|
||||||
@ -352,6 +424,9 @@ pub struct YamlConfig {
|
|||||||
max_effective_balance: u64,
|
max_effective_balance: u64,
|
||||||
ejection_balance: u64,
|
ejection_balance: u64,
|
||||||
effective_balance_increment: u64,
|
effective_balance_increment: u64,
|
||||||
|
hysteresis_quotient: u64,
|
||||||
|
hysteresis_downward_multiplier: u64,
|
||||||
|
hysteresis_upward_multiplier: u64,
|
||||||
genesis_slot: u64,
|
genesis_slot: u64,
|
||||||
#[serde(
|
#[serde(
|
||||||
serialize_with = "fork_to_hex_str",
|
serialize_with = "fork_to_hex_str",
|
||||||
@ -403,12 +478,22 @@ pub struct YamlConfig {
|
|||||||
deserialize_with = "u32_from_hex_str",
|
deserialize_with = "u32_from_hex_str",
|
||||||
serialize_with = "u32_to_hex_str"
|
serialize_with = "u32_to_hex_str"
|
||||||
)]
|
)]
|
||||||
|
domain_selection_proof: u32,
|
||||||
|
#[serde(
|
||||||
|
deserialize_with = "u32_from_hex_str",
|
||||||
|
serialize_with = "u32_to_hex_str"
|
||||||
|
)]
|
||||||
|
domain_aggregate_and_proof: u32,
|
||||||
|
#[serde(
|
||||||
|
deserialize_with = "u32_from_hex_str",
|
||||||
|
serialize_with = "u32_to_hex_str"
|
||||||
|
)]
|
||||||
// EthSpec
|
// EthSpec
|
||||||
justification_bits_length: u32,
|
justification_bits_length: u32,
|
||||||
max_validators_per_committee: u32,
|
max_validators_per_committee: u32,
|
||||||
genesis_epoch: Epoch,
|
genesis_epoch: Epoch,
|
||||||
slots_per_epoch: u64,
|
slots_per_epoch: u64,
|
||||||
slots_per_eth1_voting_period: usize,
|
epochs_per_eth1_voting_period: u64,
|
||||||
slots_per_historical_root: usize,
|
slots_per_historical_root: usize,
|
||||||
epochs_per_historical_vector: usize,
|
epochs_per_historical_vector: usize,
|
||||||
epochs_per_slashings_vector: usize,
|
epochs_per_slashings_vector: usize,
|
||||||
@ -426,34 +511,6 @@ pub struct YamlConfig {
|
|||||||
random_subnets_per_validator: u64,
|
random_subnets_per_validator: u64,
|
||||||
epochs_per_random_subnet_subscription: u64,
|
epochs_per_random_subnet_subscription: u64,
|
||||||
seconds_per_eth1_block: u64,
|
seconds_per_eth1_block: u64,
|
||||||
|
|
||||||
// Deposit Contract (unused)
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
deposit_contract_address: String,
|
|
||||||
|
|
||||||
// Phase 1
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
epochs_per_custody_period: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
custody_period_to_randao_padding: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
shard_slots_per_beacon_slot: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
epochs_per_shard_period: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
phase_1_fork_epoch: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
phase_1_fork_slot: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
domain_custody_bit_challenge: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
domain_shard_proposer: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
domain_shard_attester: u32,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
max_epochs_per_crosslink: u64,
|
|
||||||
#[serde(skip_serializing)]
|
|
||||||
early_derived_secret_penalty_max_future_epochs: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for YamlConfig {
|
impl Default for YamlConfig {
|
||||||
@ -463,7 +520,7 @@ impl Default for YamlConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
impl YamlConfig {
|
impl YamlConfig {
|
||||||
pub fn from_spec<T: EthSpec>(spec: &ChainSpec) -> Self {
|
pub fn from_spec<T: EthSpec>(spec: &ChainSpec) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -483,6 +540,9 @@ impl YamlConfig {
|
|||||||
max_effective_balance: spec.max_effective_balance,
|
max_effective_balance: spec.max_effective_balance,
|
||||||
ejection_balance: spec.ejection_balance,
|
ejection_balance: spec.ejection_balance,
|
||||||
effective_balance_increment: spec.effective_balance_increment,
|
effective_balance_increment: spec.effective_balance_increment,
|
||||||
|
hysteresis_quotient: spec.hysteresis_quotient,
|
||||||
|
hysteresis_downward_multiplier: spec.hysteresis_downward_multiplier,
|
||||||
|
hysteresis_upward_multiplier: spec.hysteresis_upward_multiplier,
|
||||||
genesis_slot: spec.genesis_slot.into(),
|
genesis_slot: spec.genesis_slot.into(),
|
||||||
bls_withdrawal_prefix: spec.bls_withdrawal_prefix_byte,
|
bls_withdrawal_prefix: spec.bls_withdrawal_prefix_byte,
|
||||||
seconds_per_slot: spec.milliseconds_per_slot / 1000,
|
seconds_per_slot: spec.milliseconds_per_slot / 1000,
|
||||||
@ -504,13 +564,15 @@ impl YamlConfig {
|
|||||||
domain_randao: spec.domain_randao,
|
domain_randao: spec.domain_randao,
|
||||||
domain_deposit: spec.domain_deposit,
|
domain_deposit: spec.domain_deposit,
|
||||||
domain_voluntary_exit: spec.domain_voluntary_exit,
|
domain_voluntary_exit: spec.domain_voluntary_exit,
|
||||||
|
domain_selection_proof: spec.domain_selection_proof,
|
||||||
|
domain_aggregate_and_proof: spec.domain_aggregate_and_proof,
|
||||||
|
|
||||||
// EthSpec
|
// EthSpec
|
||||||
justification_bits_length: T::JustificationBitsLength::to_u32(),
|
justification_bits_length: T::JustificationBitsLength::to_u32(),
|
||||||
max_validators_per_committee: T::MaxValidatorsPerCommittee::to_u32(),
|
max_validators_per_committee: T::MaxValidatorsPerCommittee::to_u32(),
|
||||||
genesis_epoch: T::genesis_epoch(),
|
genesis_epoch: T::genesis_epoch(),
|
||||||
slots_per_epoch: T::slots_per_epoch(),
|
slots_per_epoch: T::slots_per_epoch(),
|
||||||
slots_per_eth1_voting_period: T::slots_per_eth1_voting_period(),
|
epochs_per_eth1_voting_period: T::EpochsPerEth1VotingPeriod::to_u64(),
|
||||||
slots_per_historical_root: T::slots_per_historical_root(),
|
slots_per_historical_root: T::slots_per_historical_root(),
|
||||||
epochs_per_historical_vector: T::epochs_per_historical_vector(),
|
epochs_per_historical_vector: T::epochs_per_historical_vector(),
|
||||||
epochs_per_slashings_vector: T::EpochsPerSlashingsVector::to_usize(),
|
epochs_per_slashings_vector: T::EpochsPerSlashingsVector::to_usize(),
|
||||||
@ -528,22 +590,6 @@ impl YamlConfig {
|
|||||||
random_subnets_per_validator: 0,
|
random_subnets_per_validator: 0,
|
||||||
epochs_per_random_subnet_subscription: 0,
|
epochs_per_random_subnet_subscription: 0,
|
||||||
seconds_per_eth1_block: spec.seconds_per_eth1_block,
|
seconds_per_eth1_block: spec.seconds_per_eth1_block,
|
||||||
|
|
||||||
// Deposit Contract (unused)
|
|
||||||
deposit_contract_address: String::new(),
|
|
||||||
|
|
||||||
// Phase 1
|
|
||||||
epochs_per_custody_period: 0,
|
|
||||||
custody_period_to_randao_padding: 0,
|
|
||||||
shard_slots_per_beacon_slot: 0,
|
|
||||||
epochs_per_shard_period: 0,
|
|
||||||
phase_1_fork_epoch: 0,
|
|
||||||
phase_1_fork_slot: 0,
|
|
||||||
domain_custody_bit_challenge: 0,
|
|
||||||
domain_shard_proposer: 0,
|
|
||||||
domain_shard_attester: 0,
|
|
||||||
max_epochs_per_crosslink: 0,
|
|
||||||
early_derived_secret_penalty_max_future_epochs: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,7 +606,7 @@ impl YamlConfig {
|
|||||||
|| self.max_validators_per_committee != T::MaxValidatorsPerCommittee::to_u32()
|
|| self.max_validators_per_committee != T::MaxValidatorsPerCommittee::to_u32()
|
||||||
|| self.genesis_epoch != T::genesis_epoch()
|
|| self.genesis_epoch != T::genesis_epoch()
|
||||||
|| self.slots_per_epoch != T::slots_per_epoch()
|
|| self.slots_per_epoch != T::slots_per_epoch()
|
||||||
|| self.slots_per_eth1_voting_period != T::slots_per_eth1_voting_period()
|
|| self.epochs_per_eth1_voting_period != T::EpochsPerEth1VotingPeriod::to_u64()
|
||||||
|| self.slots_per_historical_root != T::slots_per_historical_root()
|
|| self.slots_per_historical_root != T::slots_per_historical_root()
|
||||||
|| self.epochs_per_historical_vector != T::epochs_per_historical_vector()
|
|| self.epochs_per_historical_vector != T::epochs_per_historical_vector()
|
||||||
|| self.epochs_per_slashings_vector != T::EpochsPerSlashingsVector::to_usize()
|
|| self.epochs_per_slashings_vector != T::EpochsPerSlashingsVector::to_usize()
|
||||||
@ -589,6 +635,9 @@ impl YamlConfig {
|
|||||||
min_deposit_amount: self.min_deposit_amount,
|
min_deposit_amount: self.min_deposit_amount,
|
||||||
min_genesis_delay: self.min_genesis_delay,
|
min_genesis_delay: self.min_genesis_delay,
|
||||||
max_effective_balance: self.max_effective_balance,
|
max_effective_balance: self.max_effective_balance,
|
||||||
|
hysteresis_quotient: self.hysteresis_quotient,
|
||||||
|
hysteresis_downward_multiplier: self.hysteresis_downward_multiplier,
|
||||||
|
hysteresis_upward_multiplier: self.hysteresis_upward_multiplier,
|
||||||
ejection_balance: self.ejection_balance,
|
ejection_balance: self.ejection_balance,
|
||||||
effective_balance_increment: self.effective_balance_increment,
|
effective_balance_increment: self.effective_balance_increment,
|
||||||
genesis_slot: Slot::from(self.genesis_slot),
|
genesis_slot: Slot::from(self.genesis_slot),
|
||||||
@ -608,6 +657,7 @@ impl YamlConfig {
|
|||||||
inactivity_penalty_quotient: self.inactivity_penalty_quotient,
|
inactivity_penalty_quotient: self.inactivity_penalty_quotient,
|
||||||
min_slashing_penalty_quotient: self.min_slashing_penalty_quotient,
|
min_slashing_penalty_quotient: self.min_slashing_penalty_quotient,
|
||||||
domain_beacon_proposer: self.domain_beacon_proposer,
|
domain_beacon_proposer: self.domain_beacon_proposer,
|
||||||
|
domain_beacon_attester: self.domain_beacon_attester,
|
||||||
domain_randao: self.domain_randao,
|
domain_randao: self.domain_randao,
|
||||||
domain_deposit: self.domain_deposit,
|
domain_deposit: self.domain_deposit,
|
||||||
domain_voluntary_exit: self.domain_voluntary_exit,
|
domain_voluntary_exit: self.domain_voluntary_exit,
|
||||||
|
@ -7,7 +7,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// Casper FFG checkpoint, used in attestations.
|
/// Casper FFG checkpoint, used in attestations.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
Clone,
|
Clone,
|
||||||
|
@ -11,7 +11,7 @@ pub const DEPOSIT_TREE_DEPTH: usize = 32;
|
|||||||
|
|
||||||
/// A deposit to potentially become a beacon chain validator.
|
/// A deposit to potentially become a beacon chain validator.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct Deposit {
|
pub struct Deposit {
|
||||||
pub proof: FixedVector<Hash256, U33>,
|
pub proof: FixedVector<Hash256, U33>,
|
||||||
|
@ -9,7 +9,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// The data supplied by the user to the deposit contract.
|
/// The data supplied by the user to the deposit contract.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct DepositData {
|
pub struct DepositData {
|
||||||
pub pubkey: PublicKeyBytes,
|
pub pubkey: PublicKeyBytes,
|
||||||
@ -21,7 +21,7 @@ pub struct DepositData {
|
|||||||
impl DepositData {
|
impl DepositData {
|
||||||
/// Create a `DepositMessage` corresponding to this `DepositData`, for signature verification.
|
/// Create a `DepositMessage` corresponding to this `DepositData`, for signature verification.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn as_deposit_message(&self) -> DepositMessage {
|
pub fn as_deposit_message(&self) -> DepositMessage {
|
||||||
DepositMessage {
|
DepositMessage {
|
||||||
pubkey: self.pubkey.clone(),
|
pubkey: self.pubkey.clone(),
|
||||||
@ -32,7 +32,7 @@ impl DepositData {
|
|||||||
|
|
||||||
/// Generate the signature for a given DepositData details.
|
/// Generate the signature for a given DepositData details.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn create_signature(&self, secret_key: &SecretKey, spec: &ChainSpec) -> SignatureBytes {
|
pub fn create_signature(&self, secret_key: &SecretKey, spec: &ChainSpec) -> SignatureBytes {
|
||||||
let domain = spec.get_deposit_domain();
|
let domain = spec.get_deposit_domain();
|
||||||
let msg = self.as_deposit_message().signing_root(domain);
|
let msg = self.as_deposit_message().signing_root(domain);
|
||||||
|
@ -9,7 +9,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// The data supplied by the user to the deposit contract.
|
/// The data supplied by the user to the deposit contract.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct DepositMessage {
|
pub struct DepositMessage {
|
||||||
pub pubkey: PublicKeyBytes,
|
pub pubkey: PublicKeyBytes,
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// Contains data obtained from the Eth1 chain.
|
/// Contains data obtained from the Eth1 chain.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use ssz_types::typenum::{
|
use ssz_types::typenum::{
|
||||||
Unsigned, U0, U1, U1024, U1099511627776, U128, U16, U16777216, U2048, U32, U4, U4096, U64,
|
Unsigned, U0, U1, U1024, U1099511627776, U128, U16, U16777216, U2, U2048, U32, U4, U4096, U64,
|
||||||
U65536, U8, U8192,
|
U65536, U8, U8192,
|
||||||
};
|
};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@ -20,7 +20,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq {
|
|||||||
* Time parameters
|
* Time parameters
|
||||||
*/
|
*/
|
||||||
type SlotsPerEpoch: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type SlotsPerEpoch: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
type SlotsPerEth1VotingPeriod: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type EpochsPerEth1VotingPeriod: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
type SlotsPerHistoricalRoot: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type SlotsPerHistoricalRoot: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
/*
|
/*
|
||||||
* State list lengths
|
* State list lengths
|
||||||
@ -43,9 +43,13 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq {
|
|||||||
/// The length of the `{previous,current}_epoch_attestations` lists.
|
/// The length of the `{previous,current}_epoch_attestations` lists.
|
||||||
///
|
///
|
||||||
/// Must be set to `MaxAttestations * SlotsPerEpoch`
|
/// Must be set to `MaxAttestations * SlotsPerEpoch`
|
||||||
// NOTE: we could safely instantiate this by using type-level arithmetic, but doing
|
// NOTE: we could safely instantiate these by using type-level arithmetic, but doing
|
||||||
// so adds ~25s to the time required to type-check this crate
|
// so adds ~25s to the time required to type-check this crate
|
||||||
type MaxPendingAttestations: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
type MaxPendingAttestations: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
|
/// The length of `eth1_data_votes`.
|
||||||
|
///
|
||||||
|
/// Must be set to `EpochsPerEth1VotingPeriod * SlotsPerEpoch`
|
||||||
|
type SlotsPerEth1VotingPeriod: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||||
|
|
||||||
fn default_spec() -> ChainSpec;
|
fn default_spec() -> ChainSpec;
|
||||||
|
|
||||||
@ -58,7 +62,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq {
|
|||||||
/// Note: the number of committees per slot is constant in each epoch, and depends only on
|
/// Note: the number of committees per slot is constant in each epoch, and depends only on
|
||||||
/// the `active_validator_count` during the slot's epoch.
|
/// the `active_validator_count` during the slot's epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn get_committee_count_per_slot(active_validator_count: usize, spec: &ChainSpec) -> usize {
|
fn get_committee_count_per_slot(active_validator_count: usize, spec: &ChainSpec) -> usize {
|
||||||
let slots_per_epoch = Self::SlotsPerEpoch::to_usize();
|
let slots_per_epoch = Self::SlotsPerEpoch::to_usize();
|
||||||
|
|
||||||
@ -82,28 +86,28 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq {
|
|||||||
|
|
||||||
/// Returns the `SLOTS_PER_EPOCH` constant for this specification.
|
/// Returns the `SLOTS_PER_EPOCH` constant for this specification.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn slots_per_epoch() -> u64 {
|
fn slots_per_epoch() -> u64 {
|
||||||
Self::SlotsPerEpoch::to_u64()
|
Self::SlotsPerEpoch::to_u64()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `SLOTS_PER_HISTORICAL_ROOT` constant for this specification.
|
/// Returns the `SLOTS_PER_HISTORICAL_ROOT` constant for this specification.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn slots_per_historical_root() -> usize {
|
fn slots_per_historical_root() -> usize {
|
||||||
Self::SlotsPerHistoricalRoot::to_usize()
|
Self::SlotsPerHistoricalRoot::to_usize()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `EPOCHS_PER_HISTORICAL_VECTOR` constant for this specification.
|
/// Returns the `EPOCHS_PER_HISTORICAL_VECTOR` constant for this specification.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn epochs_per_historical_vector() -> usize {
|
fn epochs_per_historical_vector() -> usize {
|
||||||
Self::EpochsPerHistoricalVector::to_usize()
|
Self::EpochsPerHistoricalVector::to_usize()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `SLOTS_PER_ETH1_VOTING_PERIOD` constant for this specification.
|
/// Returns the `SLOTS_PER_ETH1_VOTING_PERIOD` constant for this specification.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
fn slots_per_eth1_voting_period() -> usize {
|
fn slots_per_eth1_voting_period() -> usize {
|
||||||
Self::SlotsPerEth1VotingPeriod::to_usize()
|
Self::SlotsPerEth1VotingPeriod::to_usize()
|
||||||
}
|
}
|
||||||
@ -119,7 +123,7 @@ macro_rules! params_from_eth_spec {
|
|||||||
|
|
||||||
/// Ethereum Foundation specifications.
|
/// Ethereum Foundation specifications.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct MainnetEthSpec;
|
pub struct MainnetEthSpec;
|
||||||
|
|
||||||
@ -128,7 +132,7 @@ impl EthSpec for MainnetEthSpec {
|
|||||||
type MaxValidatorsPerCommittee = U2048;
|
type MaxValidatorsPerCommittee = U2048;
|
||||||
type GenesisEpoch = U0;
|
type GenesisEpoch = U0;
|
||||||
type SlotsPerEpoch = U32;
|
type SlotsPerEpoch = U32;
|
||||||
type SlotsPerEth1VotingPeriod = U1024;
|
type EpochsPerEth1VotingPeriod = U32;
|
||||||
type SlotsPerHistoricalRoot = U8192;
|
type SlotsPerHistoricalRoot = U8192;
|
||||||
type EpochsPerHistoricalVector = U65536;
|
type EpochsPerHistoricalVector = U65536;
|
||||||
type EpochsPerSlashingsVector = U8192;
|
type EpochsPerSlashingsVector = U8192;
|
||||||
@ -140,6 +144,7 @@ impl EthSpec for MainnetEthSpec {
|
|||||||
type MaxDeposits = U16;
|
type MaxDeposits = U16;
|
||||||
type MaxVoluntaryExits = U16;
|
type MaxVoluntaryExits = U16;
|
||||||
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
|
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
|
||||||
|
type SlotsPerEth1VotingPeriod = U1024; // 32 epochs * 32 slots per epoch
|
||||||
|
|
||||||
fn default_spec() -> ChainSpec {
|
fn default_spec() -> ChainSpec {
|
||||||
ChainSpec::mainnet()
|
ChainSpec::mainnet()
|
||||||
@ -150,17 +155,18 @@ pub type FoundationBeaconState = BeaconState<MainnetEthSpec>;
|
|||||||
|
|
||||||
/// Ethereum Foundation minimal spec, as defined in the eth2.0-specs repo.
|
/// Ethereum Foundation minimal spec, as defined in the eth2.0-specs repo.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct MinimalEthSpec;
|
pub struct MinimalEthSpec;
|
||||||
|
|
||||||
impl EthSpec for MinimalEthSpec {
|
impl EthSpec for MinimalEthSpec {
|
||||||
type SlotsPerEpoch = U8;
|
type SlotsPerEpoch = U8;
|
||||||
type SlotsPerEth1VotingPeriod = U16;
|
type EpochsPerEth1VotingPeriod = U2;
|
||||||
type SlotsPerHistoricalRoot = U64;
|
type SlotsPerHistoricalRoot = U64;
|
||||||
type EpochsPerHistoricalVector = U64;
|
type EpochsPerHistoricalVector = U64;
|
||||||
type EpochsPerSlashingsVector = U64;
|
type EpochsPerSlashingsVector = U64;
|
||||||
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
|
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
|
||||||
|
type SlotsPerEth1VotingPeriod = U16; // 2 epochs * 8 slots per epoch
|
||||||
|
|
||||||
params_from_eth_spec!(MainnetEthSpec {
|
params_from_eth_spec!(MainnetEthSpec {
|
||||||
JustificationBitsLength,
|
JustificationBitsLength,
|
||||||
@ -188,11 +194,12 @@ pub struct InteropEthSpec;
|
|||||||
|
|
||||||
impl EthSpec for InteropEthSpec {
|
impl EthSpec for InteropEthSpec {
|
||||||
type SlotsPerEpoch = U8;
|
type SlotsPerEpoch = U8;
|
||||||
|
type EpochsPerEth1VotingPeriod = U2;
|
||||||
type SlotsPerHistoricalRoot = U64;
|
type SlotsPerHistoricalRoot = U64;
|
||||||
type SlotsPerEth1VotingPeriod = U16;
|
|
||||||
type EpochsPerHistoricalVector = U64;
|
type EpochsPerHistoricalVector = U64;
|
||||||
type EpochsPerSlashingsVector = U64;
|
type EpochsPerSlashingsVector = U64;
|
||||||
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
|
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
|
||||||
|
type SlotsPerEth1VotingPeriod = U16; // 2 epochs * 8 slots per epoch
|
||||||
|
|
||||||
params_from_eth_spec!(MainnetEthSpec {
|
params_from_eth_spec!(MainnetEthSpec {
|
||||||
JustificationBitsLength,
|
JustificationBitsLength,
|
||||||
|
@ -9,7 +9,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// Specifies a fork of the `BeaconChain`, to prevent replay attacks.
|
/// Specifies a fork of the `BeaconChain`, to prevent replay attacks.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
||||||
)]
|
)]
|
||||||
@ -30,7 +30,7 @@ pub struct Fork {
|
|||||||
impl Fork {
|
impl Fork {
|
||||||
/// Return the fork version of the given ``epoch``.
|
/// Return the fork version of the given ``epoch``.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn get_fork_version(&self, epoch: Epoch) -> [u8; 4] {
|
pub fn get_fork_version(&self, epoch: Epoch) -> [u8; 4] {
|
||||||
if epoch < self.epoch {
|
if epoch < self.epoch {
|
||||||
return self.previous_version;
|
return self.previous_version;
|
||||||
|
32
eth2/types/src/fork_data.rs
Normal file
32
eth2/types/src/fork_data.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use crate::test_utils::TestRandom;
|
||||||
|
use crate::utils::{fork_from_hex_str, fork_to_hex_str};
|
||||||
|
use crate::{Hash256, SignedRoot};
|
||||||
|
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use ssz_derive::{Decode, Encode};
|
||||||
|
use test_random_derive::TestRandom;
|
||||||
|
use tree_hash_derive::TreeHash;
|
||||||
|
|
||||||
|
/// Specifies a fork of the `BeaconChain`, to prevent replay attacks.
|
||||||
|
///
|
||||||
|
/// Spec v0.11.1
|
||||||
|
#[derive(
|
||||||
|
Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
||||||
|
)]
|
||||||
|
pub struct ForkData {
|
||||||
|
#[serde(
|
||||||
|
serialize_with = "fork_to_hex_str",
|
||||||
|
deserialize_with = "fork_from_hex_str"
|
||||||
|
)]
|
||||||
|
pub current_version: [u8; 4],
|
||||||
|
pub genesis_validators_root: Hash256,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SignedRoot for ForkData {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
ssz_and_tree_hash_tests!(ForkData);
|
||||||
|
}
|
@ -9,7 +9,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// Historical block and state roots.
|
/// Historical block and state roots.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct HistoricalBatch<T: EthSpec> {
|
pub struct HistoricalBatch<T: EthSpec> {
|
||||||
pub block_roots: FixedVector<Hash256, T::SlotsPerHistoricalRoot>,
|
pub block_roots: FixedVector<Hash256, T::SlotsPerHistoricalRoot>,
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
///
|
///
|
||||||
/// To be included in an `AttesterSlashing`.
|
/// To be included in an `AttesterSlashing`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
#[serde(bound = "T: EthSpec")]
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct IndexedAttestation<T: EthSpec> {
|
pub struct IndexedAttestation<T: EthSpec> {
|
||||||
@ -21,14 +21,14 @@ pub struct IndexedAttestation<T: EthSpec> {
|
|||||||
impl<T: EthSpec> IndexedAttestation<T> {
|
impl<T: EthSpec> IndexedAttestation<T> {
|
||||||
/// 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.10.1
|
/// Spec v0.11.1
|
||||||
pub fn is_double_vote(&self, other: &Self) -> bool {
|
pub fn is_double_vote(&self, other: &Self) -> bool {
|
||||||
self.data.target.epoch == other.data.target.epoch && self.data != other.data
|
self.data.target.epoch == other.data.target.epoch && self.data != other.data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
|
/// Check if ``attestation_data_1`` surrounds ``attestation_data_2``.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn is_surround_vote(&self, other: &Self) -> bool {
|
pub fn is_surround_vote(&self, other: &Self) -> bool {
|
||||||
self.data.source.epoch < other.data.source.epoch
|
self.data.source.epoch < other.data.source.epoch
|
||||||
&& other.data.target.epoch < self.data.target.epoch
|
&& other.data.target.epoch < self.data.target.epoch
|
||||||
|
@ -23,6 +23,7 @@ pub mod deposit_message;
|
|||||||
pub mod eth1_data;
|
pub mod eth1_data;
|
||||||
pub mod eth_spec;
|
pub mod eth_spec;
|
||||||
pub mod fork;
|
pub mod fork;
|
||||||
|
pub mod fork_data;
|
||||||
pub mod free_attestation;
|
pub mod free_attestation;
|
||||||
pub mod historical_batch;
|
pub mod historical_batch;
|
||||||
pub mod indexed_attestation;
|
pub mod indexed_attestation;
|
||||||
@ -59,6 +60,7 @@ pub use crate::deposit_data::DepositData;
|
|||||||
pub use crate::deposit_message::DepositMessage;
|
pub use crate::deposit_message::DepositMessage;
|
||||||
pub use crate::eth1_data::Eth1Data;
|
pub use crate::eth1_data::Eth1Data;
|
||||||
pub use crate::fork::Fork;
|
pub use crate::fork::Fork;
|
||||||
|
pub use crate::fork_data::ForkData;
|
||||||
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::indexed_attestation::IndexedAttestation;
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::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.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct PendingAttestation<T: EthSpec> {
|
pub struct PendingAttestation<T: EthSpec> {
|
||||||
pub aggregation_bits: BitList<T::MaxValidatorsPerCommittee>,
|
pub aggregation_bits: BitList<T::MaxValidatorsPerCommittee>,
|
||||||
|
@ -8,10 +8,9 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// Two conflicting proposals from the same proposer (validator).
|
/// Two conflicting proposals from the same proposer (validator).
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct ProposerSlashing {
|
pub struct ProposerSlashing {
|
||||||
pub proposer_index: u64,
|
|
||||||
pub signed_header_1: SignedBeaconBlockHeader,
|
pub signed_header_1: SignedBeaconBlockHeader,
|
||||||
pub signed_header_2: SignedBeaconBlockHeader,
|
pub signed_header_2: SignedBeaconBlockHeader,
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ pub enum Error {
|
|||||||
/// Defines the epochs relative to some epoch. Most useful when referring to the committees prior
|
/// Defines the epochs relative to some epoch. Most useful when referring to the committees prior
|
||||||
/// to and following some epoch.
|
/// to and following some epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
pub enum RelativeEpoch {
|
pub enum RelativeEpoch {
|
||||||
/// The prior epoch.
|
/// The prior epoch.
|
||||||
@ -23,7 +23,7 @@ pub enum RelativeEpoch {
|
|||||||
impl RelativeEpoch {
|
impl RelativeEpoch {
|
||||||
/// Returns the `epoch` that `self` refers to, with respect to the `base` epoch.
|
/// Returns the `epoch` that `self` refers to, with respect to the `base` epoch.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn into_epoch(self, base: Epoch) -> Epoch {
|
pub fn into_epoch(self, base: Epoch) -> Epoch {
|
||||||
match self {
|
match self {
|
||||||
// Due to saturating nature of epoch, check for current first.
|
// Due to saturating nature of epoch, check for current first.
|
||||||
@ -40,7 +40,7 @@ impl RelativeEpoch {
|
|||||||
/// - `EpochTooLow` when `other` is more than 1 prior to `base`.
|
/// - `EpochTooLow` when `other` is more than 1 prior to `base`.
|
||||||
/// - `EpochTooHigh` when `other` is more than 1 after `base`.
|
/// - `EpochTooHigh` when `other` is more than 1 after `base`.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn from_epoch(base: Epoch, other: Epoch) -> Result<Self, Error> {
|
pub fn from_epoch(base: Epoch, other: Epoch) -> Result<Self, Error> {
|
||||||
// Due to saturating nature of epoch, check for current first.
|
// Due to saturating nature of epoch, check for current first.
|
||||||
if other == base {
|
if other == base {
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash::TreeHash;
|
|||||||
|
|
||||||
/// A `BeaconBlock` and a signature from its proposer.
|
/// A `BeaconBlock` and a signature from its proposer.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TestRandom)]
|
||||||
#[serde(bound = "E: EthSpec")]
|
#[serde(bound = "E: EthSpec")]
|
||||||
pub struct SignedBeaconBlock<E: EthSpec> {
|
pub struct SignedBeaconBlock<E: EthSpec> {
|
||||||
@ -34,7 +34,7 @@ impl<E: EthSpec> SignedBeaconBlock<E> {
|
|||||||
|
|
||||||
/// Returns the `tree_hash_root` of the block.
|
/// Returns the `tree_hash_root` of the block.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn canonical_root(&self) -> Hash256 {
|
pub fn canonical_root(&self) -> Hash256 {
|
||||||
Hash256::from_slice(&self.message.tree_hash_root()[..])
|
Hash256::from_slice(&self.message.tree_hash_root()[..])
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// An exit voluntarily submitted a validator who wishes to withdraw.
|
/// An exit voluntarily submitted a validator who wishes to withdraw.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct SignedBeaconBlockHeader {
|
pub struct SignedBeaconBlockHeader {
|
||||||
pub message: BeaconBlockHeader,
|
pub message: BeaconBlockHeader,
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// An exit voluntarily submitted a validator who wishes to withdraw.
|
/// An exit voluntarily submitted a validator who wishes to withdraw.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct SignedVoluntaryExit {
|
pub struct SignedVoluntaryExit {
|
||||||
pub message: VoluntaryExit,
|
pub message: VoluntaryExit,
|
||||||
|
@ -9,11 +9,11 @@ use tree_hash_derive::TreeHash;
|
|||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct SigningRoot {
|
pub struct SigningRoot {
|
||||||
pub object_root: Hash256,
|
pub object_root: Hash256,
|
||||||
pub domain: u64,
|
pub domain: Hash256,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SignedRoot: TreeHash {
|
pub trait SignedRoot: TreeHash {
|
||||||
fn signing_root(&self, domain: u64) -> Hash256 {
|
fn signing_root(&self, domain: Hash256) -> Hash256 {
|
||||||
SigningRoot {
|
SigningRoot {
|
||||||
object_root: self.tree_hash_root(),
|
object_root: self.tree_hash_root(),
|
||||||
domain,
|
domain,
|
||||||
|
@ -55,6 +55,7 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
|
|||||||
signing_validators: &[usize],
|
signing_validators: &[usize],
|
||||||
secret_keys: &[&SecretKey],
|
secret_keys: &[&SecretKey],
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -77,15 +78,28 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.attestation
|
self.attestation
|
||||||
.sign(secret_keys[index], committee_index, fork, spec)
|
.sign(
|
||||||
|
secret_keys[index],
|
||||||
|
committee_index,
|
||||||
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
)
|
||||||
.expect("can sign attestation");
|
.expect("can sign attestation");
|
||||||
|
|
||||||
if let AttestationTestTask::BadIndexedAttestationBadSignature = test_task {
|
self.attestation
|
||||||
self.attestation
|
.aggregation_bits
|
||||||
.aggregation_bits
|
.set(committee_index, true)
|
||||||
.set(committee_index, false)
|
.unwrap();
|
||||||
.unwrap();
|
}
|
||||||
}
|
|
||||||
|
if test_task == AttestationTestTask::BadIndexedAttestationBadSignature {
|
||||||
|
// Flip an aggregation bit, to make the aggregate invalid
|
||||||
|
// (We also want to avoid making it completely empty)
|
||||||
|
self.attestation
|
||||||
|
.aggregation_bits
|
||||||
|
.set(0, !self.attestation.aggregation_bits.get(0).unwrap())
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -22,6 +22,7 @@ impl TestingAttesterSlashingBuilder {
|
|||||||
validator_indices: &[u64],
|
validator_indices: &[u64],
|
||||||
signer: F,
|
signer: F,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> AttesterSlashing<T>
|
) -> AttesterSlashing<T>
|
||||||
where
|
where
|
||||||
@ -83,8 +84,12 @@ impl TestingAttesterSlashingBuilder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let add_signatures = |attestation: &mut IndexedAttestation<T>| {
|
let add_signatures = |attestation: &mut IndexedAttestation<T>| {
|
||||||
let domain =
|
let domain = spec.get_domain(
|
||||||
spec.get_domain(attestation.data.target.epoch, Domain::BeaconAttester, fork);
|
attestation.data.target.epoch,
|
||||||
|
Domain::BeaconAttester,
|
||||||
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
);
|
||||||
let message = attestation.data.signing_root(domain);
|
let message = attestation.data.signing_root(domain);
|
||||||
|
|
||||||
for validator_index in validator_indices {
|
for validator_index in validator_indices {
|
||||||
|
@ -97,12 +97,23 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
|||||||
self.block.slot = slot;
|
self.block.slot = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the proposer index of the block.
|
||||||
|
pub fn set_proposer_index(&mut self, proposer_index: u64) {
|
||||||
|
self.block.proposer_index = proposer_index;
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
/// 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,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) {
|
||||||
let epoch = self.block.slot.epoch(T::slots_per_epoch());
|
let epoch = self.block.slot.epoch(T::slots_per_epoch());
|
||||||
let domain = spec.get_domain(epoch, Domain::Randao, fork);
|
let domain = spec.get_domain(epoch, Domain::Randao, fork, genesis_validators_root);
|
||||||
let message = epoch.signing_root(domain);
|
let message = epoch.signing_root(domain);
|
||||||
self.block.body.randao_reveal = Signature::new(message.as_bytes(), sk);
|
self.block.body.randao_reveal = Signature::new(message.as_bytes(), sk);
|
||||||
}
|
}
|
||||||
@ -119,10 +130,17 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
|||||||
validator_index: u64,
|
validator_index: u64,
|
||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) {
|
) {
|
||||||
let proposer_slashing =
|
let proposer_slashing = build_proposer_slashing::<T>(
|
||||||
build_proposer_slashing::<T>(test_task, validator_index, secret_key, fork, spec);
|
test_task,
|
||||||
|
validator_index,
|
||||||
|
secret_key,
|
||||||
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
);
|
||||||
self.block
|
self.block
|
||||||
.body
|
.body
|
||||||
.proposer_slashings
|
.proposer_slashings
|
||||||
@ -137,6 +155,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
|||||||
validator_indices: &[u64],
|
validator_indices: &[u64],
|
||||||
secret_keys: &[&SecretKey],
|
secret_keys: &[&SecretKey],
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) {
|
) {
|
||||||
let attester_slashing = build_double_vote_attester_slashing(
|
let attester_slashing = build_double_vote_attester_slashing(
|
||||||
@ -144,6 +163,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
|||||||
validator_indices,
|
validator_indices,
|
||||||
secret_keys,
|
secret_keys,
|
||||||
fork,
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
let _ = self.block.body.attester_slashings.push(attester_slashing);
|
let _ = self.block.body.attester_slashings.push(attester_slashing);
|
||||||
@ -246,6 +266,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
|||||||
signing_validators,
|
signing_validators,
|
||||||
&signing_secret_keys,
|
&signing_secret_keys,
|
||||||
&state.fork,
|
&state.fork,
|
||||||
|
state.genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -355,14 +376,20 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let builder = TestingVoluntaryExitBuilder::new(exit_epoch, validator_index);
|
let builder = TestingVoluntaryExitBuilder::new(exit_epoch, validator_index);
|
||||||
let exit = builder.build(sk, &state.fork, spec);
|
let exit = builder.build(sk, &state.fork, state.genesis_validators_root, spec);
|
||||||
|
|
||||||
self.block.body.voluntary_exits.push(exit).unwrap();
|
self.block.body.voluntary_exits.push(exit).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs and returns the block, consuming the builder.
|
/// Signs and returns the block, consuming the builder.
|
||||||
pub fn build(self, sk: &SecretKey, fork: &Fork, spec: &ChainSpec) -> SignedBeaconBlock<T> {
|
pub fn build(
|
||||||
self.block.sign(sk, fork, spec)
|
self,
|
||||||
|
sk: &SecretKey,
|
||||||
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> SignedBeaconBlock<T> {
|
||||||
|
self.block.sign(sk, fork, genesis_validators_root, spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the block, consuming the builder.
|
/// Returns the block, consuming the builder.
|
||||||
@ -382,6 +409,7 @@ pub fn build_proposer_slashing<T: EthSpec>(
|
|||||||
validator_index: u64,
|
validator_index: u64,
|
||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> ProposerSlashing {
|
) -> ProposerSlashing {
|
||||||
TestingProposerSlashingBuilder::double_vote::<T>(
|
TestingProposerSlashingBuilder::double_vote::<T>(
|
||||||
@ -389,6 +417,7 @@ pub fn build_proposer_slashing<T: EthSpec>(
|
|||||||
validator_index,
|
validator_index,
|
||||||
secret_key,
|
secret_key,
|
||||||
fork,
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
spec,
|
spec,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -401,6 +430,7 @@ pub fn build_double_vote_attester_slashing<T: EthSpec>(
|
|||||||
validator_indices: &[u64],
|
validator_indices: &[u64],
|
||||||
secret_keys: &[&SecretKey],
|
secret_keys: &[&SecretKey],
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> AttesterSlashing<T> {
|
) -> AttesterSlashing<T> {
|
||||||
let signer = |validator_index: u64, message: &[u8]| {
|
let signer = |validator_index: u64, message: &[u8]| {
|
||||||
@ -411,5 +441,12 @@ pub fn build_double_vote_attester_slashing<T: EthSpec>(
|
|||||||
Signature::new(message, secret_keys[key_index])
|
Signature::new(message, secret_keys[key_index])
|
||||||
};
|
};
|
||||||
|
|
||||||
TestingAttesterSlashingBuilder::double_vote(test_task, validator_indices, signer, fork, spec)
|
TestingAttesterSlashingBuilder::double_vote(
|
||||||
|
test_task,
|
||||||
|
validator_indices,
|
||||||
|
signer,
|
||||||
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
spec,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,10 @@ impl TestingProposerSlashingBuilder {
|
|||||||
/// Where domain is a domain "constant" (e.g., `spec.domain_attestation`).
|
/// Where domain is a domain "constant" (e.g., `spec.domain_attestation`).
|
||||||
pub fn double_vote<T>(
|
pub fn double_vote<T>(
|
||||||
test_task: ProposerSlashingTestTask,
|
test_task: ProposerSlashingTestTask,
|
||||||
mut proposer_index: u64,
|
proposer_index: u64,
|
||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> ProposerSlashing
|
) -> ProposerSlashing
|
||||||
where
|
where
|
||||||
@ -31,6 +32,7 @@ impl TestingProposerSlashingBuilder {
|
|||||||
let mut signed_header_1 = SignedBeaconBlockHeader {
|
let mut signed_header_1 = SignedBeaconBlockHeader {
|
||||||
message: BeaconBlockHeader {
|
message: BeaconBlockHeader {
|
||||||
slot,
|
slot,
|
||||||
|
proposer_index,
|
||||||
parent_root: hash_1,
|
parent_root: hash_1,
|
||||||
state_root: hash_1,
|
state_root: hash_1,
|
||||||
body_root: hash_1,
|
body_root: hash_1,
|
||||||
@ -54,19 +56,25 @@ impl TestingProposerSlashingBuilder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if test_task != ProposerSlashingTestTask::BadProposal1Signature {
|
if test_task != ProposerSlashingTestTask::BadProposal1Signature {
|
||||||
signed_header_1 = signed_header_1.message.sign::<T>(secret_key, fork, spec);
|
signed_header_1 =
|
||||||
|
signed_header_1
|
||||||
|
.message
|
||||||
|
.sign::<T>(secret_key, fork, genesis_validators_root, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if test_task != ProposerSlashingTestTask::BadProposal2Signature {
|
if test_task != ProposerSlashingTestTask::BadProposal2Signature {
|
||||||
signed_header_2 = signed_header_2.message.sign::<T>(secret_key, fork, spec);
|
signed_header_2 =
|
||||||
|
signed_header_2
|
||||||
|
.message
|
||||||
|
.sign::<T>(secret_key, fork, genesis_validators_root, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if test_task == ProposerSlashingTestTask::ProposerUnknown {
|
if test_task == ProposerSlashingTestTask::ProposerUnknown {
|
||||||
proposer_index = 3_141_592;
|
signed_header_1.message.proposer_index = 3_141_592;
|
||||||
|
signed_header_2.message.proposer_index = 3_141_592;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProposerSlashing {
|
ProposerSlashing {
|
||||||
proposer_index,
|
|
||||||
signed_header_1,
|
signed_header_1,
|
||||||
signed_header_2,
|
signed_header_2,
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,10 @@ impl TestingVoluntaryExitBuilder {
|
|||||||
self,
|
self,
|
||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> SignedVoluntaryExit {
|
) -> SignedVoluntaryExit {
|
||||||
self.exit.sign(secret_key, fork, spec)
|
self.exit
|
||||||
|
.sign(secret_key, fork, genesis_validators_root, spec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// Information about a `BeaconChain` validator.
|
/// Information about a `BeaconChain` validator.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)]
|
||||||
pub struct Validator {
|
pub struct Validator {
|
||||||
pub pubkey: PublicKeyBytes,
|
pub pubkey: PublicKeyBytes,
|
||||||
@ -44,7 +44,7 @@ impl Validator {
|
|||||||
|
|
||||||
/// Returns `true` if the validator is eligible to join the activation queue.
|
/// Returns `true` if the validator is eligible to join the activation queue.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn is_eligible_for_activation_queue(&self, spec: &ChainSpec) -> bool {
|
pub fn is_eligible_for_activation_queue(&self, spec: &ChainSpec) -> bool {
|
||||||
self.activation_eligibility_epoch == spec.far_future_epoch
|
self.activation_eligibility_epoch == spec.far_future_epoch
|
||||||
&& self.effective_balance == spec.max_effective_balance
|
&& self.effective_balance == spec.max_effective_balance
|
||||||
@ -52,7 +52,7 @@ impl Validator {
|
|||||||
|
|
||||||
/// Returns `true` if the validator is eligible to be activated.
|
/// Returns `true` if the validator is eligible to be activated.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
pub fn is_eligible_for_activation<E: EthSpec>(
|
pub fn is_eligible_for_activation<E: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
state: &BeaconState<E>,
|
state: &BeaconState<E>,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
test_utils::TestRandom, ChainSpec, Domain, Epoch, Fork, SecretKey, Signature, SignedRoot,
|
test_utils::TestRandom, ChainSpec, Domain, Epoch, Fork, Hash256, SecretKey, Signature,
|
||||||
SignedVoluntaryExit,
|
SignedRoot, SignedVoluntaryExit,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
@ -10,7 +10,7 @@ use tree_hash_derive::TreeHash;
|
|||||||
|
|
||||||
/// An exit voluntarily submitted a validator who wishes to withdraw.
|
/// An exit voluntarily submitted a validator who wishes to withdraw.
|
||||||
///
|
///
|
||||||
/// Spec v0.10.1
|
/// Spec v0.11.1
|
||||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||||
pub struct VoluntaryExit {
|
pub struct VoluntaryExit {
|
||||||
/// Earliest epoch when voluntary exit can be processed.
|
/// Earliest epoch when voluntary exit can be processed.
|
||||||
@ -25,9 +25,15 @@ impl VoluntaryExit {
|
|||||||
self,
|
self,
|
||||||
secret_key: &SecretKey,
|
secret_key: &SecretKey,
|
||||||
fork: &Fork,
|
fork: &Fork,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> SignedVoluntaryExit {
|
) -> SignedVoluntaryExit {
|
||||||
let domain = spec.get_domain(self.epoch, Domain::VoluntaryExit, fork);
|
let domain = spec.get_domain(
|
||||||
|
self.epoch,
|
||||||
|
Domain::VoluntaryExit,
|
||||||
|
fork,
|
||||||
|
genesis_validators_root,
|
||||||
|
);
|
||||||
let message = self.signing_root(domain);
|
let message = self.signing_root(domain);
|
||||||
let signature = Signature::new(message.as_bytes(), &secret_key);
|
let signature = Signature::new(message.as_bytes(), &secret_key);
|
||||||
SignedVoluntaryExit {
|
SignedVoluntaryExit {
|
||||||
|
@ -9,9 +9,9 @@ use std::fs::File;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
const TAG: &str = "v0.10.1";
|
const TAG: &str = "v0.11.1";
|
||||||
// NOTE: the version of the unsafe contract lags the main tag, but the v0.9.2.1 code is compatible
|
// NOTE: the version of the unsafe contract lags the main tag, but the v0.9.2.1 code is compatible
|
||||||
// with the unmodified v0.10.1 contract
|
// with the unmodified v0.11.1 contract
|
||||||
const UNSAFE_TAG: &str = "v0.9.2.1";
|
const UNSAFE_TAG: &str = "v0.9.2.1";
|
||||||
|
|
||||||
fn spec_url() -> String {
|
fn spec_url() -> String {
|
||||||
|
@ -23,15 +23,15 @@ impl From<ethabi::Error> for DecodeError {
|
|||||||
|
|
||||||
pub const CONTRACT_DEPLOY_GAS: usize = 4_000_000;
|
pub const CONTRACT_DEPLOY_GAS: usize = 4_000_000;
|
||||||
pub const DEPOSIT_GAS: usize = 4_000_000;
|
pub const DEPOSIT_GAS: usize = 4_000_000;
|
||||||
pub const ABI: &[u8] = include_bytes!("../contracts/v0.10.1_validator_registration.json");
|
pub const ABI: &[u8] = include_bytes!("../contracts/v0.11.1_validator_registration.json");
|
||||||
pub const BYTECODE: &[u8] = include_bytes!("../contracts/v0.10.1_validator_registration.bytecode");
|
pub const BYTECODE: &[u8] = include_bytes!("../contracts/v0.11.1_validator_registration.bytecode");
|
||||||
pub const DEPOSIT_DATA_LEN: usize = 420; // lol
|
pub const DEPOSIT_DATA_LEN: usize = 420; // lol
|
||||||
|
|
||||||
pub mod testnet {
|
pub mod testnet {
|
||||||
pub const ABI: &[u8] =
|
pub const ABI: &[u8] =
|
||||||
include_bytes!("../contracts/v0.10.1_testnet_validator_registration.json");
|
include_bytes!("../contracts/v0.11.1_testnet_validator_registration.json");
|
||||||
pub const BYTECODE: &[u8] =
|
pub const BYTECODE: &[u8] =
|
||||||
include_bytes!("../contracts/v0.10.1_testnet_validator_registration.bytecode");
|
include_bytes!("../contracts/v0.11.1_testnet_validator_registration.bytecode");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_eth1_tx_data(deposit_data: &DepositData) -> Result<Vec<u8>, Error> {
|
pub fn encode_eth1_tx_data(deposit_data: &DepositData) -> Result<Vec<u8>, Error> {
|
||||||
|
@ -202,6 +202,7 @@ mod tests {
|
|||||||
|
|
||||||
type E = MainnetEthSpec;
|
type E = MainnetEthSpec;
|
||||||
|
|
||||||
|
/* TODO: disabled until testnet config is updated for v0.11
|
||||||
#[test]
|
#[test]
|
||||||
fn hard_coded_works() {
|
fn hard_coded_works() {
|
||||||
let dir: Eth2TestnetConfig<E> =
|
let dir: Eth2TestnetConfig<E> =
|
||||||
@ -211,6 +212,7 @@ mod tests {
|
|||||||
assert!(dir.genesis_state.is_some());
|
assert!(dir.genesis_state.is_some());
|
||||||
assert!(dir.yaml_config.is_some());
|
assert!(dir.yaml_config.is_some());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn round_trip() {
|
fn round_trip() {
|
||||||
|
@ -32,10 +32,8 @@ pub fn int_to_bytes3(int: u32) -> Option<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `int` as little-endian bytes with a length of 4.
|
/// Returns `int` as little-endian bytes with a length of 4.
|
||||||
pub fn int_to_bytes4(int: u32) -> Vec<u8> {
|
pub fn int_to_bytes4(int: u32) -> [u8; 4] {
|
||||||
let mut bytes = BytesMut::with_capacity(4);
|
int.to_le_bytes()
|
||||||
bytes.put_u32_le(int);
|
|
||||||
bytes.to_vec()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `int` as little-endian bytes with a length of 8.
|
/// Returns `int` as little-endian bytes with a length of 8.
|
||||||
@ -128,7 +126,7 @@ mod tests {
|
|||||||
1 => assert_eq!(int_to_bytes1(int as u8), bytes),
|
1 => assert_eq!(int_to_bytes1(int as u8), bytes),
|
||||||
2 => assert_eq!(int_to_bytes2(int as u16), bytes),
|
2 => assert_eq!(int_to_bytes2(int as u16), bytes),
|
||||||
3 => assert_eq!(int_to_bytes3(int as u32), Some(bytes)),
|
3 => assert_eq!(int_to_bytes3(int as u32), Some(bytes)),
|
||||||
4 => assert_eq!(int_to_bytes4(int as u32), bytes),
|
4 => assert_eq!(&int_to_bytes4(int as u32)[..], &bytes[..]),
|
||||||
8 => assert_eq!(int_to_bytes8(int), bytes),
|
8 => assert_eq!(int_to_bytes8(int), bytes),
|
||||||
32 => assert_eq!(int_to_bytes32(int), bytes),
|
32 => assert_eq!(int_to_bytes32(int), bytes),
|
||||||
48 => assert_eq!(int_to_bytes48(int), bytes),
|
48 => assert_eq!(int_to_bytes48(int), bytes),
|
||||||
|
@ -324,6 +324,14 @@ impl<E: EthSpec> Beacon<E> {
|
|||||||
.and_then(move |url| client.json_get(url, vec![]))
|
.and_then(move |url| client.json_get(url, vec![]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the genesis validators root.
|
||||||
|
pub fn get_genesis_validators_root(&self) -> impl Future<Item = Hash256, Error = Error> {
|
||||||
|
let client = self.0.clone();
|
||||||
|
self.url("genesis_validators_root")
|
||||||
|
.into_future()
|
||||||
|
.and_then(move |url| client.json_get(url, vec![]))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the fork at the head of the beacon chain.
|
/// Returns the fork at the head of the beacon chain.
|
||||||
pub fn get_fork(&self) -> impl Future<Item = Fork, Error = Error> {
|
pub fn get_fork(&self) -> impl Future<Item = Fork, Error = Error> {
|
||||||
let client = self.0.clone();
|
let client = self.0.clone();
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
//! format designed for use in Ethereum 2.0.
|
//! format designed for use in Ethereum 2.0.
|
||||||
//!
|
//!
|
||||||
//! Adheres to the Ethereum 2.0 [SSZ
|
//! Adheres to the Ethereum 2.0 [SSZ
|
||||||
//! specification](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/ssz/simple-serialize.md)
|
//! specification](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/ssz/simple-serialize.md)
|
||||||
//! at v0.10.1.
|
//! at v0.11.1.
|
||||||
//!
|
//!
|
||||||
//! ## Example
|
//! ## Example
|
||||||
//!
|
//!
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
//! for padding and verification.
|
//! for padding and verification.
|
||||||
//!
|
//!
|
||||||
//! Adheres to the Ethereum 2.0 [SSZ
|
//! Adheres to the Ethereum 2.0 [SSZ
|
||||||
//! specification](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/ssz/simple-serialize.md)
|
//! specification](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/ssz/simple-serialize.md)
|
||||||
//! at v0.10.1.
|
//! at v0.11.1.
|
||||||
//!
|
//!
|
||||||
//! ## Example
|
//! ## Example
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Provides list-shuffling functions matching the Ethereum 2.0 specification.
|
//! Provides list-shuffling functions matching the Ethereum 2.0 specification.
|
||||||
//!
|
//!
|
||||||
//! See
|
//! See
|
||||||
//! [compute_shuffled_index](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#compute_shuffled_index)
|
//! [compute_shuffled_index](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#compute_shuffled_index)
|
||||||
//! for specifications.
|
//! for specifications.
|
||||||
//!
|
//!
|
||||||
//! There are two functions exported by this crate:
|
//! There are two functions exported by this crate:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Bump the test tag here and in .gitlab-ci.yml and CI will take care of updating the cached tarballs
|
# Bump the test tag here and in .gitlab-ci.yml and CI will take care of updating the cached tarballs
|
||||||
TESTS_TAG := v0.10.1
|
TESTS_TAG := v0.11.1
|
||||||
TESTS = general minimal mainnet
|
TESTS = general minimal mainnet
|
||||||
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))
|
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))
|
||||||
|
|
||||||
|
@ -81,7 +81,11 @@ impl<E: EthSpec> EpochTransition<E> for Slashings {
|
|||||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||||
let mut validator_statuses = ValidatorStatuses::new(&state, spec)?;
|
let mut validator_statuses = ValidatorStatuses::new(&state, spec)?;
|
||||||
validator_statuses.process_attestations(&state, spec)?;
|
validator_statuses.process_attestations(&state, spec)?;
|
||||||
process_slashings(state, validator_statuses.total_balances.current_epoch, spec)?;
|
process_slashings(
|
||||||
|
state,
|
||||||
|
validator_statuses.total_balances.current_epoch(),
|
||||||
|
spec,
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,6 @@ mod ssz_static {
|
|||||||
ssz_static_test!(voluntary_exit, VoluntaryExit);
|
ssz_static_test!(voluntary_exit, VoluntaryExit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: SSZ generic tests disabled, missing from v0.10.0
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ssz_generic() {
|
fn ssz_generic() {
|
||||||
SszGenericHandler::<BasicVector>::run();
|
SszGenericHandler::<BasicVector>::run();
|
||||||
@ -186,7 +185,6 @@ fn ssz_generic() {
|
|||||||
SszGenericHandler::<Uints>::run();
|
SszGenericHandler::<Uints>::run();
|
||||||
SszGenericHandler::<Containers>::run();
|
SszGenericHandler::<Containers>::run();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn epoch_processing_justification_and_finalization() {
|
fn epoch_processing_justification_and_finalization() {
|
||||||
|
@ -143,101 +143,125 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
box_future
|
box_future
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.and_then(move |(beacon_node, remote_eth2_config, genesis_time)| {
|
.and_then(|(beacon_node, eth2_config, genesis_time)| {
|
||||||
let log = log_4.clone();
|
beacon_node
|
||||||
|
.http
|
||||||
|
.beacon()
|
||||||
|
.get_genesis_validators_root()
|
||||||
|
.map(move |genesis_validators_root| {
|
||||||
|
(
|
||||||
|
beacon_node,
|
||||||
|
eth2_config,
|
||||||
|
genesis_time,
|
||||||
|
genesis_validators_root,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map_err(|e| {
|
||||||
|
format!(
|
||||||
|
"Unable to read genesis validators root from beacon node: {:?}",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.and_then(
|
||||||
|
move |(beacon_node, remote_eth2_config, genesis_time, genesis_validators_root)| {
|
||||||
|
let log = log_4.clone();
|
||||||
|
|
||||||
// Do not permit a connection to a beacon node using different spec constants.
|
// Do not permit a connection to a beacon node using different spec constants.
|
||||||
if context.eth2_config.spec_constants != remote_eth2_config.spec_constants {
|
if context.eth2_config.spec_constants != remote_eth2_config.spec_constants {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Beacon node is using an incompatible spec. Got {}, expected {}",
|
"Beacon node is using an incompatible spec. Got {}, expected {}",
|
||||||
remote_eth2_config.spec_constants, context.eth2_config.spec_constants
|
remote_eth2_config.spec_constants, context.eth2_config.spec_constants
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: here we just assume the spec variables of the remote node. This is very useful
|
// Note: here we just assume the spec variables of the remote node. This is very useful
|
||||||
// for testnets, but perhaps a security issue when it comes to mainnet.
|
// for testnets, but perhaps a security issue when it comes to mainnet.
|
||||||
//
|
//
|
||||||
// A damaging attack would be for a beacon node to convince the validator client of a
|
// A damaging attack would be for a beacon node to convince the validator client of a
|
||||||
// different `SLOTS_PER_EPOCH` variable. This could result in slashable messages being
|
// different `SLOTS_PER_EPOCH` variable. This could result in slashable messages being
|
||||||
// produced. We are safe from this because `SLOTS_PER_EPOCH` is a type-level constant
|
// produced. We are safe from this because `SLOTS_PER_EPOCH` is a type-level constant
|
||||||
// for Lighthouse.
|
// for Lighthouse.
|
||||||
context.eth2_config = remote_eth2_config;
|
context.eth2_config = remote_eth2_config;
|
||||||
|
|
||||||
let slot_clock = SystemTimeSlotClock::new(
|
let slot_clock = SystemTimeSlotClock::new(
|
||||||
context.eth2_config.spec.genesis_slot,
|
context.eth2_config.spec.genesis_slot,
|
||||||
Duration::from_secs(genesis_time),
|
Duration::from_secs(genesis_time),
|
||||||
Duration::from_millis(context.eth2_config.spec.milliseconds_per_slot),
|
Duration::from_millis(context.eth2_config.spec.milliseconds_per_slot),
|
||||||
);
|
);
|
||||||
|
|
||||||
let fork_service = ForkServiceBuilder::new()
|
let fork_service = ForkServiceBuilder::new()
|
||||||
.slot_clock(slot_clock.clone())
|
.slot_clock(slot_clock.clone())
|
||||||
.beacon_node(beacon_node.clone())
|
.beacon_node(beacon_node.clone())
|
||||||
.runtime_context(context.service_context("fork".into()))
|
.runtime_context(context.service_context("fork".into()))
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let validator_store: ValidatorStore<SystemTimeSlotClock, T> =
|
let validator_store: ValidatorStore<SystemTimeSlotClock, T> =
|
||||||
match &config.key_source {
|
match &config.key_source {
|
||||||
// Load pre-existing validators from the data dir.
|
// Load pre-existing validators from the data dir.
|
||||||
//
|
//
|
||||||
// Use the `account_manager` to generate these files.
|
// Use the `account_manager` to generate these files.
|
||||||
KeySource::Disk => ValidatorStore::load_from_disk(
|
KeySource::Disk => ValidatorStore::load_from_disk(
|
||||||
config.data_dir.clone(),
|
config.data_dir.clone(),
|
||||||
context.eth2_config.spec.clone(),
|
genesis_validators_root,
|
||||||
fork_service.clone(),
|
|
||||||
log.clone(),
|
|
||||||
)?,
|
|
||||||
// Generate ephemeral insecure keypairs for testing purposes.
|
|
||||||
//
|
|
||||||
// Do not use in production.
|
|
||||||
KeySource::InsecureKeypairs(indices) => {
|
|
||||||
ValidatorStore::insecure_ephemeral_validators(
|
|
||||||
&indices,
|
|
||||||
context.eth2_config.spec.clone(),
|
context.eth2_config.spec.clone(),
|
||||||
fork_service.clone(),
|
fork_service.clone(),
|
||||||
log.clone(),
|
log.clone(),
|
||||||
)?
|
)?,
|
||||||
}
|
// Generate ephemeral insecure keypairs for testing purposes.
|
||||||
};
|
//
|
||||||
|
// Do not use in production.
|
||||||
|
KeySource::InsecureKeypairs(indices) => {
|
||||||
|
ValidatorStore::insecure_ephemeral_validators(
|
||||||
|
&indices,
|
||||||
|
genesis_validators_root,
|
||||||
|
context.eth2_config.spec.clone(),
|
||||||
|
fork_service.clone(),
|
||||||
|
log.clone(),
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
log,
|
log,
|
||||||
"Loaded validator keypair store";
|
"Loaded validator keypair store";
|
||||||
"voting_validators" => validator_store.num_voting_validators()
|
"voting_validators" => validator_store.num_voting_validators()
|
||||||
);
|
);
|
||||||
|
|
||||||
let duties_service = DutiesServiceBuilder::new()
|
let duties_service = DutiesServiceBuilder::new()
|
||||||
.slot_clock(slot_clock.clone())
|
.slot_clock(slot_clock.clone())
|
||||||
.validator_store(validator_store.clone())
|
.validator_store(validator_store.clone())
|
||||||
.beacon_node(beacon_node.clone())
|
.beacon_node(beacon_node.clone())
|
||||||
.runtime_context(context.service_context("duties".into()))
|
.runtime_context(context.service_context("duties".into()))
|
||||||
.allow_unsynced_beacon_node(config.allow_unsynced_beacon_node)
|
.allow_unsynced_beacon_node(config.allow_unsynced_beacon_node)
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let block_service = BlockServiceBuilder::new()
|
let block_service = BlockServiceBuilder::new()
|
||||||
.duties_service(duties_service.clone())
|
.duties_service(duties_service.clone())
|
||||||
.slot_clock(slot_clock.clone())
|
.slot_clock(slot_clock.clone())
|
||||||
.validator_store(validator_store.clone())
|
.validator_store(validator_store.clone())
|
||||||
.beacon_node(beacon_node.clone())
|
.beacon_node(beacon_node.clone())
|
||||||
.runtime_context(context.service_context("block".into()))
|
.runtime_context(context.service_context("block".into()))
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let attestation_service = AttestationServiceBuilder::new()
|
let attestation_service = AttestationServiceBuilder::new()
|
||||||
.duties_service(duties_service.clone())
|
.duties_service(duties_service.clone())
|
||||||
.slot_clock(slot_clock)
|
.slot_clock(slot_clock)
|
||||||
.validator_store(validator_store)
|
.validator_store(validator_store)
|
||||||
.beacon_node(beacon_node)
|
.beacon_node(beacon_node)
|
||||||
.runtime_context(context.service_context("attestation".into()))
|
.runtime_context(context.service_context("attestation".into()))
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
context,
|
context,
|
||||||
duties_service,
|
duties_service,
|
||||||
fork_service,
|
fork_service,
|
||||||
block_service,
|
block_service,
|
||||||
attestation_service,
|
attestation_service,
|
||||||
exit_signals: vec![],
|
exit_signals: vec![],
|
||||||
})
|
})
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_service(&mut self) -> Result<(), String> {
|
pub fn start_service(&mut self) -> Result<(), String> {
|
||||||
|
@ -12,13 +12,14 @@ use std::path::PathBuf;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
use types::{
|
use types::{
|
||||||
Attestation, BeaconBlock, ChainSpec, Domain, Epoch, EthSpec, Fork, PublicKey, Signature,
|
Attestation, BeaconBlock, ChainSpec, Domain, Epoch, EthSpec, Fork, Hash256, PublicKey,
|
||||||
SignedBeaconBlock, SignedRoot,
|
Signature, SignedBeaconBlock, SignedRoot,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ValidatorStore<T, E: EthSpec> {
|
pub struct ValidatorStore<T, E: EthSpec> {
|
||||||
validators: Arc<RwLock<HashMap<PublicKey, ValidatorDirectory>>>,
|
validators: Arc<RwLock<HashMap<PublicKey, ValidatorDirectory>>>,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: Arc<ChainSpec>,
|
spec: Arc<ChainSpec>,
|
||||||
log: Logger,
|
log: Logger,
|
||||||
temp_dir: Option<Arc<TempDir>>,
|
temp_dir: Option<Arc<TempDir>>,
|
||||||
@ -29,6 +30,7 @@ pub struct ValidatorStore<T, E: EthSpec> {
|
|||||||
impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
||||||
pub fn load_from_disk(
|
pub fn load_from_disk(
|
||||||
base_dir: PathBuf,
|
base_dir: PathBuf,
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: ChainSpec,
|
spec: ChainSpec,
|
||||||
fork_service: ForkService<T, E>,
|
fork_service: ForkService<T, E>,
|
||||||
log: Logger,
|
log: Logger,
|
||||||
@ -66,6 +68,7 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
validators: Arc::new(RwLock::new(HashMap::from_par_iter(validator_key_values))),
|
validators: Arc::new(RwLock::new(HashMap::from_par_iter(validator_key_values))),
|
||||||
|
genesis_validators_root,
|
||||||
spec: Arc::new(spec),
|
spec: Arc::new(spec),
|
||||||
log,
|
log,
|
||||||
temp_dir: None,
|
temp_dir: None,
|
||||||
@ -76,6 +79,7 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
|||||||
|
|
||||||
pub fn insecure_ephemeral_validators(
|
pub fn insecure_ephemeral_validators(
|
||||||
validator_indices: &[usize],
|
validator_indices: &[usize],
|
||||||
|
genesis_validators_root: Hash256,
|
||||||
spec: ChainSpec,
|
spec: ChainSpec,
|
||||||
fork_service: ForkService<T, E>,
|
fork_service: ForkService<T, E>,
|
||||||
log: Logger,
|
log: Logger,
|
||||||
@ -107,6 +111,7 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
validators: Arc::new(RwLock::new(HashMap::from_iter(validators))),
|
validators: Arc::new(RwLock::new(HashMap::from_iter(validators))),
|
||||||
|
genesis_validators_root,
|
||||||
spec: Arc::new(spec),
|
spec: Arc::new(spec),
|
||||||
log,
|
log,
|
||||||
temp_dir: Some(Arc::new(temp_dir)),
|
temp_dir: Some(Arc::new(temp_dir)),
|
||||||
@ -144,7 +149,12 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
|||||||
.get(validator_pubkey)
|
.get(validator_pubkey)
|
||||||
.and_then(|validator_dir| {
|
.and_then(|validator_dir| {
|
||||||
let voting_keypair = validator_dir.voting_keypair.as_ref()?;
|
let voting_keypair = validator_dir.voting_keypair.as_ref()?;
|
||||||
let domain = self.spec.get_domain(epoch, Domain::Randao, &self.fork()?);
|
let domain = self.spec.get_domain(
|
||||||
|
epoch,
|
||||||
|
Domain::Randao,
|
||||||
|
&self.fork()?,
|
||||||
|
self.genesis_validators_root,
|
||||||
|
);
|
||||||
let message = epoch.signing_root(domain);
|
let message = epoch.signing_root(domain);
|
||||||
|
|
||||||
Some(Signature::new(message.as_bytes(), &voting_keypair.sk))
|
Some(Signature::new(message.as_bytes(), &voting_keypair.sk))
|
||||||
@ -162,7 +172,12 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
|||||||
.get(validator_pubkey)
|
.get(validator_pubkey)
|
||||||
.and_then(|validator_dir| {
|
.and_then(|validator_dir| {
|
||||||
let voting_keypair = validator_dir.voting_keypair.as_ref()?;
|
let voting_keypair = validator_dir.voting_keypair.as_ref()?;
|
||||||
Some(block.sign(&voting_keypair.sk, &self.fork()?, &self.spec))
|
Some(block.sign(
|
||||||
|
&voting_keypair.sk,
|
||||||
|
&self.fork()?,
|
||||||
|
self.genesis_validators_root,
|
||||||
|
&self.spec,
|
||||||
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,6 +199,7 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
|||||||
&voting_keypair.sk,
|
&voting_keypair.sk,
|
||||||
validator_committee_position,
|
validator_committee_position,
|
||||||
&self.fork()?,
|
&self.fork()?,
|
||||||
|
self.genesis_validators_root,
|
||||||
&self.spec,
|
&self.spec,
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
Loading…
Reference in New Issue
Block a user