Skip to content

Commit

Permalink
Update to spec v0.11 (#959)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
michaelsproul and Herman Alonso Junge authored Apr 1, 2020
1 parent e04fc8d commit 26bdc29
Show file tree
Hide file tree
Showing 84 changed files with 1,069 additions and 505 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Like all Ethereum 2.0 clients, Lighthouse is a work-in-progress.

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.
- RESTful JSON API via HTTP server.
- Events via WebSocket.
Expand Down
23 changes: 19 additions & 4 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ pub struct HeadInfo {
pub current_justified_checkpoint: types::Checkpoint,
pub finalized_checkpoint: types::Checkpoint,
pub fork: Fork,
pub genesis_time: u64,
pub genesis_validators_root: Hash256,
}

pub trait BeaconChainTypes: Send + Sync + 'static {
Expand Down Expand Up @@ -492,6 +494,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
current_justified_checkpoint: head.beacon_state.current_justified_checkpoint.clone(),
finalized_checkpoint: head.beacon_state.finalized_checkpoint.clone(),
fork: head.beacon_state.fork.clone(),
genesis_time: head.beacon_state.genesis_time,
genesis_validators_root: head.beacon_state.genesis_validators_root,
})
}

Expand Down Expand Up @@ -1031,17 +1035,23 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
})
.collect::<Result<Vec<&PublicKey>, Error>>()?;

let fork = self
let (fork, genesis_validators_root) = self
.canonical_head
.try_read_for(HEAD_LOCK_TIMEOUT)
.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(
pubkeys,
&attestation.signature,
&indexed_attestation,
&fork,
genesis_validators_root,
&self.spec,
)
.map_err(Error::SignatureSetError)?;
Expand Down Expand Up @@ -1074,8 +1084,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
// Provide the valid attestation to op pool, which may choose to retain the
// attestation for inclusion in a future block.
if self.eth1_chain.is_some() {
self.op_pool
.insert_attestation(attestation, &fork, &self.spec)?;
self.op_pool.insert_attestation(
attestation,
&fork,
genesis_validators_root,
&self.spec,
)?;
};

Ok(AttestationProcessingOutcome::Processed)
Expand Down Expand Up @@ -1547,6 +1561,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
let mut block = SignedBeaconBlock {
message: BeaconBlock {
slot: state.slot,
proposer_index: state.get_beacon_proposer_index(state.slot, &self.spec)? as u64,
parent_root,
state_root: Hash256::zero(),
body: BeaconBlockBody {
Expand Down
7 changes: 5 additions & 2 deletions beacon_node/beacon_chain/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,9 @@ where

let randao_reveal = {
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);
Signature::new(message.as_bytes(), sk)
};
Expand All @@ -323,7 +325,7 @@ where
.produce_block_on_state(state, slot, randao_reveal)
.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)
}
Expand Down Expand Up @@ -408,6 +410,7 @@ where
attestation.data.target.epoch,
Domain::BeaconAttester,
fork,
state.genesis_validators_root,
);

