Skip to content

Commit 15d61f5

Browse files
committed
Added chainspec property minimum_delegation_rate
Minimum delegation rate applies to new add bids and new reservations Co-author: Michał Papierski michal@papierski.net
1 parent 4058227 commit 15d61f5

File tree

36 files changed

+662
-78
lines changed

36 files changed

+662
-78
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

execution_engine/src/runtime/mod.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ use casper_types::{
5252
},
5353
system::{
5454
self,
55-
auction::{self, DelegatorKind, EraInfo},
56-
handle_payment, mint,
57-
mint::MINT_SUSTAIN_PURSE_KEY,
55+
auction::{self, DelegatorKind, EraInfo, MINIMUM_DELEGATION_RATE_KEY},
56+
handle_payment,
57+
mint::{self, MINT_SUSTAIN_PURSE_KEY},
5858
CallStackElement, Caller, CallerInfo, SystemEntityType, AUCTION, HANDLE_PAYMENT, MINT,
5959
STANDARD_PAYMENT,
6060
},
@@ -1084,7 +1084,7 @@ where
10841084

10851085
let max_delegators_per_validator =
10861086
self.context.engine_config().max_delegators_per_validator();
1087-
1087+
let minimum_delegation_rate = self.get_minimum_delegation_rate()?;
10881088
let minimum_bid_amount = self.context().engine_config().minimum_bid_amount();
10891089

10901090
let result = runtime
@@ -1099,6 +1099,7 @@ where
10991099
reserved_slots,
11001100
global_minimum_delegation_amount,
11011101
global_maximum_delegation_amount,
1102+
minimum_delegation_rate,
11021103
)
11031104
.map_err(Self::reverter)?;
11041105

@@ -1325,8 +1326,9 @@ where
13251326
let reservations =
13261327
Self::get_named_argument(runtime_args, auction::ARG_RESERVATIONS)?;
13271328

1329+
let minimum_delegation_rate = self.get_minimum_delegation_rate()?;
13281330
runtime
1329-
.add_reservations(reservations)
1331+
.add_reservations(reservations, minimum_delegation_rate)
13301332
.map_err(Self::reverter)?;
13311333

13321334
CLValue::from_t(()).map_err(Self::reverter)
@@ -4665,6 +4667,31 @@ where
46654667
)?;
46664668
Ok(Ok(()))
46674669
}
4670+
4671+
fn get_minimum_delegation_rate(&self) -> Result<u8, ExecError> {
4672+
let auction_contract_hash = self.context.get_system_contract(AUCTION)?;
4673+
let auction_named_keys = self
4674+
.context
4675+
.state()
4676+
.borrow_mut()
4677+
.get_named_keys(EntityAddr::System(auction_contract_hash.value()))?;
4678+
let minimum_delegation_rate_key =
4679+
auction_named_keys.get(MINIMUM_DELEGATION_RATE_KEY).ok_or(
4680+
ExecError::NamedKeyNotFound(MINIMUM_DELEGATION_RATE_KEY.to_string()),
4681+
)?;
4682+
let stored_value = self
4683+
.context
4684+
.state()
4685+
.borrow_mut()
4686+
.read(minimum_delegation_rate_key)?
4687+
.ok_or_else(|| ExecError::KeyNotFound(*minimum_delegation_rate_key))?;
4688+
if let StoredValue::CLValue(cl_value) = stored_value {
4689+
let minimum_delegation_rate: u8 = cl_value.into_t().map_err(ExecError::CLValue)?;
4690+
Ok(minimum_delegation_rate)
4691+
} else {
4692+
Err(ExecError::UnexpectedStoredValueVariant)
4693+
}
4694+
}
46684695
}
46694696

46704697
#[cfg(feature = "test-support")]

execution_engine_testing/test_support/src/chainspec_config.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ impl ChainspecConfig {
131131
locked_funds_period,
132132
unbonding_delay,
133133
round_seigniorage_rate,
134+
minimum_delegation_rate,
134135
..
135136
} = core_config;
136137

