Skip to content

Commit

Permalink
Merge #4569
Browse files Browse the repository at this point in the history
4569: Min max delegation amounts r=mpapierski a=moubctez

Implements casper-network/ceps#90

Co-authored-by: Adam Ciarciński <[email protected]>
Co-authored-by: Maciek <[email protected]>
Co-authored-by: Maciej Wójcik <[email protected]>
  • Loading branch information
4 people authored May 24, 2024
2 parents 879c244 + 6a8fe54 commit 2073334
Show file tree
Hide file tree
Showing 44 changed files with 1,122 additions and 170 deletions.
20 changes: 20 additions & 0 deletions execution_engine/src/engine_state/engine_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub const DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT: u32 = 12;
pub const DEFAULT_MAX_STORED_VALUE_SIZE: u32 = 8 * 1024 * 1024;
/// Default value for minimum delegation amount in motes.
pub const DEFAULT_MINIMUM_DELEGATION_AMOUNT: u64 = 500 * 1_000_000_000;
/// Default value for maximum delegation amount in motes.
pub const DEFAULT_MAXIMUM_DELEGATION_AMOUNT: u64 = 1_000_000_000 * 1_000_000_000;
/// Default value for strict argument checking.
pub const DEFAULT_STRICT_ARGUMENT_CHECKING: bool = false;
/// 91 days / 7 days in a week = 13 weeks
Expand Down Expand Up @@ -56,6 +58,7 @@ pub struct EngineConfig {
max_associated_keys: u32,
max_runtime_call_stack_height: u32,
minimum_delegation_amount: u64,
maximum_delegation_amount: u64,
/// This flag indicates if arguments passed to contracts are checked against the defined types.
strict_argument_checking: bool,
/// Vesting schedule period in milliseconds.
Expand Down Expand Up @@ -89,6 +92,7 @@ impl Default for EngineConfig {
max_associated_keys: DEFAULT_MAX_ASSOCIATED_KEYS,
max_runtime_call_stack_height: DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT,
minimum_delegation_amount: DEFAULT_MINIMUM_DELEGATION_AMOUNT,
maximum_delegation_amount: DEFAULT_MAXIMUM_DELEGATION_AMOUNT,
strict_argument_checking: DEFAULT_STRICT_ARGUMENT_CHECKING,
vesting_schedule_period_millis: DEFAULT_VESTING_SCHEDULE_LENGTH_MILLIS,
max_delegators_per_validator: DEFAULT_MAX_DELEGATORS_PER_VALIDATOR,
Expand Down Expand Up @@ -136,6 +140,11 @@ impl EngineConfig {
self.minimum_delegation_amount
}

/// Returns the maximum delegation amount in motes.
pub fn maximum_delegation_amount(&self) -> u64 {
self.maximum_delegation_amount
}

/// Get the engine config's strict argument checking flag.
pub fn strict_argument_checking(&self) -> bool {
self.strict_argument_checking
Expand Down Expand Up @@ -206,6 +215,7 @@ pub struct EngineConfigBuilder {
max_associated_keys: Option<u32>,
max_runtime_call_stack_height: Option<u32>,
minimum_delegation_amount: Option<u64>,
maximum_delegation_amount: Option<u64>,
strict_argument_checking: Option<bool>,
vesting_schedule_period_millis: Option<u64>,
max_delegators_per_validator: Option<u32>,
Expand Down Expand Up @@ -297,6 +307,12 @@ impl EngineConfigBuilder {
self
}

/// Sets the maximum delegation amount config option.
pub fn with_maximum_delegation_amount(mut self, maximum_delegation_amount: u64) -> Self {
self.maximum_delegation_amount = Some(maximum_delegation_amount);
self
}

/// Sets the administrative accounts.
pub fn with_administrative_accounts(
mut self,
Expand Down Expand Up @@ -365,6 +381,9 @@ impl EngineConfigBuilder {
let minimum_delegation_amount = self
.minimum_delegation_amount
.unwrap_or(DEFAULT_MINIMUM_DELEGATION_AMOUNT);
let maximum_delegation_amount = self
.maximum_delegation_amount
.unwrap_or(DEFAULT_MAXIMUM_DELEGATION_AMOUNT);
let wasm_config = self.wasm_config.unwrap_or_default();
let system_config = self.system_config.unwrap_or_default();
let protocol_version = self.protocol_version.unwrap_or(DEFAULT_PROTOCOL_VERSION);
Expand Down Expand Up @@ -399,6 +418,7 @@ impl EngineConfigBuilder {
max_associated_keys,
max_runtime_call_stack_height,
minimum_delegation_amount,
maximum_delegation_amount,
wasm_config,
system_config,
protocol_version,
Expand Down
76 changes: 52 additions & 24 deletions execution_engine/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,22 @@ where
.map_err(|_| ExecError::Revert(ApiError::InvalidArgument))
}

fn try_get_named_argument<T: FromBytes + CLTyped>(
args: &RuntimeArgs,
name: &str,
) -> Result<Option<T>, ExecError> {
match args.get(name) {
Some(arg) => {
let arg = arg
.clone()
.into_t()
.map_err(|_| ExecError::Revert(ApiError::InvalidArgument))?;
Ok(Some(arg))
}
None => Ok(None),
}
}

fn reverter<T: Into<ApiError>>(error: T) -> ExecError {
let api_error: ApiError = error.into();
// NOTE: This is special casing needed to keep the native system contracts propagate
Expand Down Expand Up @@ -830,8 +846,38 @@ where
let delegation_rate =
Self::get_named_argument(runtime_args, auction::ARG_DELEGATION_RATE)?;
let amount = Self::get_named_argument(runtime_args, auction::ARG_AMOUNT)?;

let global_minimum_delegation_amount =
self.context.engine_config().minimum_delegation_amount();
let minimum_delegation_amount = Self::try_get_named_argument(
runtime_args,
auction::ARG_MINIMUM_DELEGATION_AMOUNT,
)?
.unwrap_or(global_minimum_delegation_amount);

let global_maximum_delegation_amount =
self.context.engine_config().maximum_delegation_amount();
let maximum_delegation_amount = Self::try_get_named_argument(
runtime_args,
auction::ARG_MAXIMUM_DELEGATION_AMOUNT,
)?
.unwrap_or(global_maximum_delegation_amount);

if minimum_delegation_amount < global_minimum_delegation_amount
|| maximum_delegation_amount > global_maximum_delegation_amount
|| minimum_delegation_amount > maximum_delegation_amount
{
return Err(ExecError::Revert(ApiError::InvalidDelegationAmountLimits));
}

let result = runtime
.add_bid(account_hash, delegation_rate, amount)
.add_bid(
account_hash,
delegation_rate,
amount,
minimum_delegation_amount,
maximum_delegation_amount,
)
.map_err(Self::reverter)?;

CLValue::from_t(result).map_err(Self::reverter)
Expand All @@ -858,16 +904,9 @@ where

let max_delegators_per_validator =
self.context.engine_config().max_delegators_per_validator();
let minimum_delegation_amount =
self.context.engine_config().minimum_delegation_amount();

let result = runtime
.delegate(
delegator,
validator,
amount,
max_delegators_per_validator,
minimum_delegation_amount,
)
.delegate(delegator, validator, amount, max_delegators_per_validator)
.map_err(Self::reverter)?;

CLValue::from_t(result).map_err(Self::reverter)
Expand Down Expand Up @@ -896,17 +935,8 @@ where
let new_validator =
Self::get_named_argument(runtime_args, auction::ARG_NEW_VALIDATOR)?;

let minimum_delegation_amount =
self.context.engine_config().minimum_delegation_amount();

let result = runtime
.redelegate(
delegator,
validator,
amount,
new_validator,
minimum_delegation_amount,
)
.redelegate(delegator, validator, amount, new_validator)
.map_err(Self::reverter)?;

CLValue::from_t(result).map_err(Self::reverter)
Expand All @@ -922,14 +952,11 @@ where

let max_delegators_per_validator =
self.context.engine_config().max_delegators_per_validator();
let minimum_delegation_amount =
self.context.engine_config().minimum_delegation_amount();
runtime
.run_auction(
era_end_timestamp_millis,
evicted_validators,
max_delegators_per_validator,
minimum_delegation_amount,
true,
Ratio::new_raw(U512::from(1), U512::from(5)),
)
Expand Down Expand Up @@ -3404,7 +3431,8 @@ where

// Check if the topic exists and get the summary.
let Some(StoredValue::MessageTopic(prev_topic_summary)) =
self.context.read_gs(&topic_key)? else {
self.context.read_gs(&topic_key)?
else {
return Ok(Err(ApiError::MessageTopicNotRegistered));
};

Expand Down
7 changes: 7 additions & 0 deletions execution_engine_testing/test_support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ pub const DEFAULT_MAX_QUERY_DEPTH: u64 = 5;
pub const DEFAULT_MAX_RUNTIME_CALL_STACK_HEIGHT: u32 = 12;
/// Default value for minimum delegation amount in motes.
pub const DEFAULT_MINIMUM_DELEGATION_AMOUNT: u64 = 500 * 1_000_000_000;
/// Default value for maximum delegation amount in motes.
pub const DEFAULT_MAXIMUM_DELEGATION_AMOUNT: u64 = 1_000_000_000 * 1_000_000_000;

/// Default genesis config hash.
pub const DEFAULT_GENESIS_CONFIG_HASH: Digest = Digest::from_raw([42; 32]);

Expand Down Expand Up @@ -211,6 +214,10 @@ mod tests {
production.core_config.minimum_delegation_amount,
DEFAULT_MINIMUM_DELEGATION_AMOUNT
);
assert_eq!(
production.core_config.maximum_delegation_amount,
DEFAULT_MAXIMUM_DELEGATION_AMOUNT
);

assert_eq!(production.wasm_config, WasmConfig::default());
// TODO: reenable after new payment logic is added
Expand Down
50 changes: 40 additions & 10 deletions execution_engine_testing/test_support/src/wasm_test_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ use casper_execution_engine::engine_state::{
};
use casper_storage::{
data_access_layer::{
balance::BalanceHandling, AuctionMethod, BalanceIdentifier, BalanceRequest, BalanceResult,
BiddingRequest, BiddingResult, BidsRequest, BlockRewardsRequest, BlockRewardsResult,
BlockStore, DataAccessLayer, EraValidatorsRequest, EraValidatorsResult, FeeRequest,
FeeResult, FlushRequest, FlushResult, GenesisRequest, GenesisResult, HandleFeeMode,
HandleFeeRequest, HandleFeeResult, ProofHandling, ProtocolUpgradeRequest,
ProtocolUpgradeResult, PruneRequest, PruneResult, QueryRequest, QueryResult,
RoundSeigniorageRateRequest, RoundSeigniorageRateResult, StepRequest, StepResult,
SystemEntityRegistryPayload, SystemEntityRegistryRequest, SystemEntityRegistryResult,
SystemEntityRegistrySelector, TotalSupplyRequest, TotalSupplyResult, TransferRequest,
TrieRequest,
balance::BalanceHandling,
forced_undelegate::{ForcedUndelegateRequest, ForcedUndelegateResult},
AuctionMethod, BalanceIdentifier, BalanceRequest, BalanceResult, BiddingRequest,
BiddingResult, BidsRequest, BlockRewardsRequest, BlockRewardsResult, BlockStore,
DataAccessLayer, EraValidatorsRequest, EraValidatorsResult, FeeRequest, FeeResult,
FlushRequest, FlushResult, GenesisRequest, GenesisResult, HandleFeeMode, HandleFeeRequest,
HandleFeeResult, ProofHandling, ProtocolUpgradeRequest, ProtocolUpgradeResult,
PruneRequest, PruneResult, QueryRequest, QueryResult, RoundSeigniorageRateRequest,
RoundSeigniorageRateResult, StepRequest, StepResult, SystemEntityRegistryPayload,
SystemEntityRegistryRequest, SystemEntityRegistryResult, SystemEntityRegistrySelector,
TotalSupplyRequest, TotalSupplyResult, TransferRequest, TrieRequest,
},
global_state::{
state::{
Expand Down Expand Up @@ -1033,6 +1034,35 @@ where
distribute_block_rewards_result
}

/// Undelegates delegator bids violating configured delegation limits.
pub fn forced_undelegate(
&mut self,
pre_state_hash: Option<Digest>,
protocol_version: ProtocolVersion,
block_time: u64,
) -> ForcedUndelegateResult {
let pre_state_hash = pre_state_hash.or(self.post_state_hash).unwrap();
let native_runtime_config = self.native_runtime_config();
let forced_undelegate_req = ForcedUndelegateRequest::new(
native_runtime_config,
pre_state_hash,
protocol_version,
BlockTime::new(block_time),
);
let forced_undelegate_result = self
.data_access_layer
.forced_undelegate(forced_undelegate_req);

if let ForcedUndelegateResult::Success {
post_state_hash, ..
} = forced_undelegate_result
{
self.post_state_hash = Some(post_state_hash);
}

forced_undelegate_result
}

/// Finalizes payment for a transaction
pub fn handle_fee(
&mut self,
Expand Down
8 changes: 4 additions & 4 deletions execution_engine_testing/tests/src/test/explorer/faucet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,10 +926,10 @@ fn faucet_costs() {
// This test will fail if execution costs vary. The expected costs should not be updated
// without understanding why the cost has changed. If the costs do change, it should be
// reflected in the "Costs by Entry Point" section of the faucet crate's README.md.
const EXPECTED_FAUCET_INSTALL_COST: u64 = 91_822_469_530;
const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 111_108_490;
const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_747_581_570;
const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_619_470_410;
const EXPECTED_FAUCET_INSTALL_COST: u64 = 91_840_114_390;
const EXPECTED_FAUCET_SET_VARIABLES_COST: u64 = 111_115_510;
const EXPECTED_FAUCET_CALL_BY_INSTALLER_COST: u64 = 2_747_592_370;
const EXPECTED_FAUCET_CALL_BY_USER_COST: u64 = 2_619_485_530;

let installer_account = AccountHash::new([1u8; 32]);
let user_account: AccountHash = AccountHash::new([2u8; 32]);
Expand Down
Loading

0 comments on commit 2073334

Please sign in to comment.