let message = attestation.data.signing_root(domain);
Expand Down
10 changes: 9 additions & 1 deletion beacon_node/rest_api/src/beacon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,15 @@ pub fn get_genesis_time<T: BeaconChainTypes>(
req: Request<Body>,
beacon_chain: Arc<BeaconChain<T>>,
) -> 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>(
Expand Down
14 changes: 7 additions & 7 deletions beacon_node/rest_api/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ pub struct VoteCount {
impl Into<VoteCount> for TotalBalances {
fn into(self) -> VoteCount {
VoteCount {
current_epoch_active_gwei: self.current_epoch,
previous_epoch_active_gwei: self.previous_epoch,
current_epoch_attesting_gwei: self.current_epoch_attesters,
current_epoch_target_attesting_gwei: self.current_epoch_target_attesters,
previous_epoch_attesting_gwei: self.previous_epoch_attesters,
previous_epoch_target_attesting_gwei: self.previous_epoch_target_attesters,
previous_epoch_head_attesting_gwei: self.previous_epoch_head_attesters,
current_epoch_active_gwei: self.current_epoch(),
previous_epoch_active_gwei: self.previous_epoch(),
current_epoch_attesting_gwei: self.current_epoch_attesters(),
current_epoch_target_attesting_gwei: self.current_epoch_target_attesters(),
previous_epoch_attesting_gwei: self.previous_epoch_attesters(),
previous_epoch_target_attesting_gwei: self.previous_epoch_target_attesters(),
previous_epoch_head_attesting_gwei: self.previous_epoch_head_attesters(),
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions beacon_node/rest_api/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ pub fn route<T: BeaconChainTypes>(
(&Method::GET, "/beacon/genesis_time") => {
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") => {
into_boxfut(beacon::get_validators::<T>(req, beacon_chain))
}
Expand Down
50 changes: 38 additions & 12 deletions beacon_node/rest_api/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,15 @@ fn get_randao_reveal<T: BeaconChainTypes>(
slot: Slot,
spec: &ChainSpec,
) -> Signature {
let fork = beacon_chain
.head()
.expect("should get head")
.beacon_state
.fork;
let head = beacon_chain.head().expect("should get head");
let fork = head.beacon_state.fork;
let genesis_validators_root = head.beacon_state.genesis_validators_root;
let proposer_index = beacon_chain
.block_proposer(slot)
.expect("should get proposer index");
let keypair = generate_deterministic_keypair(proposer_index);
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);
Signature::new(message.as_bytes(), &keypair.sk)
}
Expand All @@ -68,16 +66,14 @@ fn sign_block<T: BeaconChainTypes>(
block: BeaconBlock<T::EthSpec>,
spec: &ChainSpec,
) -> SignedBeaconBlock<T::EthSpec> {
let fork = beacon_chain
.head()
.expect("should get head")
.beacon_state
.fork;
let head = beacon_chain.head().expect("should get head");
let fork = head.beacon_state.fork;
let genesis_validators_root = head.beacon_state.genesis_validators_root;
let proposer_index = beacon_chain
.block_proposer(block.slot)
.expect("should get 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]
Expand Down Expand Up @@ -156,6 +152,7 @@ fn validator_produce_attestation() {
.attestation_committee_position
.expect("should have committee position"),
&state.fork,
state.genesis_validators_root,
spec,
)
.expect("should sign attestation");
Expand Down Expand Up @@ -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]
fn fork() {
let mut env = build_env();
Expand Down Expand Up @@ -903,6 +925,7 @@ fn proposer_slashing() {
proposer_index as u64,
&key,
fork,
state.genesis_validators_root,
spec,
);

Expand All @@ -927,6 +950,7 @@ fn proposer_slashing() {
proposer_index as u64,
&key,
fork,
state.genesis_validators_root,
spec,
);
invalid_proposer_slashing.signed_header_2 = invalid_proposer_slashing.signed_header_1.clone();
Expand Down Expand Up @@ -981,6 +1005,7 @@ fn attester_slashing() {
&validator_indices[..],
&secret_keys[..],
fork,
state.genesis_validators_root,
spec,
);

Expand All @@ -1006,6 +1031,7 @@ fn attester_slashing() {
&validator_indices[..],
&secret_keys[..],
fork,
state.genesis_validators_root,
spec,
);
invalid_attester_slashing.attestation_2 = invalid_attester_slashing.attestation_1.clone();
Expand Down
5 changes: 4 additions & 1 deletion beacon_node/store/src/partial_beacon_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ use types::*;
///
/// Utilises lazy-loading from separate storage for its vector fields.
///
/// Spec v0.10.1
/// Spec v0.11.1
#[derive(Debug, PartialEq, Clone, Encode, Decode)]
pub struct PartialBeaconState<T>
where
T: EthSpec,
{
// Versioning
pub genesis_time: u64,
pub genesis_validators_root: Hash256,
pub slot: Slot,
pub fork: Fork,

Expand Down Expand Up @@ -72,6 +73,7 @@ impl<T: EthSpec> PartialBeaconState<T> {
// TODO: could use references/Cow for fields to avoid cloning
PartialBeaconState {
genesis_time: s.genesis_time,
genesis_validators_root: s.genesis_validators_root,
slot: s.slot,
fork: s.fork.clone(),

Expand Down Expand Up @@ -181,6 +183,7 @@ impl<E: EthSpec> TryInto<BeaconState<E>> for PartialBeaconState<E> {

Ok(BeaconState {
genesis_time: self.genesis_time,
genesis_validators_root: self.genesis_validators_root,
slot: self.slot,
fork: self.fork,

Expand Down
8 changes: 5 additions & 3 deletions book/src/http_beacon.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ Returns an object containing a single [`SignedBeaconBlock`](https://github.com/e
"beacon_block": {
"message": {
"slot": 0,
"proposer_index": 14,
"parent_root": "0x0000000000000000000000000000000000000000000000000000000000000000",
"state_root": "0xf15690b6be4ed42ea1ee0741eb4bfd4619d37be8229b84b4ddd480fb028dcc8f",
"body": {
Expand Down Expand Up @@ -444,7 +445,7 @@ canonical chain.
### Returns

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.

### Example Response
Expand All @@ -454,6 +455,7 @@ and its tree hash root.
"root": "0x528e54ca5d4c957729a73f40fc513ae312e054c7295775c4a2b21f423416a72b",
"beacon_state": {
"genesis_time": 1575652800,
"genesis_validators_root": "0xa8a9226edee1b2627fb4117d7dea4996e64dec2998f37f6e824f74f2ce39a538",
"slot": 18478
}
}
Expand Down Expand Up @@ -505,7 +507,7 @@ Typical Responses | 200
### Returns

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

Expand Down Expand Up @@ -565,7 +567,7 @@ Typical Responses | 200

### 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

Expand Down
30 changes: 21 additions & 9 deletions eth2/operation_pool/src/attestation_id.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use int_to_bytes::int_to_bytes8;
use serde_derive::{Deserialize, Serialize};
use ssz::ssz_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.
#[derive(
Expand All @@ -13,21 +12,34 @@ pub struct AttestationId {
}

/// 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 {
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 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 }
}

pub fn compute_domain_bytes(epoch: Epoch, fork: &Fork, spec: &ChainSpec) -> Vec<u8> {
int_to_bytes8(spec.get_domain(epoch, Domain::BeaconAttester, fork))
pub fn compute_domain_bytes(
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 {
&self.v[self.v.len() - DOMAIN_BYTES_LEN..] == domain_bytes
pub fn domain_bytes_match(&self, domain_bytes: &Hash256) -> bool {
&self.v[self.v.len() - DOMAIN_BYTES_LEN..] == domain_bytes.as_bytes()
}
}
Loading

0 comments on commit 26bdc29

Please sign in to comment.