Merge remote-tracking branch 'origin/master' into v0.9

This commit is contained in:
Michael Sproul
2019-11-19 11:04:17 +11:00
111 changed files with 9944 additions and 1729 deletions

View File

@@ -16,6 +16,7 @@ eth2_hashing = "0.1.0"
hex = "0.3"
int_to_bytes = { path = "../utils/int_to_bytes" }
log = "0.4.8"
merkle_proof = { path = "../utils/merkle_proof" }
rayon = "1.2.0"
rand = "0.7.2"
serde = "1.0.102"

View File

@@ -205,7 +205,7 @@ impl<T: EthSpec> BeaconState<T> {
// Versioning
genesis_time,
slot: spec.genesis_slot,
fork: Fork::genesis(T::genesis_epoch()),
fork: spec.genesis_fork.clone(),
// History
latest_block_header: BeaconBlock::<T>::empty(spec).temporary_block_header(),

View File

@@ -89,8 +89,15 @@ pub struct ChainSpec {
*/
pub safe_slots_to_update_justified: u64,
/*
* Eth1
*/
pub eth1_follow_distance: u64,
pub boot_nodes: Vec<String>,
pub network_id: u8,
pub genesis_fork: Fork,
}
impl ChainSpec {
@@ -122,6 +129,22 @@ impl ChainSpec {
u64::from_le_bytes(fork_and_domain)
}
/// Get the domain for a deposit signature.
///
/// Deposits are valid across forks, thus the deposit domain is computed
/// with the fork zeroed.
///
/// Spec v0.8.1
pub fn get_deposit_domain(&self) -> u64 {
let mut bytes: Vec<u8> = int_to_bytes4(self.domain_deposit);
bytes.append(&mut vec![0; 4]);
let mut fork_and_domain = [0; 8];
fork_and_domain.copy_from_slice(&bytes);
u64::from_le_bytes(fork_and_domain)
}
/// Returns a `ChainSpec` compatible with the Ethereum Foundation specification.
///
/// Spec v0.9.1
@@ -194,6 +217,20 @@ impl ChainSpec {
*/
safe_slots_to_update_justified: 8,
/*
* Eth1
*/
eth1_follow_distance: 1_024,
/*
* Fork
*/
genesis_fork: Fork {
previous_version: [0; 4],
current_version: [0; 4],
epoch: Epoch::new(0),
},
/*
* Network specific
*/
@@ -217,6 +254,7 @@ impl ChainSpec {
min_genesis_active_validator_count: 64,
network_id: 2, // lighthouse testnet network id
boot_nodes,
eth1_follow_distance: 16,
..ChainSpec::mainnet()
}
}
@@ -255,7 +293,7 @@ mod tests {
}
fn test_domain(domain_type: Domain, raw_domain: u32, spec: &ChainSpec) {
let fork = Fork::genesis(Epoch::new(0));
let fork = &spec.genesis_fork;
let epoch = Epoch::new(0);
let domain = spec.get_domain(epoch, domain_type, &fork);

View File

@@ -7,6 +7,8 @@ use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
pub const DEPOSIT_TREE_DEPTH: usize = 32;
/// A deposit to potentially become a beacon chain validator.
///
/// Spec v0.9.1

View File

@@ -36,15 +36,9 @@ impl DepositData {
/// Generate the signature for a given DepositData details.
///
/// Spec v0.9.1
pub fn create_signature(
&self,
secret_key: &SecretKey,
epoch: Epoch,
fork: &Fork,
spec: &ChainSpec,
) -> SignatureBytes {
pub fn create_signature(&self, secret_key: &SecretKey, spec: &ChainSpec) -> SignatureBytes {
let msg = self.signed_root();
let domain = spec.get_domain(epoch, Domain::Deposit, fork);
let domain = spec.get_deposit_domain();
SignatureBytes::from(Signature::new(msg.as_slice(), domain, secret_key))
}

View File

@@ -10,7 +10,18 @@ use tree_hash_derive::TreeHash;
///
/// Spec v0.9.1
#[derive(
Debug, PartialEq, Clone, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
Debug,
PartialEq,
Clone,
Default,
Eq,
Hash,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
)]
pub struct Eth1Data {
pub deposit_root: Hash256,

View File

@@ -28,17 +28,6 @@ pub struct Fork {
}
impl Fork {
/// Initialize the `Fork` from the genesis parameters in the `spec`.
///
/// Spec v0.9.1
pub fn genesis(genesis_epoch: Epoch) -> Self {
Self {
previous_version: [0; 4],
current_version: [0; 4],
epoch: genesis_epoch,
}
}
/// Return the fork version of the given ``epoch``.
///
/// Spec v0.9.1
@@ -56,24 +45,6 @@ mod tests {
ssz_tests!(Fork);
fn test_genesis(epoch: Epoch) {
let fork = Fork::genesis(epoch);
assert_eq!(fork.epoch, epoch, "epoch incorrect");
assert_eq!(
fork.previous_version, fork.current_version,
"previous and current are not identical"
);
}
#[test]
fn genesis() {
test_genesis(Epoch::new(0));
test_genesis(Epoch::new(11));
test_genesis(Epoch::new(2_u64.pow(63)));
test_genesis(Epoch::max_value());
}
#[test]
fn get_fork_version() {
let previous_version = [1; 4];

View File

@@ -50,7 +50,7 @@ pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee};
pub use crate::beacon_state::{Error as BeaconStateError, *};
pub use crate::chain_spec::{ChainSpec, Domain};
pub use crate::checkpoint::Checkpoint;
pub use crate::deposit::Deposit;
pub use crate::deposit::{Deposit, DEPOSIT_TREE_DEPTH};
pub use crate::deposit_data::DepositData;
pub use crate::eth1_data::Eth1Data;
pub use crate::fork::Fork;

View File

@@ -1,4 +1,4 @@
use crate::test_utils::TestingAttestationDataBuilder;
use crate::test_utils::{AttestationTestTask, TestingAttestationDataBuilder};
use crate::*;
use tree_hash::TreeHash;
@@ -12,12 +12,26 @@ pub struct TestingAttestationBuilder<T: EthSpec> {
impl<T: EthSpec> TestingAttestationBuilder<T> {
/// Create a new attestation builder.
pub fn new(state: &BeaconState<T>, committee: &[usize], slot: Slot, index: u64) -> Self {
let data_builder = TestingAttestationDataBuilder::new(state, index, slot);
pub fn new(
test_task: AttestationTestTask,
state: &BeaconState<T>,
committee: &[usize],
slot: Slot,
index: u64,
spec: &ChainSpec,
) -> Self {
let data_builder = TestingAttestationDataBuilder::new(test_task, state, index, slot, spec);
let mut aggregation_bits = BitList::with_capacity(committee.len()).unwrap();
let mut aggregation_bits_len = committee.len();
for (i, _) in committee.iter().enumerate() {
match test_task {
AttestationTestTask::BadAggregationBitfieldLen => aggregation_bits_len += 1,
_ => (),
}
let mut aggregation_bits = BitList::with_capacity(aggregation_bits_len).unwrap();
for i in 0..committee.len() {
aggregation_bits.set(i, false).unwrap();
}
@@ -39,6 +53,7 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
/// keypair must be that of the first signing validator.
pub fn sign(
&mut self,
test_task: AttestationTestTask,
signing_validators: &[usize],
secret_keys: &[&SecretKey],
fork: &Fork,
@@ -57,10 +72,15 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
.position(|v| *v == *validator_index)
.expect("Signing validator not in attestation committee");
self.attestation
.aggregation_bits
.set(committee_index, true)
.unwrap();
match test_task {
AttestationTestTask::BadIndexedAttestationBadSignature => (),
_ => {
self.attestation
.aggregation_bits
.set(committee_index, true)
.unwrap();
}
}
let message = self.attestation.data.tree_hash_root();
@@ -70,7 +90,12 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
fork,
);
let signature = Signature::new(&message, domain, secret_keys[key_index]);
let index = if test_task == AttestationTestTask::BadSignature {
0
} else {
key_index
};
let signature = Signature::new(&message, domain, secret_keys[index]);
self.attestation.signature.add(&signature)
}

View File

@@ -1,3 +1,4 @@
use crate::test_utils::AttestationTestTask;
use crate::*;
/// Builds an `AttestationData` to be used for testing purposes.
@@ -10,19 +11,25 @@ pub struct TestingAttestationDataBuilder {
impl TestingAttestationDataBuilder {
/// Configures a new `AttestationData` which attests to all of the same parameters as the
/// state.
pub fn new<T: EthSpec>(state: &BeaconState<T>, index: u64, slot: Slot) -> Self {
pub fn new<T: EthSpec>(
test_task: AttestationTestTask,
state: &BeaconState<T>,
mut index: u64,
mut slot: Slot,
spec: &ChainSpec,
) -> Self {
let current_epoch = state.current_epoch();
let previous_epoch = state.previous_epoch();
let is_previous_epoch = slot.epoch(T::slots_per_epoch()) != current_epoch;
let source = if is_previous_epoch {
let mut source = if is_previous_epoch {
state.previous_justified_checkpoint.clone()
} else {
state.current_justified_checkpoint.clone()
};
let target = if is_previous_epoch {
let mut target = if is_previous_epoch {
Checkpoint {
epoch: previous_epoch,
root: *state
@@ -38,12 +45,49 @@ impl TestingAttestationDataBuilder {
}
};
let beacon_block_root = *state.get_block_root(slot).unwrap();
match test_task {
// FIXME(sproul)
AttestationTestTask::NoCommiteeForShard => index += 2,
// AttestationTestTask::BadShard => index = T::ShardCount::to_u64(),
AttestationTestTask::IncludedTooEarly => {
slot = state.slot - spec.min_attestation_inclusion_delay + 1
}
AttestationTestTask::IncludedTooLate => slot -= T::SlotsPerEpoch::to_u64(),
AttestationTestTask::BadTargetEpoch => {
target = Checkpoint {
epoch: Epoch::from(5 as u64),
root: Hash256::zero(),
}
}
AttestationTestTask::WrongJustifiedCheckpoint => {
source = Checkpoint {
epoch: Epoch::from(0 as u64),
root: Hash256::zero(),
}
}
AttestationTestTask::BadTargetTooLow => {
target = Checkpoint {
epoch: Epoch::from(0 as u64),
root: Hash256::zero(),
}
}
AttestationTestTask::BadTargetTooHigh => {
target = Checkpoint {
epoch: Epoch::from(10 as u64),
root: Hash256::zero(),
}
}
_ => (),
}
let data = AttestationData {
slot,
index,
// LMD GHOST vote
beacon_block_root: *state.get_block_root(slot).unwrap(),
beacon_block_root,
// FFG Vote
source,

View File

@@ -1,3 +1,4 @@
use crate::test_utils::AttesterSlashingTestTask;
use crate::*;
use tree_hash::TreeHash;
@@ -17,7 +18,11 @@ impl TestingAttesterSlashingBuilder {
/// - `domain: Domain`
///
/// Where domain is a domain "constant" (e.g., `spec.domain_attestation`).
pub fn double_vote<F, T: EthSpec>(validator_indices: &[u64], signer: F) -> AttesterSlashing<T>
pub fn double_vote<F, T: EthSpec>(
test_task: AttesterSlashingTestTask,
validator_indices: &[u64],
signer: F,
) -> AttesterSlashing<T>
where
F: Fn(u64, &[u8], Epoch, Domain) -> Signature,
{
@@ -44,19 +49,35 @@ impl TestingAttesterSlashingBuilder {
target: checkpoint_1,
};
let data_2 = AttestationData {
target: checkpoint_2,
..data_1.clone()
let data_2 = if test_task == AttesterSlashingTestTask::NotSlashable {
AttestationData { ..data_1.clone() }
} else {
AttestationData {
target: checkpoint_2,
..data_1.clone()
}
};
let mut attestation_1 = IndexedAttestation {
attesting_indices: validator_indices.to_vec().into(),
attesting_indices: if test_task == AttesterSlashingTestTask::IndexedAttestation1Invalid
{
// Trigger bad validator indices ordering error.
vec![1, 0].into()
} else {
validator_indices.to_vec().into()
},
data: data_1,
signature: AggregateSignature::new(),
};
let mut attestation_2 = IndexedAttestation {
attesting_indices: validator_indices.to_vec().into(),
attesting_indices: if test_task == AttesterSlashingTestTask::IndexedAttestation2Invalid
{
// Trigger bad validator indices ordering error.
vec![1, 0].into()
} else {
validator_indices.to_vec().into()
},
data: data_2,
signature: AggregateSignature::new(),
};

View File

@@ -3,8 +3,11 @@ use crate::{
TestingAttestationBuilder, TestingAttesterSlashingBuilder, TestingDepositBuilder,
TestingProposerSlashingBuilder, TestingVoluntaryExitBuilder,
},
typenum::U4294967296,
*,
};
use int_to_bytes::int_to_bytes32;
use merkle_proof::MerkleTree;
use rayon::prelude::*;
use tree_hash::{SignedRoot, TreeHash};
@@ -15,6 +18,67 @@ pub struct TestingBeaconBlockBuilder<T: EthSpec> {
pub block: BeaconBlock<T>,
}
/// Enum used for passing test options to builder
#[derive(PartialEq, Clone, Copy)]
pub enum DepositTestTask {
Valid,
BadPubKey,
BadSig,
InvalidPubKey,
NoReset,
}
/// Enum used for passing test options to builder
#[derive(PartialEq, Clone, Copy)]
pub enum ExitTestTask {
AlreadyInitiated,
AlreadyExited,
BadSignature,
FutureEpoch,
NotActive,
Valid,
ValidatorUnknown,
}
/// Enum used for passing test options to builder
#[derive(PartialEq, Clone, Copy)]
pub enum AttestationTestTask {
Valid,
NoCommiteeForShard,
WrongJustifiedCheckpoint,
BadTargetTooLow,
BadTargetTooHigh,
BadShard,
BadIndexedAttestationBadSignature,
BadAggregationBitfieldLen,
BadSignature,
ValidatorUnknown,
IncludedTooEarly,
IncludedTooLate,
BadTargetEpoch,
}
/// Enum used for passing test options to builder
#[derive(PartialEq, Clone, Copy)]
pub enum AttesterSlashingTestTask {
Valid,
NotSlashable,
IndexedAttestation1Invalid,
IndexedAttestation2Invalid,
}
/// Enum used for passing test options to builder
#[derive(PartialEq, Clone, Copy)]
pub enum ProposerSlashingTestTask {
Valid,
ProposerUnknown,
ProposalEpochMismatch,
ProposalsIdentical,
ProposerNotSlashable,
BadProposal1Signature,
BadProposal2Signature,
}
impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
/// Create a new builder from genesis.
pub fn new(spec: &ChainSpec) -> Self {
@@ -61,13 +125,14 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
/// Inserts a signed, valid `ProposerSlashing` for the validator.
pub fn insert_proposer_slashing(
&mut self,
test_task: ProposerSlashingTestTask,
validator_index: u64,
secret_key: &SecretKey,
fork: &Fork,
spec: &ChainSpec,
) {
let proposer_slashing =
build_proposer_slashing::<T>(validator_index, secret_key, fork, spec);
build_proposer_slashing::<T>(test_task, validator_index, secret_key, fork, spec);
self.block
.body
.proposer_slashings
@@ -78,18 +143,20 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
/// Inserts a signed, valid `AttesterSlashing` for each validator index in `validator_indices`.
pub fn insert_attester_slashing(
&mut self,
test_task: AttesterSlashingTestTask,
validator_indices: &[u64],
secret_keys: &[&SecretKey],
fork: &Fork,
spec: &ChainSpec,
) {
let attester_slashing =
build_double_vote_attester_slashing(validator_indices, secret_keys, fork, spec);
self.block
.body
.attester_slashings
.push(attester_slashing)
.unwrap();
let attester_slashing = build_double_vote_attester_slashing(
test_task,
validator_indices,
secret_keys,
fork,
spec,
);
let _ = self.block.body.attester_slashings.push(attester_slashing);
}
/// Fills the block with `num_attestations` attestations.
@@ -103,6 +170,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
/// to aggregate these split attestations.
pub fn insert_attestations(
&mut self,
test_task: AttestationTestTask,
state: &BeaconState<T>,
secret_keys: &[&SecretKey],
num_attestations: usize,
@@ -175,13 +243,21 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
let attestations: Vec<_> = committees
.par_iter()
.map(|(slot, committee, signing_validators, index)| {
let mut builder = TestingAttestationBuilder::new(state, committee, *slot, *index);
let mut builder = TestingAttestationBuilder::new(
test_task, state, committee, *slot, *index, spec,
);
let signing_secret_keys: Vec<&SecretKey> = signing_validators
.iter()
.map(|validator_index| secret_keys[*validator_index])
.collect();
builder.sign(signing_validators, &signing_secret_keys, &state.fork, spec);
builder.sign(
test_task,
signing_validators,
&signing_secret_keys,
&state.fork,
spec,
);
builder.build()
})
@@ -195,47 +271,108 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
}
/// Insert a `Valid` deposit into the state.
pub fn insert_deposit(
pub fn insert_deposits(
&mut self,
amount: u64,
test_task: DepositTestTask,
// TODO: deal with the fact deposits no longer have explicit indices
_index: u64,
state: &BeaconState<T>,
num_deposits: u64,
state: &mut BeaconState<T>,
spec: &ChainSpec,
) {
let keypair = Keypair::random();
// Vector containing deposits' data
let mut datas = vec![];
for _ in 0..num_deposits {
let keypair = Keypair::random();
let mut builder = TestingDepositBuilder::new(keypair.pk.clone(), amount);
builder.sign(
&keypair,
state.slot.epoch(T::slots_per_epoch()),
&state.fork,
spec,
);
let mut builder = TestingDepositBuilder::new(keypair.pk.clone(), amount);
builder.sign(test_task, &keypair, spec);
datas.push(builder.build().data);
}
self.block.body.deposits.push(builder.build()).unwrap()
// Vector containing all leaves
let leaves = datas
.iter()
.map(|data| Hash256::from_slice(&data.tree_hash_root()))
.collect::<Vec<_>>();
// Building a VarList from leaves
let deposit_data_list = VariableList::<_, U4294967296>::from(leaves.clone());
// Setting the deposit_root to be the tree_hash_root of the VarList
state.eth1_data.deposit_root = Hash256::from_slice(&deposit_data_list.tree_hash_root());
// Building the merkle tree used for generating proofs
let tree = MerkleTree::create(&leaves[..], spec.deposit_contract_tree_depth as usize);
// Building proofs
let mut proofs = vec![];
for i in 0..leaves.len() {
let (_, mut proof) = tree.generate_proof(i, spec.deposit_contract_tree_depth as usize);
proof.push(Hash256::from_slice(&int_to_bytes32(leaves.len() as u64)));
proofs.push(proof);
}
// Building deposits
let deposits = datas
.into_par_iter()
.zip(proofs.into_par_iter())
.map(|(data, proof)| (data, proof.into()))
.map(|(data, proof)| Deposit { proof, data })
.collect::<Vec<_>>();
// Pushing deposits to block body
for deposit in deposits {
let _ = self.block.body.deposits.push(deposit);
}
// Manually setting the deposit_count to process deposits
// This is for test purposes only
if test_task == DepositTestTask::NoReset {
state.eth1_data.deposit_count += num_deposits;
} else {
state.eth1_deposit_index = 0;
state.eth1_data.deposit_count = num_deposits;
}
}
/// Insert a `Valid` exit into the state.
pub fn insert_exit(
&mut self,
state: &BeaconState<T>,
validator_index: u64,
test_task: ExitTestTask,
state: &mut BeaconState<T>,
mut validator_index: u64,
secret_key: &SecretKey,
spec: &ChainSpec,
) {
let mut builder = TestingVoluntaryExitBuilder::new(
state.slot.epoch(T::slots_per_epoch()),
validator_index,
);
let sk = &mut secret_key.clone();
let mut exit_epoch = state.slot.epoch(T::slots_per_epoch());
builder.sign(secret_key, &state.fork, spec);
match test_task {
ExitTestTask::BadSignature => *sk = SecretKey::random(),
ExitTestTask::ValidatorUnknown => validator_index = 4242,
ExitTestTask::AlreadyExited => {
state.validators[validator_index as usize].exit_epoch = Epoch::from(314_159 as u64)
}
// FIXME: disabled in v0.9
ExitTestTask::NotActive => {
state.validators[validator_index as usize].activation_epoch =
Epoch::from(314_159 as u64)
}
ExitTestTask::FutureEpoch => exit_epoch = spec.far_future_epoch,
_ => (),
}
let mut builder = TestingVoluntaryExitBuilder::new(exit_epoch, validator_index);
builder.sign(sk, &state.fork, spec);
self.block
.body
.voluntary_exits
.push(builder.build())
.unwrap()
.unwrap();
}
/// Signs and returns the block, consuming the builder.
@@ -254,6 +391,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
///
/// Signs the message using a `BeaconChainHarness`.
fn build_proposer_slashing<T: EthSpec>(
test_task: ProposerSlashingTestTask,
validator_index: u64,
secret_key: &SecretKey,
fork: &Fork,
@@ -264,13 +402,14 @@ fn build_proposer_slashing<T: EthSpec>(
Signature::new(message, domain, secret_key)
};
TestingProposerSlashingBuilder::double_vote::<T, _>(validator_index, signer)
TestingProposerSlashingBuilder::double_vote::<T, _>(test_task, validator_index, signer)
}
/// Builds an `AttesterSlashing` for some `validator_indices`.
///
/// Signs the message using a `BeaconChainHarness`.
fn build_double_vote_attester_slashing<T: EthSpec>(
test_task: AttesterSlashingTestTask,
validator_indices: &[u64],
secret_keys: &[&SecretKey],
fork: &Fork,
@@ -285,5 +424,5 @@ fn build_double_vote_attester_slashing<T: EthSpec>(
Signature::new(message, domain, secret_keys[key_index])
};
TestingAttesterSlashingBuilder::double_vote(validator_indices, signer)
TestingAttesterSlashingBuilder::double_vote(test_task, validator_indices, signer)
}

View File

@@ -1,5 +1,5 @@
use super::super::{generate_deterministic_keypairs, KeypairsFile};
use crate::test_utils::TestingPendingAttestationBuilder;
use crate::test_utils::{AttestationTestTask, TestingPendingAttestationBuilder};
use crate::*;
use bls::get_withdrawal_credentials;
use dirs;
@@ -222,6 +222,7 @@ impl<T: EthSpec> TestingBeaconStateBuilder<T> {
for beacon_committee in committees {
let mut builder = TestingPendingAttestationBuilder::new(
AttestationTestTask::Valid,
state,
beacon_committee.index,
slot,

View File

@@ -1,3 +1,4 @@
use crate::test_utils::DepositTestTask;
use crate::*;
use bls::{get_withdrawal_credentials, PublicKeyBytes, SignatureBytes};
@@ -29,18 +30,31 @@ impl TestingDepositBuilder {
/// - `pubkey` to the signing pubkey.
/// - `withdrawal_credentials` to the signing pubkey.
/// - `proof_of_possession`
pub fn sign(&mut self, keypair: &Keypair, epoch: Epoch, fork: &Fork, spec: &ChainSpec) {
pub fn sign(&mut self, test_task: DepositTestTask, keypair: &Keypair, spec: &ChainSpec) {
let new_key = Keypair::random();
let mut pubkeybytes = PublicKeyBytes::from(keypair.pk.clone());
let mut secret_key = keypair.sk.clone();
match test_task {
DepositTestTask::BadPubKey => pubkeybytes = PublicKeyBytes::from(new_key.pk.clone()),
DepositTestTask::InvalidPubKey => {
// Creating invalid public key bytes
let mut public_key_bytes: Vec<u8> = vec![0; 48];
public_key_bytes[0] = 255;
pubkeybytes = PublicKeyBytes::from_bytes(&public_key_bytes).unwrap();
}
DepositTestTask::BadSig => secret_key = new_key.sk,
_ => (),
}
let withdrawal_credentials = Hash256::from_slice(
&get_withdrawal_credentials(&keypair.pk, spec.bls_withdrawal_prefix_byte)[..],
);
self.deposit.data.pubkey = PublicKeyBytes::from(keypair.pk.clone());
// Building the data and signing it
self.deposit.data.pubkey = pubkeybytes;
self.deposit.data.withdrawal_credentials = withdrawal_credentials;
self.deposit.data.signature =
self.deposit
.data
.create_signature(&keypair.sk, epoch, fork, spec);
self.deposit.data.signature = self.deposit.data.create_signature(&secret_key, spec);
}
/// Builds the deposit, consuming the builder.

View File

@@ -1,4 +1,4 @@
use crate::test_utils::TestingAttestationDataBuilder;
use crate::test_utils::{AttestationTestTask, TestingAttestationDataBuilder};
use crate::*;
/// Builds an `AttesterSlashing` to be used for testing purposes.
@@ -15,8 +15,14 @@ impl<T: EthSpec> TestingPendingAttestationBuilder<T> {
///
/// * The aggregation and custody bitfields will all be empty, they need to be set with
/// `Self::add_committee_participation`.
pub fn new(state: &BeaconState<T>, index: u64, slot: Slot, spec: &ChainSpec) -> Self {
let data_builder = TestingAttestationDataBuilder::new(state, index, slot);
pub fn new(
test_task: AttestationTestTask,
state: &BeaconState<T>,
index: u64,
slot: Slot,
spec: &ChainSpec,
) -> Self {
let data_builder = TestingAttestationDataBuilder::new(test_task, state, index, slot, spec);
let proposer_index = state.get_beacon_proposer_index(slot, spec).unwrap() as u64;

View File

@@ -1,3 +1,4 @@
use crate::test_utils::ProposerSlashingTestTask;
use crate::*;
use tree_hash::SignedRoot;
@@ -17,14 +18,22 @@ impl TestingProposerSlashingBuilder {
/// - `domain: Domain`
///
/// Where domain is a domain "constant" (e.g., `spec.domain_attestation`).
pub fn double_vote<T, F>(proposer_index: u64, signer: F) -> ProposerSlashing
pub fn double_vote<T, F>(
test_task: ProposerSlashingTestTask,
mut proposer_index: u64,
signer: F,
) -> ProposerSlashing
where
T: EthSpec,
F: Fn(u64, &[u8], Epoch, Domain) -> Signature,
{
let slot = Slot::new(0);
let hash_1 = Hash256::from([1; 32]);
let hash_2 = Hash256::from([2; 32]);
let hash_2 = if test_task == ProposerSlashingTestTask::ProposalsIdentical {
hash_1.clone()
} else {
Hash256::from([2; 32])
};
let mut header_1 = BeaconBlockHeader {
slot,
@@ -34,22 +43,37 @@ impl TestingProposerSlashingBuilder {
signature: Signature::empty_signature(),
};
let slot_2 = if test_task == ProposerSlashingTestTask::ProposalEpochMismatch {
Slot::new(128)
} else {
Slot::new(0)
};
let mut header_2 = BeaconBlockHeader {
parent_root: hash_2,
slot: slot_2,
..header_1.clone()
};
let epoch = slot.epoch(T::slots_per_epoch());
header_1.signature = {
let message = header_1.signed_root();
signer(proposer_index, &message[..], epoch, Domain::BeaconProposer)
};
if test_task != ProposerSlashingTestTask::BadProposal1Signature {
header_1.signature = {
let message = header_1.signed_root();
signer(proposer_index, &message[..], epoch, Domain::BeaconProposer)
};
}
header_2.signature = {
let message = header_2.signed_root();
signer(proposer_index, &message[..], epoch, Domain::BeaconProposer)
};
if test_task != ProposerSlashingTestTask::BadProposal2Signature {
header_2.signature = {
let message = header_2.signed_root();
signer(proposer_index, &message[..], epoch, Domain::BeaconProposer)
};
}
if test_task == ProposerSlashingTestTask::ProposerUnknown {
proposer_index = 3_141_592;
}
ProposerSlashing {
proposer_index,