1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
//! Support for a step method.
//!
//! A step request executes auction code, slashes validators, evicts validators and distributes
//! rewards.
use std::{collections::BTreeMap, vec::Vec};
use casper_hashing::Digest;
use casper_types::{bytesrepr, CLValueError, EraId, ProtocolVersion, PublicKey};
use crate::{
core::{engine_state::Error, execution, runtime::stack::RuntimeStackOverflow},
shared::execution_journal::ExecutionJournal,
};
/// The definition of a slash item.
#[derive(Debug, Clone)]
pub struct SlashItem {
/// The public key of the validator that will be slashed.
pub validator_id: PublicKey,
}
impl SlashItem {
/// Creates a new slash item.
pub fn new(validator_id: PublicKey) -> Self {
Self { validator_id }
}
}
/// The definition of a reward item.
#[derive(Debug, Clone)]
pub struct RewardItem {
/// The public key of the validator that will be rewarded.
pub validator_id: PublicKey,
/// Amount of motes that will be distributed as rewards.
pub value: u64,
}
impl RewardItem {
/// Creates new reward item.
pub fn new(validator_id: PublicKey, value: u64) -> Self {
Self {
validator_id,
value,
}
}
}
/// The definition of an evict item.
#[derive(Debug, Clone)]
pub struct EvictItem {
/// The public key of the validator that will be evicted.
pub validator_id: PublicKey,
}
impl EvictItem {
/// Creates new evict item.
pub fn new(validator_id: PublicKey) -> Self {
Self { validator_id }
}
}
/// Representation of a step request.
#[derive(Debug)]
pub struct StepRequest {
/// State root hash.
pub pre_state_hash: Digest,
/// Protocol version for this request.
pub protocol_version: ProtocolVersion,
/// List of validators to be slashed.
///
/// A slashed validator is removed from the next validator set.
pub slash_items: Vec<SlashItem>,
/// List of validators that will be rewarded.
pub reward_items: Vec<RewardItem>,
/// List of validators to be evicted.
///
/// Compared to a slashing, evictions are deactivating a given validator, but his stake is
/// unchanged. A further re-activation is possible.
pub evict_items: Vec<EvictItem>,
/// Specifies which era validators will be returned based on `next_era_id`.
///
/// Intended use is to always specify the current era id + 1 which will return computed era at
/// the end of this step request.
pub next_era_id: EraId,
/// Timestamp in milliseconds representing end of the current era.
pub era_end_timestamp_millis: u64,
}
impl StepRequest {
/// Creates new step request.
#[allow(clippy::too_many_arguments)]
pub fn new(
pre_state_hash: Digest,
protocol_version: ProtocolVersion,
slash_items: Vec<SlashItem>,
reward_items: Vec<RewardItem>,
evict_items: Vec<EvictItem>,
next_era_id: EraId,
era_end_timestamp_millis: u64,
) -> Self {
Self {
pre_state_hash,
protocol_version,
slash_items,
reward_items,
evict_items,
next_era_id,
era_end_timestamp_millis,
}
}
/// Returns list of slashed validators.
pub fn slashed_validators(&self) -> Vec<PublicKey> {
self.slash_items
.iter()
.map(|si| si.validator_id.clone())
.collect()
}
/// Returns all reward factors.
pub fn reward_factors(&self) -> Result<BTreeMap<PublicKey, u64>, bytesrepr::Error> {
let mut ret = BTreeMap::new();
for reward_item in &self.reward_items {
ret.insert(reward_item.validator_id.clone(), reward_item.value);
}
Ok(ret)
}
}
/// Representation of all possible failures of a step request.
#[derive(Debug, thiserror::Error)]
pub enum StepError {
/// Invalid state root hash.
#[error("Root not found: {0:?}")]
RootNotFound(Digest),
/// Error creating a tracking copy instance.
#[error("Tracking copy error: {0}")]
TrackingCopyError(Error),
#[error("Get contract error: {0}")]
/// Error getting a system contract.
GetContractError(Error),
/// Error retrieving a system module.
#[error("Get system module error: {0}")]
GetSystemModuleError(Error),
/// Error executing a slashing operation.
#[error("Slashing error: {0}")]
SlashingError(Error),
/// Error executing the auction contract.
#[error("Auction error: {0}")]
AuctionError(Error),
/// Error executing a distribute operation.
#[error("Distribute error: {0}")]
DistributeError(Error),
/// Error executing a distribute accumulated fees operation.
#[error("Distribute accumulated fees error: {0}")]
DistributeAccumulatedFeesError(Error),
/// Invalid protocol version.
#[error("Invalid protocol version: {0}")]
InvalidProtocolVersion(ProtocolVersion),
/// Error while (de)serializing data.
#[error("{0}")]
BytesRepr(bytesrepr::Error),
/// Error converting `CLValue`.
#[error("{0}")]
CLValueError(CLValueError),
#[error("Other engine state error: {0}")]
/// Other engine state error.
OtherEngineStateError(#[from] Error),
/// Execution error.
#[error(transparent)]
ExecutionError(#[from] execution::Error),
}
impl From<bytesrepr::Error> for StepError {
fn from(error: bytesrepr::Error) -> Self {
StepError::BytesRepr(error)
}
}
impl From<CLValueError> for StepError {
fn from(error: CLValueError) -> Self {
StepError::CLValueError(error)
}
}
impl From<RuntimeStackOverflow> for StepError {
fn from(overflow: RuntimeStackOverflow) -> Self {
StepError::OtherEngineStateError(Error::from(overflow))
}
}
/// Represents a successfully executed step request.
#[derive(Debug)]
pub struct StepSuccess {
/// New state root hash generated after effects were applied.
pub post_state_hash: Digest,
/// Effects of executing a step request.
pub execution_journal: ExecutionJournal,
}