use std::{
borrow::Cow,
collections::{BTreeMap, HashMap, HashSet},
fmt::{self, Debug, Display, Formatter},
sync::Arc,
};
use datasize::DataSize;
use semver::Version;
use serde::Serialize;
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},
ExecutionResult, Key, ProtocolVersion, PublicKey, Transfer, URef,
};
use hex_fmt::HexFmt;
use super::{Multiple, Responder};
use crate::{
components::{
chainspec_loader::ChainspecInfo,
consensus::EraId,
contract_runtime::{EraValidatorsRequest, ValidatorWeightsByEraIdRequest},
deploy_acceptor::Error,
fetcher::FetchResult,
},
crypto::hash::Digest,
rpcs::chain::BlockIdentifier,
types::{
Block as LinearBlock, Block, BlockHash, BlockHeader, Deploy, DeployHash, DeployHeader,
DeployMetadata, FinalitySignature, FinalizedBlock, Item, ProtoBlock, StatusFeed, Timestamp,
},
utils::DisplayIter,
Chainspec,
};
#[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, Serialize)]
#[must_use]
pub enum NetworkRequest<I, P> {
SendMessage {
dest: I,
payload: P,
#[serde(skip_serializing)]
responder: Responder<()>,
},
Broadcast {
payload: P,
#[serde(skip_serializing)]
responder: Responder<()>,
},
Gossip {
payload: P,
count: usize,
#[serde(skip_serializing)]
exclude: HashSet<I>,
#[serde(skip_serializing)]
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<BTreeMap<I, String>>,
},
}
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, Serialize)]
#[must_use]
pub enum StorageRequest {
PutBlock {
block: Box<Block>,
responder: Responder<bool>,
},
GetBlock {
block_hash: BlockHash,
responder: Responder<Option<Block>>,
},
GetBlockAtHeight {
height: BlockHeight,
responder: Responder<Option<Block>>,
},
GetHighestBlock {
responder: Responder<Option<Block>>,
},
GetBlockHeader {
block_hash: BlockHash,
responder: Responder<Option<BlockHeader>>,
},
GetBlockTransfers {
block_hash: BlockHash,
responder: Responder<Option<Vec<Transfer>>>,
},
PutDeploy {
deploy: Box<Deploy>,
responder: Responder<bool>,
},
GetDeploys {
deploy_hashes: Multiple<DeployHash>,
responder: Responder<Vec<Option<Deploy>>>,
},
GetDeployHeaders {
deploy_hashes: Multiple<DeployHash>,
responder: Responder<Vec<Option<DeployHeader>>>,
},
PutExecutionResults {
block_hash: BlockHash,
execution_results: HashMap<DeployHash, ExecutionResult>,
responder: Responder<()>,
},
GetDeployAndMetadata {
deploy_hash: DeployHash,
responder: Responder<Option<(Deploy, DeployMetadata)>>,
},
PutChainspec {
chainspec: Arc<Chainspec>,
responder: Responder<()>,
},
GetChainspec {
version: Version,
responder: Responder<Option<Arc<Chainspec>>>,
},
}
impl Display for StorageRequest {
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::GetBlockTransfers { block_hash, .. } => {
write!(formatter, "get transfers for {}", 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(DataSize, Debug, Serialize)]
pub enum StateStoreRequest {
Save {
key: Cow<'static, [u8]>,
#[serde(skip_serializing)]
data: Vec<u8>,
responder: Responder<()>,
},
Load {
key: Cow<'static, [u8]>,
responder: Responder<Option<Vec<u8>>>,
},
}
impl Display for StateStoreRequest {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
StateStoreRequest::Save { key, data, .. } => {
write!(f, "save data under {} ({} bytes)", HexFmt(key), data.len())
}
StateStoreRequest::Load { key, .. } => {
write!(f, "load data from key {}", HexFmt(key))
}
}
}
}
#[derive(DataSize, Debug)]
pub struct ProtoBlockRequest {
pub(crate) current_instant: Timestamp,
pub(crate) past_deploys: HashSet<DeployHash>,
pub(crate) next_finalized: u64,
pub(crate) random_bit: bool,
pub(crate) responder: Responder<ProtoBlock>,
}
#[derive(DataSize, Debug)]
#[must_use]
pub enum BlockProposerRequest {
RequestProtoBlock(ProtoBlockRequest),
}
impl Display for BlockProposerRequest {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
BlockProposerRequest::RequestProtoBlock(ProtoBlockRequest {
current_instant,
past_deploys,
next_finalized,
responder: _,
random_bit: _,
}) => write!(
formatter,
"list for inclusion: instant {} past {} next_finalized {}",
current_instant,
past_deploys.len(),
next_finalized
),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum RpcRequest<I> {
SubmitDeploy {
deploy: Box<Deploy>,
responder: Responder<Result<(), Error>>,
},
GetBlock {
maybe_id: Option<BlockIdentifier>,
responder: Responder<Option<LinearBlock>>,
},
GetBlockTransfers {
block_hash: BlockHash,
responder: Responder<Option<Vec<Transfer>>>,
},
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)>>,
},
GetPeers {
responder: Responder<BTreeMap<I, String>>,
},
GetStatus {
responder: Responder<StatusFeed<I>>,
},
GetMetrics {
responder: Responder<Option<String>>,
},
}
impl<I> Display for RpcRequest<I> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
RpcRequest::SubmitDeploy { deploy, .. } => write!(formatter, "submit {}", *deploy),
RpcRequest::GetBlock {
maybe_id: Some(BlockIdentifier::Hash(hash)),
..
} => write!(formatter, "get {}", hash),
RpcRequest::GetBlock {
maybe_id: Some(BlockIdentifier::Height(height)),
..
} => write!(formatter, "get {}", height),
RpcRequest::GetBlock { maybe_id: None, .. } => write!(formatter, "get latest block"),
RpcRequest::GetBlockTransfers { block_hash, .. } => {
write!(formatter, "get transfers {}", block_hash)
}
RpcRequest::QueryProtocolData {
protocol_version, ..
} => write!(formatter, "protocol_version {}", protocol_version),
RpcRequest::QueryGlobalState {
state_root_hash,
base_key,
path,
..
} => write!(
formatter,
"query {}, base_key: {}, path: {:?}",
state_root_hash, base_key, path
),
RpcRequest::QueryEraValidators {
state_root_hash, ..
} => write!(formatter, "auction {}", state_root_hash),
RpcRequest::GetBalance {
state_root_hash,
purse_uref,
..
} => write!(
formatter,
"balance {}, purse_uref: {}",
state_root_hash, purse_uref
),
RpcRequest::GetDeploy { hash, .. } => write!(formatter, "get {}", hash),
RpcRequest::GetPeers { .. } => write!(formatter, "get peers"),
RpcRequest::GetStatus { .. } => write!(formatter, "get status"),
RpcRequest::GetMetrics { .. } => write!(formatter, "get metrics"),
}
}
}
#[derive(Debug)]
#[must_use]
pub enum RestRequest<I> {
GetStatus {
responder: Responder<StatusFeed<I>>,
},
GetMetrics {
responder: Responder<Option<String>>,
},
}
impl<I> Display for RestRequest<I> {
fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
match self {
RestRequest::GetStatus { .. } => write!(formatter, "get status"),
RestRequest::GetMetrics { .. } => write!(formatter, "get metrics"),
}
}
}
#[derive(Debug, Serialize)]
#[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 {
#[serde(skip_serializing)]
execute_request: Box<ExecuteRequest>,
responder: Responder<Result<ExecutionResults, engine_state::RootNotFound>>,
},
Commit {
state_root_hash: Digest,
#[serde(skip_serializing)]
effects: AdditiveMap<Key, Transform>,
responder: Responder<Result<CommitResult, engine_state::Error>>,
},
Upgrade {
#[serde(skip_serializing)]
upgrade_config: Box<UpgradeConfig>,
responder: Responder<Result<UpgradeResult, engine_state::Error>>,
},
Query {
#[serde(skip_serializing)]
query_request: QueryRequest,
responder: Responder<Result<QueryResult, engine_state::Error>>,
},
GetBalance {
#[serde(skip_serializing)]
balance_request: BalanceRequest,
responder: Responder<Result<BalanceResult, engine_state::Error>>,
},
GetEraValidators {
#[serde(skip_serializing)]
request: EraValidatorsRequest,
responder: Responder<Result<EraValidators, GetEraValidatorsError>>,
},
GetValidatorWeightsByEraId {
#[serde(skip_serializing)]
request: ValidatorWeightsByEraIdRequest,
responder: Responder<Result<Option<ValidatorWeights>, GetEraValidatorsError>>,
},
Step {
#[serde(skip_serializing)]
step_request: StepRequest,
responder: Responder<Result<StepResult, engine_state::Error>>,
},
IsBonded {
state_root_hash: Digest,
public_key: PublicKey,
era_id: EraId,
protocol_version: ProtocolVersion,
responder: Responder<Result<bool, GetEraValidatorsError>>,
},
}
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),
ContractRuntimeRequest::IsBonded {
public_key, era_id, ..
} => {
write!(formatter, "is {} bonded in era {}", public_key, era_id)
}
}
}
}
#[derive(Debug, Serialize)]
#[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, Serialize)]
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<Option<FinalitySignature>>),
IsBondedValidator(EraId, PublicKey, Responder<bool>),
}
#[derive(Debug, Serialize)]
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"),
}
}
}