Add graffiti cli flag to the validator client. (#1425)
## Issue Addressed #1419 ## Proposed Changes Creates a `--graffiti` cli flag in the validator client. If the flag is set, it overrides graffiti in the beacon node. ## Additional Info
This commit is contained in:
parent
95b55d7170
commit
ec84183e05
@ -1564,12 +1564,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
&self,
|
&self,
|
||||||
randao_reveal: Signature,
|
randao_reveal: Signature,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
|
validator_graffiti: Option<Graffiti>,
|
||||||
) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
|
) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
|
||||||
let state = self
|
let state = self
|
||||||
.state_at_slot(slot - 1, StateSkipConfig::WithStateRoots)
|
.state_at_slot(slot - 1, StateSkipConfig::WithStateRoots)
|
||||||
.map_err(|_| BlockProductionError::UnableToProduceAtSlot(slot))?;
|
.map_err(|_| BlockProductionError::UnableToProduceAtSlot(slot))?;
|
||||||
|
|
||||||
self.produce_block_on_state(state, slot, randao_reveal)
|
self.produce_block_on_state(state, slot, randao_reveal, validator_graffiti)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a block for some `slot` upon the given `state`.
|
/// Produce a block for some `slot` upon the given `state`.
|
||||||
@ -1585,6 +1586,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
mut state: BeaconState<T::EthSpec>,
|
mut state: BeaconState<T::EthSpec>,
|
||||||
produce_at_slot: Slot,
|
produce_at_slot: Slot,
|
||||||
randao_reveal: Signature,
|
randao_reveal: Signature,
|
||||||
|
validator_graffiti: Option<Graffiti>,
|
||||||
) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
|
) -> Result<BeaconBlockAndState<T::EthSpec>, BlockProductionError> {
|
||||||
metrics::inc_counter(&metrics::BLOCK_PRODUCTION_REQUESTS);
|
metrics::inc_counter(&metrics::BLOCK_PRODUCTION_REQUESTS);
|
||||||
let timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_TIMES);
|
let timer = metrics::start_timer(&metrics::BLOCK_PRODUCTION_TIMES);
|
||||||
@ -1652,6 +1654,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Override the beacon node's graffiti with graffiti from the validator, if present.
|
||||||
|
let graffiti = match validator_graffiti {
|
||||||
|
Some(graffiti) => graffiti,
|
||||||
|
None => self.graffiti,
|
||||||
|
};
|
||||||
|
|
||||||
let mut block = SignedBeaconBlock {
|
let mut block = SignedBeaconBlock {
|
||||||
message: BeaconBlock {
|
message: BeaconBlock {
|
||||||
slot: state.slot,
|
slot: state.slot,
|
||||||
@ -1661,7 +1669,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
body: BeaconBlockBody {
|
body: BeaconBlockBody {
|
||||||
randao_reveal,
|
randao_reveal,
|
||||||
eth1_data,
|
eth1_data,
|
||||||
graffiti: self.graffiti,
|
graffiti,
|
||||||
proposer_slashings: proposer_slashings.into(),
|
proposer_slashings: proposer_slashings.into(),
|
||||||
attester_slashings: attester_slashings.into(),
|
attester_slashings: attester_slashings.into(),
|
||||||
attestations: self
|
attestations: self
|
||||||
|
@ -520,7 +520,7 @@ where
|
|||||||
|
|
||||||
let (block, state) = self
|
let (block, state) = self
|
||||||
.chain
|
.chain
|
||||||
.produce_block_on_state(state, slot, randao_reveal)
|
.produce_block_on_state(state, slot, randao_reveal, None)
|
||||||
.expect("should produce block");
|
.expect("should produce block");
|
||||||
|
|
||||||
let signed_block = block.sign(sk, &state.fork, state.genesis_validators_root, &self.spec);
|
let signed_block = block.sign(sk, &state.fork, state.genesis_validators_root, &self.spec);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use crate::helpers::{check_content_type_for_json, publish_beacon_block_to_network};
|
use crate::helpers::{
|
||||||
|
check_content_type_for_json, parse_hex_ssz_bytes, publish_beacon_block_to_network,
|
||||||
|
};
|
||||||
use crate::response_builder::ResponseBuilder;
|
use crate::response_builder::ResponseBuilder;
|
||||||
use crate::{ApiError, ApiResult, NetworkChannel, UrlQuery};
|
use crate::{ApiError, ApiResult, NetworkChannel, UrlQuery};
|
||||||
use beacon_chain::{
|
use beacon_chain::{
|
||||||
@ -288,8 +290,14 @@ pub fn get_new_beacon_block<T: BeaconChainTypes>(
|
|||||||
let slot = query.slot()?;
|
let slot = query.slot()?;
|
||||||
let randao_reveal = query.randao_reveal()?;
|
let randao_reveal = query.randao_reveal()?;
|
||||||
|
|
||||||
|
let validator_graffiti = if let Some((_key, value)) = query.first_of_opt(&["graffiti"]) {
|
||||||
|
Some(parse_hex_ssz_bytes(&value)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let (new_block, _state) = beacon_chain
|
let (new_block, _state) = beacon_chain
|
||||||
.produce_block(randao_reveal, slot)
|
.produce_block(randao_reveal, slot, validator_graffiti)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!(
|
error!(
|
||||||
log,
|
log,
|
||||||
|
@ -460,7 +460,7 @@ fn validator_block_post() {
|
|||||||
remote_node
|
remote_node
|
||||||
.http
|
.http
|
||||||
.validator()
|
.validator()
|
||||||
.produce_block(slot, randao_reveal),
|
.produce_block(slot, randao_reveal, None),
|
||||||
)
|
)
|
||||||
.expect("should fetch block from http api");
|
.expect("should fetch block from http api");
|
||||||
|
|
||||||
@ -547,7 +547,7 @@ fn validator_block_get() {
|
|||||||
remote_node
|
remote_node
|
||||||
.http
|
.http
|
||||||
.validator()
|
.validator()
|
||||||
.produce_block(slot, randao_reveal.clone()),
|
.produce_block(slot, randao_reveal.clone(), None),
|
||||||
)
|
)
|
||||||
.expect("should fetch block from http api");
|
.expect("should fetch block from http api");
|
||||||
|
|
||||||
@ -555,7 +555,50 @@ fn validator_block_get() {
|
|||||||
.client
|
.client
|
||||||
.beacon_chain()
|
.beacon_chain()
|
||||||
.expect("client should have beacon chain")
|
.expect("client should have beacon chain")
|
||||||
.produce_block(randao_reveal, slot)
|
.produce_block(randao_reveal, slot, None)
|
||||||
|
.expect("should produce block");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
block, expected_block,
|
||||||
|
"the block returned from the API should be as expected"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn validator_block_get_with_graffiti() {
|
||||||
|
let mut env = build_env();
|
||||||
|
|
||||||
|
let spec = &E::default_spec();
|
||||||
|
|
||||||
|
let node = build_node(&mut env, testing_client_config());
|
||||||
|
let remote_node = node.remote_node().expect("should produce remote node");
|
||||||
|
|
||||||
|
let beacon_chain = node
|
||||||
|
.client
|
||||||
|
.beacon_chain()
|
||||||
|
.expect("client should have beacon chain");
|
||||||
|
|
||||||
|
let slot = Slot::new(1);
|
||||||
|
let randao_reveal = get_randao_reveal(beacon_chain, slot, spec);
|
||||||
|
|
||||||
|
let block = env
|
||||||
|
.runtime()
|
||||||
|
.block_on(remote_node.http.validator().produce_block(
|
||||||
|
slot,
|
||||||
|
randao_reveal.clone(),
|
||||||
|
Some(*b"test-graffiti-test-graffiti-test"),
|
||||||
|
))
|
||||||
|
.expect("should fetch block from http api");
|
||||||
|
|
||||||
|
let (expected_block, _state) = node
|
||||||
|
.client
|
||||||
|
.beacon_chain()
|
||||||
|
.expect("client should have beacon chain")
|
||||||
|
.produce_block(
|
||||||
|
randao_reveal,
|
||||||
|
slot,
|
||||||
|
Some(*b"test-graffiti-test-graffiti-test"),
|
||||||
|
)
|
||||||
.expect("should produce block");
|
.expect("should produce block");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -11,8 +11,8 @@ use std::marker::PhantomData;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use types::{
|
use types::{
|
||||||
Attestation, AttestationData, AttesterSlashing, BeaconBlock, BeaconState, CommitteeIndex,
|
Attestation, AttestationData, AttesterSlashing, BeaconBlock, BeaconState, CommitteeIndex,
|
||||||
Epoch, EthSpec, Fork, Hash256, ProposerSlashing, PublicKey, PublicKeyBytes, Signature,
|
Epoch, EthSpec, Fork, Graffiti, Hash256, ProposerSlashing, PublicKey, PublicKeyBytes,
|
||||||
SignedAggregateAndProof, SignedBeaconBlock, Slot, SubnetId,
|
Signature, SignedAggregateAndProof, SignedBeaconBlock, Slot, SubnetId,
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
@ -313,18 +313,21 @@ impl<E: EthSpec> Validator<E> {
|
|||||||
&self,
|
&self,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
randao_reveal: Signature,
|
randao_reveal: Signature,
|
||||||
|
graffiti: Option<Graffiti>,
|
||||||
) -> Result<BeaconBlock<E>, Error> {
|
) -> Result<BeaconBlock<E>, Error> {
|
||||||
let client = self.0.clone();
|
let client = self.0.clone();
|
||||||
let url = self.url("block")?;
|
let url = self.url("block")?;
|
||||||
client
|
|
||||||
.json_get::<BeaconBlock<E>>(
|
let mut query_pairs = vec![
|
||||||
url,
|
("slot".into(), format!("{}", slot.as_u64())),
|
||||||
vec![
|
("randao_reveal".into(), as_ssz_hex_string(&randao_reveal)),
|
||||||
("slot".into(), format!("{}", slot.as_u64())),
|
];
|
||||||
("randao_reveal".into(), as_ssz_hex_string(&randao_reveal)),
|
|
||||||
],
|
if let Some(graffiti_bytes) = graffiti {
|
||||||
)
|
query_pairs.push(("graffiti".into(), as_ssz_hex_string(&graffiti_bytes)));
|
||||||
.await
|
}
|
||||||
|
|
||||||
|
client.json_get::<BeaconBlock<E>>(url, query_pairs).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subscribes a list of validators to particular slots for attestation production/publication.
|
/// Subscribes a list of validators to particular slots for attestation production/publication.
|
||||||
|
@ -7,7 +7,7 @@ use slog::{crit, debug, error, info, trace, warn};
|
|||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{EthSpec, PublicKey, Slot};
|
use types::{EthSpec, Graffiti, PublicKey, Slot};
|
||||||
|
|
||||||
/// Builds a `BlockService`.
|
/// Builds a `BlockService`.
|
||||||
pub struct BlockServiceBuilder<T, E: EthSpec> {
|
pub struct BlockServiceBuilder<T, E: EthSpec> {
|
||||||
@ -15,6 +15,7 @@ pub struct BlockServiceBuilder<T, E: EthSpec> {
|
|||||||
slot_clock: Option<Arc<T>>,
|
slot_clock: Option<Arc<T>>,
|
||||||
beacon_node: Option<RemoteBeaconNode<E>>,
|
beacon_node: Option<RemoteBeaconNode<E>>,
|
||||||
context: Option<RuntimeContext<E>>,
|
context: Option<RuntimeContext<E>>,
|
||||||
|
graffiti: Option<Graffiti>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||||
@ -24,6 +25,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
|||||||
slot_clock: None,
|
slot_clock: None,
|
||||||
beacon_node: None,
|
beacon_node: None,
|
||||||
context: None,
|
context: None,
|
||||||
|
graffiti: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +49,11 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn graffiti(mut self, graffiti: Option<Graffiti>) -> Self {
|
||||||
|
self.graffiti = graffiti;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Result<BlockService<T, E>, String> {
|
pub fn build(self) -> Result<BlockService<T, E>, String> {
|
||||||
Ok(BlockService {
|
Ok(BlockService {
|
||||||
inner: Arc::new(Inner {
|
inner: Arc::new(Inner {
|
||||||
@ -62,6 +69,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
|||||||
context: self
|
context: self
|
||||||
.context
|
.context
|
||||||
.ok_or_else(|| "Cannot build BlockService without runtime_context")?,
|
.ok_or_else(|| "Cannot build BlockService without runtime_context")?,
|
||||||
|
graffiti: self.graffiti,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -73,6 +81,7 @@ pub struct Inner<T, E: EthSpec> {
|
|||||||
slot_clock: Arc<T>,
|
slot_clock: Arc<T>,
|
||||||
beacon_node: RemoteBeaconNode<E>,
|
beacon_node: RemoteBeaconNode<E>,
|
||||||
context: RuntimeContext<E>,
|
context: RuntimeContext<E>,
|
||||||
|
graffiti: Option<Graffiti>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to produce attestations for any block producer(s) at the start of the epoch.
|
/// Attempts to produce attestations for any block producer(s) at the start of the epoch.
|
||||||
@ -214,7 +223,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
|
|||||||
.beacon_node
|
.beacon_node
|
||||||
.http
|
.http
|
||||||
.validator()
|
.validator()
|
||||||
.produce_block(slot, randao_reveal)
|
.produce_block(slot, randao_reveal, self.graffiti)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("Error from beacon node when producing block: {:?}", e))?;
|
.map_err(|e| format!("Error from beacon node when producing block: {:?}", e))?;
|
||||||
|
|
||||||
|
@ -60,4 +60,12 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
|||||||
node is not synced.",
|
node is not synced.",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
// This overwrites the graffiti configured in the beacon node.
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("graffiti")
|
||||||
|
.long("graffiti")
|
||||||
|
.help("Specify your custom graffiti to be included in blocks.")
|
||||||
|
.value_name("GRAFFITI")
|
||||||
|
.takes_value(true)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use clap::ArgMatches;
|
|||||||
use clap_utils::{parse_optional, parse_path_with_default_in_home_dir};
|
use clap_utils::{parse_optional, parse_path_with_default_in_home_dir};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use types::{Graffiti, GRAFFITI_BYTES_LEN};
|
||||||
|
|
||||||
pub const DEFAULT_HTTP_SERVER: &str = "http://localhost:5052/";
|
pub const DEFAULT_HTTP_SERVER: &str = "http://localhost:5052/";
|
||||||
pub const DEFAULT_DATA_DIR: &str = ".lighthouse/validators";
|
pub const DEFAULT_DATA_DIR: &str = ".lighthouse/validators";
|
||||||
@ -27,6 +28,8 @@ pub struct Config {
|
|||||||
pub strict_lockfiles: bool,
|
pub strict_lockfiles: bool,
|
||||||
/// If true, don't scan the validators dir for new keystores.
|
/// If true, don't scan the validators dir for new keystores.
|
||||||
pub disable_auto_discover: bool,
|
pub disable_auto_discover: bool,
|
||||||
|
/// Graffiti to be inserted everytime we create a block.
|
||||||
|
pub graffiti: Option<Graffiti>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -45,6 +48,7 @@ impl Default for Config {
|
|||||||
allow_unsynced_beacon_node: false,
|
allow_unsynced_beacon_node: false,
|
||||||
strict_lockfiles: false,
|
strict_lockfiles: false,
|
||||||
disable_auto_discover: false,
|
disable_auto_discover: false,
|
||||||
|
graffiti: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,6 +84,26 @@ impl Config {
|
|||||||
config.secrets_dir = secrets_dir;
|
config.secrets_dir = secrets_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(input_graffiti) = cli_args.value_of("graffiti") {
|
||||||
|
let graffiti_bytes = input_graffiti.as_bytes();
|
||||||
|
if graffiti_bytes.len() > GRAFFITI_BYTES_LEN {
|
||||||
|
return Err(format!(
|
||||||
|
"Your graffiti is too long! {} bytes maximum!",
|
||||||
|
GRAFFITI_BYTES_LEN
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
// Default graffiti to all 0 bytes.
|
||||||
|
let mut graffiti = Graffiti::default();
|
||||||
|
|
||||||
|
// Copy the provided bytes over.
|
||||||
|
//
|
||||||
|
// Panic-free because `graffiti_bytes.len()` <= `GRAFFITI_BYTES_LEN`.
|
||||||
|
graffiti[..graffiti_bytes.len()].copy_from_slice(&graffiti_bytes);
|
||||||
|
|
||||||
|
config.graffiti = Some(graffiti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,7 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
.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()))
|
||||||
|
.graffiti(config.graffiti)
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
let attestation_service = AttestationServiceBuilder::new()
|
let attestation_service = AttestationServiceBuilder::new()
|
||||||
|
Loading…
Reference in New Issue
Block a user