Add attester/proposer slashing endpoints (#856)

* Remove deprecated api_spec.yaml

* add prototype for proposer slashing

* remove clippy warnings

* Add proposer_slashing API

* Prototype for attester slashing API call

* Fix logic error in operation pool

* Finish test for attester_slashing api call

* Clean proposer_slashing test

* Cargo fmt

* Remove useless to_string after format! macro

* Cargo fmt

* Update book with new api calls

* Re-enable proposer slashing verification

* Update book with appropriate test example

* Fix proposer_slashing test

* Update comments and tests for clearer code

* Remove extraneous comments

* Fix test

* Minor fix

* Address reviewer comments

Co-authored-by: pscott <30843220+pscott@users.noreply.github.com>
This commit is contained in:
Pawan Dhananjay
2020-02-14 17:05:18 +05:30
committed by GitHub
parent 7a880dd23c
commit 74c34d1602
6 changed files with 627 additions and 180 deletions

View File

@@ -12,9 +12,12 @@ use remote_beacon_node::{
use std::convert::TryInto;
use std::sync::Arc;
use types::{
test_utils::generate_deterministic_keypair, BeaconBlock, BeaconState, ChainSpec, Domain, Epoch,
EthSpec, MinimalEthSpec, PublicKey, RelativeEpoch, Signature, SignedBeaconBlock, SignedRoot,
Slot, Validator,
test_utils::{
build_double_vote_attester_slashing, build_proposer_slashing,
generate_deterministic_keypair, AttesterSlashingTestTask, ProposerSlashingTestTask,
},
BeaconBlock, BeaconState, ChainSpec, Domain, Epoch, EthSpec, MinimalEthSpec, PublicKey,
RelativeEpoch, Signature, SignedBeaconBlock, SignedRoot, Slot, Validator,
};
use version;
@@ -862,3 +865,158 @@ fn compare_validator_response<T: EthSpec>(
assert_eq!(state.balances[i], balance, "balances");
assert_eq!(state.validators[i], *validator, "validator index");
}
#[test]
fn proposer_slashing() {
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 chain = node
.client
.beacon_chain()
.expect("node should have beacon chain");
let state = chain
.head()
.expect("should have retrieved state")
.beacon_state;
let spec = &chain.spec;
// Check that there are no proposer slashings before insertion
let (proposer_slashings, _attester_slashings) = chain.op_pool.get_slashings(&state, spec);
assert_eq!(proposer_slashings.len(), 0);
let slot = state.slot;
let proposer_index = chain
.block_proposer(slot)
.expect("should get proposer index");
let keypair = generate_deterministic_keypair(proposer_index);
let key = &keypair.sk;
let fork = &state.fork;
let proposer_slashing = build_proposer_slashing::<E>(
ProposerSlashingTestTask::Valid,
proposer_index as u64,
&key,
fork,
spec,
);
let result = env
.runtime()
.block_on(
remote_node
.http
.beacon()
.proposer_slashing(proposer_slashing.clone()),
)
.expect("should fetch from http api");
assert!(result, true);
// Length should be just one as we've inserted only one proposer slashing
let (proposer_slashings, _attester_slashings) = chain.op_pool.get_slashings(&state, spec);
assert_eq!(proposer_slashings.len(), 1);
assert_eq!(proposer_slashing.clone(), proposer_slashings[0]);
let mut invalid_proposer_slashing = build_proposer_slashing::<E>(
ProposerSlashingTestTask::Valid,
proposer_index as u64,
&key,
fork,
spec,
);
invalid_proposer_slashing.signed_header_2 = invalid_proposer_slashing.signed_header_1.clone();
let result = env.runtime().block_on(
remote_node
.http
.beacon()
.proposer_slashing(invalid_proposer_slashing),
);
assert!(result.is_err());
// Length should still be one as we've inserted nothing since last time.
let (proposer_slashings, _attester_slashings) = chain.op_pool.get_slashings(&state, spec);
assert_eq!(proposer_slashings.len(), 1);
assert_eq!(proposer_slashing, proposer_slashings[0]);
}
#[test]
fn attester_slashing() {
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 chain = node
.client
.beacon_chain()
.expect("node should have beacon chain");
let state = chain
.head()
.expect("should have retrieved state")
.beacon_state;
let slot = state.slot;
let spec = &chain.spec;
let proposer_index = chain
.block_proposer(slot)
.expect("should get proposer index");
let keypair = generate_deterministic_keypair(proposer_index);
let secret_keys = vec![&keypair.sk];
let validator_indices = vec![proposer_index as u64];
let fork = &state.fork;
// Checking there are no attester slashings before insertion
let (_proposer_slashings, attester_slashings) = chain.op_pool.get_slashings(&state, spec);
assert_eq!(attester_slashings.len(), 0);
let attester_slashing = build_double_vote_attester_slashing(
AttesterSlashingTestTask::Valid,
&validator_indices[..],
&secret_keys[..],
fork,
spec,
);
let result = env
.runtime()
.block_on(
remote_node
.http
.beacon()
.attester_slashing(attester_slashing.clone()),
)
.expect("should fetch from http api");
assert!(result, true);
// Length should be just one as we've inserted only one attester slashing
let (_proposer_slashings, attester_slashings) = chain.op_pool.get_slashings(&state, spec);
assert_eq!(attester_slashings.len(), 1);
assert_eq!(attester_slashing, attester_slashings[0]);
// Building an invalid attester slashing
let mut invalid_attester_slashing = build_double_vote_attester_slashing(
AttesterSlashingTestTask::Valid,
&validator_indices[..],
&secret_keys[..],
fork,
spec,
);
invalid_attester_slashing.attestation_2 = invalid_attester_slashing.attestation_1.clone();
let result = env.runtime().block_on(
remote_node
.http
.beacon()
.attester_slashing(invalid_attester_slashing),
);
assert!(result.is_err());
// Length should still be one as we've failed to insert the attester slashing.
let (_proposer_slashings, attester_slashings) = chain.op_pool.get_slashings(&state, spec);
assert_eq!(attester_slashings.len(), 1);
assert_eq!(attester_slashing, attester_slashings[0]);
}