Update to v0.9.1

This commit is contained in:
Michael Sproul
2019-11-11 14:55:54 +11:00
parent aaa5f2042f
commit c36bb94d6e
19 changed files with 38 additions and 243 deletions

View File

@@ -4,7 +4,7 @@ default:
image: 'sigp/lighthouse:latest'
cache:
paths:
- tests/ef_tests/*-v0.9.0.tar.gz
- tests/ef_tests/*-v0.9.1.tar.gz
stages:
- test

View File

@@ -12,8 +12,8 @@ use std::sync::Arc;
use store::MemoryStore;
use tree_hash::{SignedRoot, TreeHash};
use types::{
AggregateSignature, Attestation, AttestationDataAndCustodyBit, BeaconBlock, BeaconState,
BitList, ChainSpec, Domain, EthSpec, Hash256, Keypair, SecretKey, Signature, Slot,
AggregateSignature, Attestation, BeaconBlock, BeaconState, BitList, ChainSpec, Domain, EthSpec,
Hash256, Keypair, SecretKey, Signature, Slot,
};
pub use types::test_utils::generate_deterministic_keypairs;
@@ -321,15 +321,9 @@ where
aggregation_bits
.set(i, true)
.expect("should be able to set aggregation bits");
let custody_bits = BitList::with_capacity(committee_size)
.expect("should make custody bits");
let signature = {
let message = AttestationDataAndCustodyBit {
data: data.clone(),
custody_bit: false,
}
.tree_hash_root();
let message = data.tree_hash_root();
let domain = spec.get_domain(
data.target.epoch,
@@ -350,7 +344,6 @@ where
let attestation = Attestation {
aggregation_bits,
data,
custody_bits,
signature,
};

View File

@@ -347,8 +347,6 @@ pub fn get_new_attestation<T: BeaconChainTypes + 'static>(req: Request<Body>) ->
let attestation: Attestation<T::EthSpec> = Attestation {
aggregation_bits,
data: attestation_data,
custody_bits: BitList::with_capacity(val_duty.committee_len)
.expect("Should be able to create an empty BitList for the custody bits."),
signature: AggregateSignature::new(),
};

View File

@@ -3,7 +3,7 @@ use types::*;
/// Returns validator indices which participated in the attestation, sorted by increasing index.
///
/// Spec v0.9.0
/// Spec v0.9.1
pub fn get_attesting_indices<T: EthSpec>(
state: &BeaconState<T>,
attestation_data: &AttestationData,

View File

@@ -6,117 +6,19 @@ type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;
/// Convert `attestation` to (almost) indexed-verifiable form.
///
/// Spec v0.9.0
/// Spec v0.9.1
pub fn get_indexed_attestation<T: EthSpec>(
state: &BeaconState<T>,
attestation: &Attestation<T>,
) -> Result<IndexedAttestation<T>> {
// Note: we rely on both calls to `get_attesting_indices` to check the bitfield lengths
// against the committee length
let attesting_indices =
get_attesting_indices(state, &attestation.data, &attestation.aggregation_bits)?;
let custody_bit_1_indices =
get_attesting_indices(state, &attestation.data, &attestation.custody_bits)?;
verify!(
custody_bit_1_indices.is_subset(&attesting_indices),
Invalid::CustodyBitfieldNotSubset
);
let custody_bit_0_indices = &attesting_indices - &custody_bit_1_indices;
Ok(IndexedAttestation {
custody_bit_0_indices: VariableList::new(
custody_bit_0_indices
.into_iter()
.map(|x| x as u64)
.collect(),
)?,
custody_bit_1_indices: VariableList::new(
custody_bit_1_indices
.into_iter()
.map(|x| x as u64)
.collect(),
attesting_indices: VariableList::new(
attesting_indices.into_iter().map(|x| x as u64).collect(),
)?,
data: attestation.data.clone(),
signature: attestation.signature.clone(),
})
}
#[cfg(test)]
mod test {
use super::*;
use itertools::{Either, Itertools};
use types::test_utils::*;
#[test]
fn custody_bitfield_indexing() {
let validator_count = 128;
let spec = MinimalEthSpec::default_spec();
let state_builder =
TestingBeaconStateBuilder::<MinimalEthSpec>::from_default_keypairs_file_if_exists(
validator_count,
&spec,
);
let (mut state, keypairs) = state_builder.build();
state.build_all_caches(&spec).unwrap();
state.slot += 1;
let index = 0;
let bc = state.get_beacon_committee(Slot::new(0), index).unwrap();
// Make a third of the validators sign with custody bit 0, a third with custody bit 1
// and a third not sign at all.
assert!(
bc.committee.len() >= 4,
"need at least 4 validators per committee for this test to work"
);
let (mut bit_0_indices, mut bit_1_indices): (Vec<_>, Vec<_>) = bc
.committee
.iter()
.enumerate()
.filter(|(i, _)| i % 3 != 0)
.partition_map(|(i, index)| {
if i % 3 == 1 {
Either::Left(*index)
} else {
Either::Right(*index)
}
});
assert!(!bit_0_indices.is_empty());
assert!(!bit_1_indices.is_empty());
let bit_0_keys = bit_0_indices
.iter()
.map(|validator_index| &keypairs[*validator_index].sk)
.collect::<Vec<_>>();
let bit_1_keys = bit_1_indices
.iter()
.map(|validator_index| &keypairs[*validator_index].sk)
.collect::<Vec<_>>();
let mut attestation_builder =
TestingAttestationBuilder::new(&state, &bc.committee, bc.slot, index);
attestation_builder
.sign(&bit_0_indices, &bit_0_keys, &state.fork, &spec, false)
.sign(&bit_1_indices, &bit_1_keys, &state.fork, &spec, true);
let attestation = attestation_builder.build();
let indexed_attestation = get_indexed_attestation(&state, &attestation).unwrap();
bit_0_indices.sort();
bit_1_indices.sort();
assert!(indexed_attestation
.custody_bit_0_indices
.iter()
.copied()
.eq(bit_0_indices.iter().map(|idx| *idx as u64)));
assert!(indexed_attestation
.custody_bit_1_indices
.iter()
.copied()
.eq(bit_1_indices.iter().map(|idx| *idx as u64)));
}
}

View File

@@ -1,8 +1,6 @@
use super::errors::{BlockOperationError, IndexedAttestationInvalid as Invalid};
use super::signature_sets::indexed_attestation_signature_set;
use crate::VerifySignatures;
use std::collections::HashSet;
use std::iter::FromIterator;
use types::*;
type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;
@@ -20,28 +18,15 @@ pub fn is_valid_indexed_attestation<T: EthSpec>(
verify_signatures: VerifySignatures,
spec: &ChainSpec,
) -> Result<()> {
let bit_0_indices = &indexed_attestation.custody_bit_0_indices;
let bit_1_indices = &indexed_attestation.custody_bit_1_indices;
// Verify no index has custody bit equal to 1 [to be removed in phase 1]
verify!(bit_1_indices.is_empty(), Invalid::CustodyBitfieldHasSetBits);
let indices = &indexed_attestation.attesting_indices;
// Verify max number of indices
let total_indices = bit_0_indices.len() + bit_1_indices.len();
verify!(
total_indices <= T::MaxValidatorsPerCommittee::to_usize(),
Invalid::MaxIndicesExceed(T::MaxValidatorsPerCommittee::to_usize(), total_indices)
indices.len() <= T::MaxValidatorsPerCommittee::to_usize(),
Invalid::MaxIndicesExceed(T::MaxValidatorsPerCommittee::to_usize(), indices.len())
);
// Verify index sets are disjoint
let custody_bit_intersection: HashSet<&u64> =
&HashSet::from_iter(bit_0_indices.iter()) & &HashSet::from_iter(bit_1_indices.iter());
verify!(
custody_bit_intersection.is_empty(),
Invalid::CustodyBitValidatorsIntersect
);
// Check that both vectors of indices are sorted
// Check that indices are sorted
let check_sorted = |list: &[u64]| -> Result<()> {
list.windows(2).enumerate().try_for_each(|(i, pair)| {
if pair[0] >= pair[1] {
@@ -52,8 +37,7 @@ pub fn is_valid_indexed_attestation<T: EthSpec>(
})?;
Ok(())
};
check_sorted(&bit_0_indices)?;
check_sorted(&bit_1_indices)?;
check_sorted(indices)?;
if verify_signatures.is_true() {
verify!(

View File

@@ -2,13 +2,13 @@
//! validated individually, or alongside in others in a potentially cheaper bulk operation.
//!
//! This module exposes one function to extract each type of `SignatureSet` from a `BeaconBlock`.
use bls::SignatureSet;
use bls::{SignatureSet, SignedMessage};
use std::convert::TryInto;
use tree_hash::{SignedRoot, TreeHash};
use types::{
AggregateSignature, AttestationDataAndCustodyBit, AttesterSlashing, BeaconBlock,
BeaconBlockHeader, BeaconState, BeaconStateError, ChainSpec, Deposit, Domain, EthSpec, Fork,
Hash256, IndexedAttestation, ProposerSlashing, PublicKey, Signature, VoluntaryExit,
AggregateSignature, AttesterSlashing, BeaconBlock, BeaconBlockHeader, BeaconState,
BeaconStateError, ChainSpec, Deposit, Domain, EthSpec, Fork, Hash256, IndexedAttestation,
ProposerSlashing, PublicKey, Signature, VoluntaryExit,
};
pub type Result<T> = std::result::Result<T, Error>;
@@ -138,16 +138,12 @@ pub fn indexed_attestation_signature_set<'a, 'b, T: EthSpec>(
indexed_attestation: &'b IndexedAttestation<T>,
spec: &'a ChainSpec,
) -> Result<SignatureSet<'a>> {
let message_0 = AttestationDataAndCustodyBit {
data: indexed_attestation.data.clone(),
custody_bit: false,
}
.tree_hash_root();
let message_1 = AttestationDataAndCustodyBit {
data: indexed_attestation.data.clone(),
custody_bit: true,
}
.tree_hash_root();
let message = indexed_attestation.data.tree_hash_root();
let signed_message = SignedMessage::new(
get_pubkeys(state, &indexed_attestation.attesting_indices)?,
message,
);
let domain = spec.get_domain(
indexed_attestation.data.target.epoch,
@@ -155,14 +151,7 @@ pub fn indexed_attestation_signature_set<'a, 'b, T: EthSpec>(
&state.fork,
);
Ok(SignatureSet::dual(
signature,
message_0,
get_pubkeys(state, &indexed_attestation.custody_bit_0_indices)?,
message_1,
get_pubkeys(state, &indexed_attestation.custody_bit_1_indices)?,
domain,
))
Ok(SignatureSet::new(signature, vec![signed_message], domain))
}
/// Returns the signature set for the given `attester_slashing` and corresponding `pubkeys`.

View File

@@ -71,15 +71,13 @@ where
let attestation_2 = &attester_slashing.attestation_2;
let attesting_indices_1 = attestation_1
.custody_bit_0_indices
.attesting_indices
.iter()
.chain(&attestation_1.custody_bit_1_indices)
.cloned()
.collect::<BTreeSet<_>>();
let attesting_indices_2 = attestation_2
.custody_bit_0_indices
.attesting_indices
.iter()
.chain(&attestation_2.custody_bit_1_indices)
.cloned()
.collect::<BTreeSet<_>>();

View File

@@ -9,7 +9,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
/// Details an attestation that can be slashable.
///
/// Spec v0.9.0
/// Spec v0.9.1
#[derive(
Debug,
Clone,
@@ -26,7 +26,6 @@ use tree_hash_derive::{SignedRoot, TreeHash};
pub struct Attestation<T: EthSpec> {
pub aggregation_bits: BitList<T::MaxValidatorsPerCommittee>,
pub data: AttestationData,
pub custody_bits: BitList<T::MaxValidatorsPerCommittee>,
#[signed_root(skip_hashing)]
pub signature: AggregateSignature,
}
@@ -47,7 +46,6 @@ impl<T: EthSpec> Attestation<T> {
debug_assert!(self.signers_disjoint_from(other));
self.aggregation_bits = self.aggregation_bits.union(&other.aggregation_bits);
self.custody_bits = self.custody_bits.union(&other.custody_bits);
self.signature.add_aggregate(&other.signature);
}
}

View File

@@ -1,22 +0,0 @@
use super::AttestationData;
use crate::test_utils::TestRandom;
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
/// Used for pairing an attestation with a proof-of-custody.
///
/// Spec v0.9.0
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
pub struct AttestationDataAndCustodyBit {
pub data: AttestationData,
pub custody_bit: bool,
}
#[cfg(test)]
mod test {
use super::*;
ssz_tests!(AttestationDataAndCustodyBit);
}

View File

@@ -9,7 +9,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
///
/// To be included in an `AttesterSlashing`.
///
/// Spec v0.9.0
/// Spec v0.9.1
#[derive(
Debug,
PartialEq,
@@ -25,8 +25,7 @@ use tree_hash_derive::{SignedRoot, TreeHash};
#[serde(bound = "T: EthSpec")]
pub struct IndexedAttestation<T: EthSpec> {
/// Lists validator registry indices, not committee indices.
pub custody_bit_0_indices: VariableList<u64, T::MaxValidatorsPerCommittee>,
pub custody_bit_1_indices: VariableList<u64, T::MaxValidatorsPerCommittee>,
pub attesting_indices: VariableList<u64, T::MaxValidatorsPerCommittee>,
pub data: AttestationData,
#[signed_root(skip_hashing)]
pub signature: AggregateSignature,

View File

@@ -8,7 +8,6 @@ pub mod test_utils;
pub mod attestation;
pub mod attestation_data;
pub mod attestation_data_and_custody_bit;
pub mod attestation_duty;
pub mod attester_slashing;
pub mod beacon_block;
@@ -42,7 +41,6 @@ use ethereum_types::{H160, H256};
pub use crate::attestation::Attestation;
pub use crate::attestation_data::AttestationData;
pub use crate::attestation_data_and_custody_bit::AttestationDataAndCustodyBit;
pub use crate::attestation_duty::AttestationDuty;
pub use crate::attester_slashing::AttesterSlashing;
pub use crate::beacon_block::BeaconBlock;

View File

@@ -16,17 +16,14 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
let data_builder = TestingAttestationDataBuilder::new(state, index, slot);
let mut aggregation_bits = BitList::with_capacity(committee.len()).unwrap();
let mut custody_bits = BitList::with_capacity(committee.len()).unwrap();
for (i, _) in committee.iter().enumerate() {
custody_bits.set(i, false).unwrap();
aggregation_bits.set(i, false).unwrap();
}
let attestation = Attestation {
aggregation_bits,
data: data_builder.build(),
custody_bits,
signature: AggregateSignature::new(),
};
@@ -46,7 +43,6 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
secret_keys: &[&SecretKey],
fork: &Fork,
spec: &ChainSpec,
custody_bit: bool,
) -> &mut Self {
assert_eq!(
signing_validators.len(),
@@ -66,18 +62,7 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
.set(committee_index, true)
.unwrap();
if custody_bit {
self.attestation
.custody_bits
.set(committee_index, true)
.unwrap();
}
let message = AttestationDataAndCustodyBit {
data: self.attestation.data.clone(),
custody_bit,
}
.tree_hash_root();
let message = self.attestation.data.tree_hash_root();
let domain = spec.get_domain(
self.attestation.data.target.epoch,

View File

@@ -50,26 +50,19 @@ impl TestingAttesterSlashingBuilder {
};
let mut attestation_1 = IndexedAttestation {
custody_bit_0_indices: validator_indices.to_vec().into(),
custody_bit_1_indices: VariableList::empty(),
attesting_indices: validator_indices.to_vec().into(),
data: data_1,
signature: AggregateSignature::new(),
};
let mut attestation_2 = IndexedAttestation {
custody_bit_0_indices: validator_indices.to_vec().into(),
custody_bit_1_indices: VariableList::empty(),
attesting_indices: validator_indices.to_vec().into(),
data: data_2,
signature: AggregateSignature::new(),
};
let add_signatures = |attestation: &mut IndexedAttestation<T>| {
// All validators sign with a `false` custody bit.
let attestation_data_and_custody_bit = AttestationDataAndCustodyBit {
data: attestation.data.clone(),
custody_bit: false,
};
let message = attestation_data_and_custody_bit.tree_hash_root();
let message = attestation.data.tree_hash_root();
for validator_index in validator_indices {
let signature = signer(

View File

@@ -181,13 +181,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
.iter()
.map(|validator_index| secret_keys[*validator_index])
.collect();
builder.sign(
signing_validators,
&signing_secret_keys,
&state.fork,
spec,
false,
);
builder.sign(signing_validators, &signing_secret_keys, &state.fork, spec);
builder.build()
})

View File

@@ -1,5 +1,5 @@
# Bump the test tag here and in .gitlab-ci.yml and CI will take care of updating the cached tarballs
TESTS_TAG := v0.9.0
TESTS_TAG := v0.9.1
TESTS = general minimal mainnet
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))

View File

@@ -38,7 +38,6 @@ type_name!(MainnetEthSpec, "mainnet");
type_name_generic!(Attestation);
type_name!(AttestationData);
type_name!(AttestationDataAndCustodyBit);
type_name_generic!(AttesterSlashing);
type_name_generic!(BeaconBlock);
type_name_generic!(BeaconBlockBody);

View File

@@ -133,10 +133,6 @@ mod ssz_static {
ssz_static_test!(attestation, Attestation<_>, SR);
ssz_static_test!(attestation_data, AttestationData);
ssz_static_test!(
attestation_data_and_custody_bit,
AttestationDataAndCustodyBit
);
ssz_static_test!(attester_slashing, AttesterSlashing<_>);
ssz_static_test!(beacon_block, BeaconBlock<_>, SR);
ssz_static_test!(beacon_block_body, BeaconBlockBody<_>);
@@ -180,7 +176,7 @@ fn epoch_processing_justification_and_finalization() {
#[test]
fn epoch_processing_rewards_and_penalties() {
EpochProcessingHandler::<MinimalEthSpec, RewardsAndPenalties>::run();
EpochProcessingHandler::<MainnetEthSpec, RewardsAndPenalties>::run();
// Note: there are no reward and penalty tests for mainnet yet
}
#[test]

View File

@@ -10,10 +10,7 @@ use beacon_node_attestation::BeaconNodeAttestation;
use core::marker::PhantomData;
use slog::{error, info, warn};
use tree_hash::TreeHash;
use types::{
AggregateSignature, Attestation, AttestationData, AttestationDataAndCustodyBit,
AttestationDuty, BitList,
};
use types::{AggregateSignature, Attestation, AttestationData, AttestationDuty, BitList};
//TODO: Group these errors at a crate level
#[derive(Debug, PartialEq)]
@@ -129,11 +126,7 @@ impl<'a, B: BeaconNodeAttestation, S: Signer, E: EthSpec> AttestationProducer<'a
// build the aggregate signature
let aggregate_signature = {
let message = AttestationDataAndCustodyBit {
data: attestation.clone(),
custody_bit: false,
}
.tree_hash_root();
let message = attestation.tree_hash_root();
let sig = self.signer.sign_message(&message, domain)?;
@@ -143,13 +136,11 @@ impl<'a, B: BeaconNodeAttestation, S: Signer, E: EthSpec> AttestationProducer<'a
};
let mut aggregation_bits = BitList::with_capacity(duties.committee_len).ok()?;
let custody_bits = BitList::with_capacity(duties.committee_len).ok()?;
aggregation_bits.set(duties.committee_position, true).ok()?;
Some(Attestation {
aggregation_bits,
data: attestation,
custody_bits,
signature: aggregate_signature,
})
}