use std::{
collections::{HashMap, HashSet},
fmt::{self, Debug, Display, Formatter},
net::SocketAddr,
};
use datasize::DataSize;
use semver::Version;
use casper_execution_engine::{
core::engine_state::{
self,
balance::{BalanceRequest, BalanceResult},
era_validators::GetEraValidatorsError,
execute_request::ExecuteRequest,
execution_result::ExecutionResults,
genesis::GenesisResult,
query::{QueryRequest, QueryResult},
step::{StepRequest, StepResult},
upgrade::{UpgradeConfig, UpgradeResult},
},
shared::{additive_map::AdditiveMap, transform::Transform},
storage::{global_state::CommitResult, protocol_data::ProtocolData},
};
use casper_types::{
auction::{EraValidators, ValidatorWeights},
Key, ProtocolVersion, URef,
};
use super::Responder;
use crate::{
components::{
chainspec_loader::ChainspecInfo,
contract_runtime::{EraValidatorsRequest, ValidatorWeightsByEraIdRequest},
fetcher::FetchResult,
storage::{
DeployHashes, DeployHeaderResults, DeployMetadata, DeployResults, StorageType, Value,
},
},
crypto::{asymmetric_key::Signature, hash::Digest},
rpcs::chain::BlockIdentifier,
types::{
json_compatibility::ExecutionResult, Block as LinearBlock, Block, BlockHash, BlockHeader,
Deploy, DeployHash, FinalizedBlock, Item, ProtoBlockHash, StatusFeed, Timestamp,
},
utils::DisplayIter,
Chainspec,
};
type DeployAndMetadata<S> = (
<S as StorageType>::Deploy,
DeployMetadata<<S as StorageType>::Block>,
);
#[derive(Debug)]
pub enum MetricsRequest {
RenderNodeMetricsText {
responder: Responder<Option<String>>,
},
}
impl Display for MetricsRequest {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
MetricsRequest::RenderNodeMetricsText { .. } => write!(formatter, "get metrics text"),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum NetworkRequest<I, P> {
SendMessage {
dest: I,
payload: P,
responder: Responder<()>,
},
Broadcast {
payload: P,
responder: Responder<()>,
},
Gossip {
payload: P,
count: usize,
exclude: HashSet<I>,
responder: Responder<HashSet<I>>,
},
}
impl<I, P> NetworkRequest<I, P> {
pub(crate) fn map_payload<F, P2>(self, wrap_payload: F) -> NetworkRequest<I, P2>
where
F: FnOnce(P) -> P2,
{
match self {
NetworkRequest::SendMessage {
dest,
payload,
responder,
} => NetworkRequest::SendMessage {
dest,
payload: wrap_payload(payload),
responder,
},
NetworkRequest::Broadcast { payload, responder } => NetworkRequest::Broadcast {
payload: wrap_payload(payload),
responder,
},
NetworkRequest::Gossip {
payload,
count,
exclude,
responder,
} => NetworkRequest::Gossip {
payload: wrap_payload(payload),
count,
exclude,
responder,
},
}
}
}
impl<I, P> Display for NetworkRequest<I, P>
where
I: Display,
P: Display,
{
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
NetworkRequest::SendMessage { dest, payload, .. } => {
write!(formatter, "send to {}: {}", dest, payload)
}
NetworkRequest::Broadcast { payload, .. } => {
write!(formatter, "broadcast: {}", payload)
}
NetworkRequest::Gossip { payload, .. } => write!(formatter, "gossip: {}", payload),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum NetworkInfoRequest<I> {
GetPeers {
responder: Responder<HashMap<I, SocketAddr>>,
},
}
impl<I> Display for NetworkInfoRequest<I>
where
I: Display,
{
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
NetworkInfoRequest::GetPeers { responder: _ } => write!(formatter, "get peers"),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum StorageRequest<S: StorageType + 'static> {
PutBlock {
block: Box<S::Block>,
responder: Responder<bool>,
},
GetBlock {
block_hash: <S::Block as Value>::Id,
responder: Responder<Option<S::Block>>,
},
GetBlockAtHeight {
height: u64,
responder: Responder<Option<S::Block>>,
},
GetHighestBlock {
responder: Responder<Option<S::Block>>,
},
GetBlockHeader {
block_hash: <S::Block as Value>::Id,
responder: Responder<Option<<S::Block as Value>::Header>>,
},
PutDeploy {
deploy: Box<S::Deploy>,
responder: Responder<bool>,
},
GetDeploys {
deploy_hashes: DeployHashes<S>,
responder: Responder<DeployResults<S>>,
},
GetDeployHeaders {
deploy_hashes: DeployHashes<S>,
responder: Responder<DeployHeaderResults<S>>,
},
PutExecutionResults {
block_hash: <S::Block as Value>::Id,
execution_results: HashMap<<S::Deploy as Value>::Id, ExecutionResult>,
responder: Responder<()>,
},
GetDeployAndMetadata {
deploy_hash: <S::Deploy as Value>::Id,
responder: Responder<Option<DeployAndMetadata<S>>>,
},
PutChainspec {
chainspec: Box<Chainspec>,
responder: Responder<()>,
},
GetChainspec {
version: Version,
responder: Responder<Option<Chainspec>>,
},
}
impl<S: StorageType> Display for StorageRequest<S> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
StorageRequest::PutBlock { block, .. } => write!(formatter, "put {}", block),
StorageRequest::GetBlock { block_hash, .. } => write!(formatter, "get {}", block_hash),
StorageRequest::GetBlockAtHeight { height, .. } => {
write!(formatter, "get block at height {}", height)
}
StorageRequest::GetHighestBlock { .. } => write!(formatter, "get highest block"),
StorageRequest::GetBlockHeader { block_hash, .. } => {
write!(formatter, "get {}", block_hash)
}
StorageRequest::PutDeploy { deploy, .. } => write!(formatter, "put {}", deploy),
StorageRequest::GetDeploys { deploy_hashes, .. } => {
write!(formatter, "get {}", DisplayIter::new(deploy_hashes.iter()))
}
StorageRequest::GetDeployHeaders { deploy_hashes, .. } => write!(
formatter,
"get headers {}",
DisplayIter::new(deploy_hashes.iter())
),
StorageRequest::PutExecutionResults { block_hash, .. } => {
write!(formatter, "put execution results for {}", block_hash)
}
StorageRequest::GetDeployAndMetadata { deploy_hash, .. } => {
write!(formatter, "get deploy and metadata for {}", deploy_hash)
}
StorageRequest::PutChainspec { chainspec, .. } => write!(
formatter,
"put chainspec {}",
chainspec.genesis.protocol_version
),
StorageRequest::GetChainspec { version, .. } => {
write!(formatter, "get chainspec {}", version)
}
}
}
}
#[derive(Debug)]
#[must_use]
pub enum BlockProposerRequest {
ListForInclusion {
current_instant: Timestamp,
past_blocks: HashSet<ProtoBlockHash>,
responder: Responder<HashSet<DeployHash>>,
},
}
impl Display for BlockProposerRequest {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
BlockProposerRequest::ListForInclusion {
current_instant,
past_blocks,
responder: _,
} => write!(
formatter,
"list for inclusion: instant {} past {}",
current_instant,
past_blocks.len()
),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum ApiRequest<I> {
SubmitDeploy {
deploy: Box<Deploy>,
responder: Responder<()>,
},
GetBlock {
maybe_id: Option<BlockIdentifier>,
responder: Responder<Option<LinearBlock>>,
},
QueryGlobalState {
state_root_hash: Digest,
base_key: Key,
path: Vec<String>,
responder: Responder<Result<QueryResult, engine_state::Error>>,
},
QueryEraValidators {
state_root_hash: Digest,
protocol_version: ProtocolVersion,
responder: Responder<Result<EraValidators, GetEraValidatorsError>>,
},
QueryProtocolData {
protocol_version: ProtocolVersion,
responder: Responder<Result<Option<Box<ProtocolData>>, engine_state::Error>>,
},
GetBalance {
state_root_hash: Digest,
purse_uref: URef,
responder: Responder<Result<BalanceResult, engine_state::Error>>,
},
GetDeploy {
hash: DeployHash,
responder: Responder<Option<(Deploy, DeployMetadata<LinearBlock>)>>,
},
GetPeers {
responder: Responder<HashMap<I, SocketAddr>>,
},
GetStatus {
responder: Responder<StatusFeed<I>>,
},
GetMetrics {
responder: Responder<Option<String>>,
},
}
impl<I> Display for ApiRequest<I> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
ApiRequest::SubmitDeploy { deploy, .. } => write!(formatter, "submit {}", *deploy),
ApiRequest::GetBlock {
maybe_id: Some(BlockIdentifier::Hash(hash)),
..
} => write!(formatter, "get {}", hash),
ApiRequest::GetBlock {
maybe_id: Some(BlockIdentifier::Height(height)),
..
} => write!(formatter, "get {}", height),
ApiRequest::GetBlock { maybe_id: None, .. } => write!(formatter, "get latest block"),
ApiRequest::QueryProtocolData {
protocol_version, ..
} => write!(formatter, "protocol_version {}", protocol_version),
ApiRequest::QueryGlobalState {
state_root_hash,
base_key,
path,
..
} => write!(
formatter,
"query {}, base_key: {}, path: {:?}",
state_root_hash, base_key, path
),
ApiRequest::QueryEraValidators {
state_root_hash, ..
} => write!(formatter, "auction {}", state_root_hash),
ApiRequest::GetBalance {
state_root_hash,
purse_uref,
..
} => write!(
formatter,
"balance {}, purse_uref: {}",
state_root_hash, purse_uref
),
ApiRequest::GetDeploy { hash, .. } => write!(formatter, "get {}", hash),
ApiRequest::GetPeers { .. } => write!(formatter, "get peers"),
ApiRequest::GetStatus { .. } => write!(formatter, "get status"),
ApiRequest::GetMetrics { .. } => write!(formatter, "get metrics"),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum ContractRuntimeRequest {
GetProtocolData {
protocol_version: ProtocolVersion,
responder: Responder<Result<Option<Box<ProtocolData>>, engine_state::Error>>,
},
CommitGenesis {
chainspec: Box<Chainspec>,
responder: Responder<Result<GenesisResult, engine_state::Error>>,
},
Execute {
execute_request: ExecuteRequest,
responder: Responder<Result<ExecutionResults, engine_state::RootNotFound>>,
},
Commit {
state_root_hash: Digest,
effects: AdditiveMap<Key, Transform>,
responder: Responder<Result<CommitResult, engine_state::Error>>,
},
Upgrade {
upgrade_config: Box<UpgradeConfig>,
responder: Responder<Result<UpgradeResult, engine_state::Error>>,
},
Query {
query_request: QueryRequest,
responder: Responder<Result<QueryResult, engine_state::Error>>,
},
GetBalance {
balance_request: BalanceRequest,
responder: Responder<Result<BalanceResult, engine_state::Error>>,
},
GetEraValidators {
request: EraValidatorsRequest,
responder: Responder<Result<EraValidators, GetEraValidatorsError>>,
},
GetValidatorWeightsByEraId {
request: ValidatorWeightsByEraIdRequest,
responder: Responder<Result<Option<ValidatorWeights>, GetEraValidatorsError>>,
},
Step {
step_request: StepRequest,
responder: Responder<Result<StepResult, engine_state::Error>>,
},
}
impl Display for ContractRuntimeRequest {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
ContractRuntimeRequest::CommitGenesis { chainspec, .. } => write!(
formatter,
"commit genesis {}",
chainspec.genesis.protocol_version
),
ContractRuntimeRequest::Execute {
execute_request, ..
} => write!(
formatter,
"execute request: {}",
execute_request.parent_state_hash
),
ContractRuntimeRequest::Commit {
state_root_hash,
effects,
..
} => write!(
formatter,
"commit request: {} {:?}",
state_root_hash, effects
),
ContractRuntimeRequest::Upgrade { upgrade_config, .. } => {
write!(formatter, "upgrade request: {:?}", upgrade_config)
}
ContractRuntimeRequest::Query { query_request, .. } => {
write!(formatter, "query request: {:?}", query_request)
}
ContractRuntimeRequest::GetBalance {
balance_request, ..
} => write!(formatter, "balance request: {:?}", balance_request),
ContractRuntimeRequest::GetEraValidators { request, .. } => {
write!(formatter, "get era validators: {:?}", request)
}
ContractRuntimeRequest::GetValidatorWeightsByEraId { request, .. } => {
write!(formatter, "get validator weights: {:?}", request)
}
ContractRuntimeRequest::Step { step_request, .. } => {
write!(formatter, "step: {:?}", step_request)
}
ContractRuntimeRequest::GetProtocolData {
protocol_version, ..
} => write!(formatter, "protocol_version: {}", protocol_version),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum FetcherRequest<I, T: Item> {
Fetch {
id: T::Id,
peer: I,
responder: Responder<Option<FetchResult<T>>>,
},
}
impl<I, T: Item> Display for FetcherRequest<I, T> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
FetcherRequest::Fetch { id, .. } => write!(formatter, "request item by id {}", id),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum BlockExecutorRequest {
ExecuteBlock(FinalizedBlock),
}
impl Display for BlockExecutorRequest {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
BlockExecutorRequest::ExecuteBlock(finalized_block) => {
write!(f, "execute block {}", finalized_block)
}
}
}
}
#[derive(Debug)]
#[must_use]
pub struct BlockValidationRequest<T, I> {
pub(crate) block: T,
pub(crate) sender: I,
pub(crate) responder: Responder<(bool, T)>,
pub(crate) block_timestamp: Timestamp,
}
impl<T: Display, I: Display> Display for BlockValidationRequest<T, I> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let BlockValidationRequest { block, sender, .. } = self;
write!(f, "validate block {} from {}", block, sender)
}
}
type BlockHeight = u64;
#[derive(Debug)]
pub enum LinearChainRequest<I> {
BlockRequest(BlockHash, I),
BlockAtHeight(BlockHeight, I),
BlockAtHeightLocal(BlockHeight, Responder<Option<Block>>),
}
impl<I: Display> Display for LinearChainRequest<I> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
LinearChainRequest::BlockRequest(bh, peer) => {
write!(f, "block request for hash {} from {}", bh, peer)
}
LinearChainRequest::BlockAtHeight(height, sender) => {
write!(f, "block request for {} from {}", height, sender)
}
LinearChainRequest::BlockAtHeightLocal(height, _) => {
write!(f, "local request for block at height {}", height)
}
}
}
}
#[derive(DataSize, Debug)]
#[must_use]
pub enum ConsensusRequest {
HandleLinearBlock(Box<BlockHeader>, Responder<Signature>),
}
#[derive(Debug)]
pub enum ChainspecLoaderRequest {
GetChainspecInfo(Responder<ChainspecInfo>),
}
impl Display for ChainspecLoaderRequest {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ChainspecLoaderRequest::GetChainspecInfo(_) => write!(f, "get chainspec info"),
}
}
}