@@ -145,6 +146,7 @@ impl ChainspecConfig {
145146
.with_unbonding_delay(*unbonding_delay)
146147
.with_genesis_timestamp_millis(DEFAULT_GENESIS_TIMESTAMP_MILLIS)
147148
.with_storage_costs(*storage_costs)
149+
.with_minimum_delegation_rate(*minimum_delegation_rate)
148150
.build();
149151

150152
Ok(GenesisRequest::new(
@@ -167,6 +169,12 @@ impl ChainspecConfig {
167169
)
168170
}
169171

172+
/// Sets the minimum delegation rate config option.
173+
pub fn with_minimum_delegation_rate(mut self, minimum_delegation_rate: u8) -> Self {
174+
self.core_config.minimum_delegation_rate = minimum_delegation_rate;
175+
self
176+
}
177+
170178
/// Sets the vesting schedule period millis config option.
171179
pub fn with_max_associated_keys(&mut self, value: u32) -> &mut Self {
172180
self.core_config.max_associated_keys = value;
@@ -311,6 +319,7 @@ impl TryFrom<ChainspecConfig> for GenesisConfig {
311319
.with_genesis_timestamp_millis(DEFAULT_GENESIS_TIMESTAMP_MILLIS)
312320
.with_storage_costs(chainspec_config.storage_costs)
313321
.with_enable_addressable_entity(chainspec_config.core_config.enable_addressable_entity)
322+
.with_minimum_delegation_rate(chainspec_config.core_config.minimum_delegation_rate)
314323
.build())
315324
}
316325
}

execution_engine_testing/test_support/src/genesis_config_builder.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! A builder for an [`GenesisConfig`].
22
use casper_execution_engine::engine_state::engine_config::DEFAULT_ENABLE_ENTITY;
33
use casper_types::{
4-
GenesisAccount, GenesisConfig, HoldBalanceHandling, StorageCosts, SystemConfig, WasmConfig,
4+
system::auction::DelegationRate, GenesisAccount, GenesisConfig, HoldBalanceHandling,
5+
StorageCosts, SystemConfig, WasmConfig,
56
};
67
use num_rational::Ratio;
78

@@ -31,6 +32,7 @@ pub struct GenesisConfigBuilder {
3132
enable_addressable_entity: Option<bool>,
3233
rewards_ratio: Option<Ratio<u64>>,
3334
storage_costs: Option<StorageCosts>,
35+
minimum_delegation_rate: DelegationRate,
3436
}
3537

3638
impl GenesisConfigBuilder {
@@ -111,6 +113,12 @@ impl GenesisConfigBuilder {
111113
self
112114
}
113115

116+
/// Sets the minimum delegation rate config option.
117+
pub fn with_minimum_delegation_rate(mut self, minimum_delegation_rate: DelegationRate) -> Self {
118+
self.minimum_delegation_rate = minimum_delegation_rate;
119+
self
120+
}
121+
114122
/// Builds a new [`GenesisConfig`] object.
115123
pub fn build(self) -> GenesisConfig {
116124
GenesisConfig::new(
@@ -134,6 +142,7 @@ impl GenesisConfigBuilder {
134142
.unwrap_or(DEFAULT_ENABLE_ENTITY),
135143
self.rewards_ratio,
136144
self.storage_costs.unwrap_or_default(),
145+
self.minimum_delegation_rate,
137146
)
138147
}
139148
}

execution_engine_testing/test_support/src/upgrade_request_builder.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use std::collections::BTreeMap;
33
use num_rational::Ratio;
44

55
use casper_types::{
6-
ChainspecRegistry, Digest, EraId, FeeHandling, HoldBalanceHandling, Key, ProtocolUpgradeConfig,
7-
ProtocolVersion, RewardsHandling, StoredValue,
6+
system::auction::DelegationRate, ChainspecRegistry, Digest, EraId, FeeHandling,
7+
HoldBalanceHandling, Key, ProtocolUpgradeConfig, ProtocolVersion, RewardsHandling, StoredValue,
88
};
99

1010
/// Builds an `UpgradeConfig`.
@@ -28,6 +28,7 @@ pub struct UpgradeRequestBuilder {
2828
minimum_delegation_amount: u64,
2929
enable_addressable_entity: bool,
3030
rewards_handling: RewardsHandling,
31+
new_minimum_delegation_rate: Option<DelegationRate>,
3132
}
3233

3334
impl UpgradeRequestBuilder {
@@ -156,6 +157,15 @@ impl UpgradeRequestBuilder {
156157
self
157158
}
158159

160+
/// Sets the minimum delegation rate for validator bids and reservations.
161+
pub fn with_new_minimum_delegation_rate(
162+
mut self,
163+
new_minimum_delegation_rate: DelegationRate,
164+
) -> Self {
165+
self.new_minimum_delegation_rate = Some(new_minimum_delegation_rate);
166+
self
167+
}
168+
159169
/// Consumes the `UpgradeRequestBuilder` and returns an [`ProtocolUpgradeConfig`].
160170
pub fn build(self) -> ProtocolUpgradeConfig {
161171
ProtocolUpgradeConfig::new(
@@ -178,6 +188,7 @@ impl UpgradeRequestBuilder {
178188
self.minimum_delegation_amount,
179189
self.enable_addressable_entity,
180190
self.rewards_handling,
191+
self.new_minimum_delegation_rate,
181192
)
182193
}
183194
}
@@ -204,6 +215,7 @@ impl Default for UpgradeRequestBuilder {
204215
minimum_delegation_amount: 0,
205216
enable_addressable_entity: false,
206217
rewards_handling: RewardsHandling::Standard,
218+
new_minimum_delegation_rate: None,
207219
}
208220
}
209221
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use casper_engine_test_support::{
2+
ChainspecConfig, ExecuteRequestBuilder, LmdbWasmTestBuilder, DEFAULT_ACCOUNTS,
3+
DEFAULT_ACCOUNT_ADDR, DEFAULT_ACCOUNT_PUBLIC_KEY, DEFAULT_PROTOCOL_VERSION,
4+
};
5+
use casper_execution_engine::{engine_state::Error, execution::ExecError};
6+
use casper_types::{
7+
runtime_args,
8+
system::auction::{ARG_AMOUNT, ARG_DELEGATION_RATE, ARG_PUBLIC_KEY},
9+
ApiError, U512,
10+
};
11+
use once_cell::sync::Lazy;
12+
use std::path::PathBuf;
13+
14+
const ADD_BIDS_WASM: &str = "auction_bids.wasm";
15+
const ARG_ENTRY_POINT: &str = "entry_point";
16+
/// The name of the chainspec file on disk.
17+
pub const CHAINSPEC_NAME: &str = "chainspec.toml";
18+
pub static LOCAL_PATH: Lazy<PathBuf> =
19+
Lazy::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../resources/local/"));
20+
21+
#[ignore]
22+
#[test]
23+
fn add_auction_should_fail_when_delegation_rate_not_met() {
24+
let path = LOCAL_PATH.join(CHAINSPEC_NAME);
25+
let mut chainspec =
26+
ChainspecConfig::from_chainspec_path(path).expect("must build chainspec configuration");
27+
chainspec = chainspec.with_minimum_delegation_rate(20);
28+
let mut builder = LmdbWasmTestBuilder::new_temporary_with_config(chainspec.clone());
29+
let genesis_request = chainspec
30+
.create_genesis_request(DEFAULT_ACCOUNTS.clone(), DEFAULT_PROTOCOL_VERSION)
31+
.unwrap();
32+
builder.run_genesis(genesis_request);
33+
34+
let exec_request = ExecuteRequestBuilder::standard(
35+
*DEFAULT_ACCOUNT_ADDR,
36+
ADD_BIDS_WASM,
37+
runtime_args! {
38+
ARG_ENTRY_POINT => "add_bid",
39+
ARG_PUBLIC_KEY => DEFAULT_ACCOUNT_PUBLIC_KEY.clone(),
40+
ARG_AMOUNT => U512::from(10_000_000_000_000u64),
41+
ARG_DELEGATION_RATE => 19u8,
42+
},
43+
)
44+
.build();
45+
46+
let commit = builder.exec(exec_request).commit();
47+
commit.expect_failure();
48+
let last_exec_result = commit
49+
.get_last_exec_result()
50+
.expect("Expected to be called after exec()");
51+
assert!(matches!(
52+
last_exec_result.error().cloned(),
53+
Some(Error::Exec(ExecError::Revert(ApiError::AuctionError(64))))
54+
));
55+
}

execution_engine_testing/tests/src/test/contract_api/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod account;
22
mod add_contract_version;
3+
mod auction;
34
mod create_purse;
45
mod dictionary;
56
mod generic_hash;

execution_engine_testing/tests/src/test/system_contracts/upgrade.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ use casper_types::{
1818
auction::{
1919
DelegatorKind, SeigniorageRecipientsSnapshotV1, SeigniorageRecipientsSnapshotV2,
2020
AUCTION_DELAY_KEY, DEFAULT_SEIGNIORAGE_RECIPIENTS_SNAPSHOT_VERSION,
21-
LOCKED_FUNDS_PERIOD_KEY, SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY,
22-
SEIGNIORAGE_RECIPIENTS_SNAPSHOT_VERSION_KEY, UNBONDING_DELAY_KEY, VALIDATOR_SLOTS_KEY,
21+
LOCKED_FUNDS_PERIOD_KEY, MINIMUM_DELEGATION_RATE_KEY,
22+
SEIGNIORAGE_RECIPIENTS_SNAPSHOT_KEY, SEIGNIORAGE_RECIPIENTS_SNAPSHOT_VERSION_KEY,
23+
UNBONDING_DELAY_KEY, VALIDATOR_SLOTS_KEY,
2324
},
2425
mint::ROUND_SEIGNIORAGE_RATE_KEY,
2526
},
@@ -889,3 +890,67 @@ fn should_migrate_seigniorage_snapshot_to_new_version() {
889890
}
890891
}
891892
}
893+
894+
#[test]
895+
fn should_store_and_upgrade_minimum_delegation_rate_named_key() {
896+
const UPGRADED_MINIMUM_DELEGATION_RATE: u8 = 20;
897+
898+
let mut builder = LmdbWasmTestBuilder::default();
899+
builder.run_genesis(LOCAL_GENESIS_REQUEST.clone());
900+
901+
let auction_contract_hash = builder.get_auction_contract_hash();
902+
let auction_named_keys =
903+
builder.get_named_keys(EntityAddr::System(auction_contract_hash.value()));
904+
let minimum_delegation_rate_key = *auction_named_keys
905+
.get(MINIMUM_DELEGATION_RATE_KEY)
906+
.expect("minimum delegation rate key should exist at genesis");
907+
908+
let minimum_delegation_rate: u8 = builder
909+
.query(None, minimum_delegation_rate_key, &[])
910+
.expect("should have minimum delegation rate")
911+
.as_cl_value()
912+
.expect("minimum delegation rate should be a CLValue")
913+
.clone()
914+
.into_t()
915+
.expect("minimum delegation rate should be u8");
916+
917+
assert_eq!(
918+
minimum_delegation_rate, 0,
919+
"genesis should have set minimum delegation rate to 0!"
920+
);
921+
922+
let sem_ver = PROTOCOL_VERSION.value();
923+
let new_protocol_version =
924+
ProtocolVersion::from_parts(sem_ver.major, sem_ver.minor, sem_ver.patch + 1);
925+
926+
let mut upgrade_request = UpgradeRequestBuilder::new()
927+
.with_current_protocol_version(PROTOCOL_VERSION)
928+
.with_new_protocol_version(new_protocol_version)
929+
.with_activation_point(DEFAULT_ACTIVATION_POINT)
930+
.with_new_minimum_delegation_rate(UPGRADED_MINIMUM_DELEGATION_RATE)
931+
.build();
932+
933+
builder
934+
.upgrade(&mut upgrade_request)
935+
.expect_upgrade_success();
936+
937+
let upgraded_auction_contract_hash = builder.get_auction_contract_hash();
938+
let upgraded_named_keys =
939+
builder.get_named_keys(EntityAddr::System(upgraded_auction_contract_hash.value()));
940+
let upgraded_minimum_delegation_rate_key = *upgraded_named_keys
941+
.get(MINIMUM_DELEGATION_RATE_KEY)
942+
.expect("minimum delegation rate key should exist after upgrade");
943+
let upgraded_minimum_delegation_rate: u8 = builder
944+
.query(None, upgraded_minimum_delegation_rate_key, &[])
945+
.expect("should have upgraded minimum delegation rate")
946+
.as_cl_value()
947+
.expect("minimum delegation rate should be a CLValue")
948+
.clone()
949+
.into_t()
950+
.expect("minimum delegation rate should be u8");
951+
952+
assert_eq!(
953+
upgraded_minimum_delegation_rate,
954+
UPGRADED_MINIMUM_DELEGATION_RATE
955+
);
956+
}

0 commit comments

Comments
 (0)