Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chain-Config update logic #208

Open
wants to merge 32 commits into
base: feat/chain-config
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
241c99c
Added new structs for Sovereign Chain Config
andreiblt1304 Dec 13, 2024
42c8e60
Updated `init` and `update` endpoints to use new struct and storage
andreiblt1304 Dec 13, 2024
50d668b
Removed any use of the `StakeMultiArg`
andreiblt1304 Dec 13, 2024
cd3b254
Clippy fix
andreiblt1304 Dec 13, 2024
d86f2d2
Chain-Config tests
andreiblt1304 Dec 19, 2024
e10eb27
Updated root `Cargo.lock`
andreiblt1304 Dec 19, 2024
4f2aeeb
Modified logic for config update
andreiblt1304 Dec 19, 2024
195f96b
Added ownership change transaction
andreiblt1304 Dec 19, 2024
2baa979
Whiteline
andreiblt1304 Dec 19, 2024
ce60191
Build + proxy
andreiblt1304 Dec 19, 2024
f2965ee
Merge branch 'config-update' into config-tests
andreiblt1304 Dec 19, 2024
1518ac2
Added `new()` function for `SovereignConfig`
andreiblt1304 Dec 19, 2024
31d75ab
Update chain-factory endpoint to use new struct
andreiblt1304 Dec 19, 2024
c1609c1
Merge branch 'config-update' into config-tests
andreiblt1304 Dec 19, 2024
2e722c1
Update unit test + build
andreiblt1304 Dec 19, 2024
866dac5
Fixed tests
andreiblt1304 Dec 19, 2024
0f718c3
Removed unused argument
andreiblt1304 Dec 19, 2024
257e3a6
Merge branch 'config-update' into config-tests
andreiblt1304 Dec 19, 2024
b47d69c
Build contracts + proxy
andreiblt1304 Dec 19, 2024
82ae7d5
Added endpoint annotation
andreiblt1304 Dec 19, 2024
245ce77
Merge branch 'config-update' into config-tests
andreiblt1304 Dec 19, 2024
382a7a7
Added `update_config` test
andreiblt1304 Dec 19, 2024
6e72794
Updated `init` and `update_config` logic
andreiblt1304 Dec 19, 2024
b5d977f
Removed unused import
andreiblt1304 Dec 19, 2024
16dbfb9
Added validators array unit test
andreiblt1304 Dec 19, 2024
5ac0490
Clippy fixes
andreiblt1304 Dec 19, 2024
de2c412
Removed comment
andreiblt1304 Dec 19, 2024
0fe84cf
Added `update_config` test
andreiblt1304 Dec 20, 2024
1e48365
Build + updated call to UserBuiltinProxy
andreiblt1304 Dec 20, 2024
76459ae
Removed unused imports
andreiblt1304 Dec 20, 2024
a338345
Updated config set logic
andreiblt1304 Dec 23, 2024
051ae2c
Merge branch 'feat/chain-config' into config-update
andreiblt1304 Dec 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions chain-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,14 @@ version = "=0.54.6"
[dependencies.multiversx-sc-modules]
version = "=0.54.6"

[dependencies.header-verifier]
path = "../header-verifier"

[dependencies.transaction]
path = "../common/transaction"

[dependencies.proxies]
path = "../common/proxies"

[dependencies.setup-phase]
path = "../common/setup-phase"
72 changes: 16 additions & 56 deletions chain-config/src/lib.rs
axenteoctavian marked this conversation as resolved.
Show resolved Hide resolved
andreiblt1304 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#![no_std]

use multiversx_sc_modules::only_admin;
use transaction::StakeMultiArg;
use validator_rules::TokenIdAmountPair;
use transaction::SovereignConfig;

multiversx_sc::imports!();

Expand All @@ -13,72 +12,33 @@ pub trait ChainConfigContract:
validator_rules::ValidatorRulesModule + only_admin::OnlyAdminModule + setup_phase::SetupPhaseModule
{
#[init]
fn init(
&self,
min_validators: u64,
max_validators: u64,
min_stake: BigUint,
admin: ManagedAddress,
additional_stake_required: MultiValueEncoded<StakeMultiArg<Self::Api>>,
) {
require!(
min_validators <= max_validators,
"Invalid min/max validator numbers"
);

let mut additional_stake_vec = ManagedVec::new();
for multi_value in additional_stake_required {
let (token_id, amount) = multi_value.into_tuple();
let value = TokenIdAmountPair { token_id, amount };

additional_stake_vec.push(value);
}

self.min_validators().set(min_validators);
self.max_validators().set(max_validators);
self.min_stake().set(min_stake);
fn init(&self, config: SovereignConfig<Self::Api>, admin: ManagedAddress) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call require_valid_config in init

self.sovereign_config().set(config.clone());
self.require_valid_config(&config);
self.add_admin(admin);
self.additional_stake_required().set(additional_stake_vec);
}

#[only_admin]
fn update_config(
&self,
opt_min_validators: Option<u64>,
opt_max_validators: Option<u64>,
opt_min_stake: Option<BigUint>,
opt_additional_stake_required: Option<MultiValueEncoded<StakeMultiArg<Self::Api>>>,
) {
if let Some(min_validators) = opt_min_validators {
self.min_validators().set(min_validators);
}
if let Some(max_validators) = opt_max_validators {
self.max_validators().set(max_validators);
}
if let Some(min_stake) = opt_min_stake {
self.min_stake().set(min_stake);
}
if let Some(additional_stake_required) = opt_additional_stake_required {
let mut additional_stake_vec = ManagedVec::new();
for multi_value in additional_stake_required {
let (token_id, amount) = multi_value.into_tuple();
let value = TokenIdAmountPair { token_id, amount };

additional_stake_vec.push(value);
}
self.additional_stake_required().set(additional_stake_vec);
}
#[endpoint(updateConfig)]
fn update_config(&self, new_config: SovereignConfig<Self::Api>) {
self.require_valid_config(&new_config);
self.sovereign_config().set(new_config);
}

#[only_owner]
fn complete_setup_phase(&self) {
#[endpoint(completeSetupPhase)]
fn complete_setup_phase(&self, header_verifier_address: ManagedAddress) {
if self.is_setup_phase_complete() {
return;
}

self.require_config_set();
// validator set in header verifier
// change ownership to header-verifier
self.tx()
.to(ToSelf)
.typed(UserBuiltinProxy)
.change_owner_address(&header_verifier_address)
.sync_call();

self.setup_phase_complete().set(true);
}

Expand Down
48 changes: 15 additions & 33 deletions chain-config/src/validator_rules.rs
andreiblt1304 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use transaction::SovereignConfig;

multiversx_sc::imports!();
multiversx_sc::derive_imports!();

Expand All @@ -13,45 +15,25 @@ pub struct TokenIdAmountPair<M: ManagedTypeApi> {

#[multiversx_sc::module]
pub trait ValidatorRulesModule {
fn require_config_set(&self) {
require!(
!self.min_validators().is_empty(),
"The minimum number of validators is not set"
);
require!(
!self.max_validators().is_empty(),
"The maximum number of validators is not set"
);
fn require_valid_config(&self, config: &SovereignConfig<Self::Api>) {
require!(
!self.min_stake().is_empty(),
"The mininum number of stake is not set"
!self.sovereign_config().is_empty(),
"The Sovereign Config is not set"
);

self.require_validator_range(config.min_validators, config.max_validators);
}

fn require_validator_range(&self, min_validators: u64, max_validators: u64) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be called in require_config_set

require!(
!self.additional_stake_required().is_empty(),
"The additional stake criteria is not set"
min_validators <= max_validators,
"Invalid min/max validator numbers"
);
}

#[view(getMinValidators)]
#[storage_mapper("minValidators")]
fn min_validators(&self) -> SingleValueMapper<u64>;

#[view(getMaxValidators)]
#[storage_mapper("maxValidators")]
fn max_validators(&self) -> SingleValueMapper<u64>;

// TODO: Read user stake and verify
#[view(getMinStake)]
#[storage_mapper("minStake")]
fn min_stake(&self) -> SingleValueMapper<BigUint>;

// NOTE: ManagedVec or MultiValueEncoded ?
// TODO: Read user stake and verify
#[view(getAdditionalStakeRequired)]
#[storage_mapper("additionalStakeRequired")]
fn additional_stake_required(
&self,
) -> SingleValueMapper<ManagedVec<TokenIdAmountPair<Self::Api>>>;
#[view(sovereignConfig)]
#[storage_mapper("sovereignConfig")]
fn sovereign_config(&self) -> SingleValueMapper<SovereignConfig<Self::Api>>;

#[view(wasPreviouslySlashed)]
#[storage_mapper("wasPreviouslySlashed")]
Expand Down
128 changes: 128 additions & 0 deletions chain-config/tests/chain_config_unit_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use multiversx_sc::types::{BigUint, TestAddress, TestSCAddress};
use multiversx_sc_scenario::{
api::StaticApi, imports::MxscPath, ExpectError, ScenarioTxRun, ScenarioWorld,
};
use proxies::chain_config_proxy::ChainConfigContractProxy;
use transaction::SovereignConfig;

const CONFIG_ADDRESS: TestSCAddress = TestSCAddress::new("config-address");
const CONFIG_CODE_PATH: MxscPath = MxscPath::new("output/chain-config.mxsc.json");

const HEADER_VERIFIER_ADDRESS: TestSCAddress = TestSCAddress::new("header-verifier");

const OWNER: TestAddress = TestAddress::new("owner");
const OWNER_BALANCE: u64 = 100_000_000_000;

fn world() -> ScenarioWorld {
let mut blockchain = ScenarioWorld::new();

blockchain.register_contract(CONFIG_CODE_PATH, chain_config::ContractBuilder);

blockchain
}

struct ChainConfigTestState {
world: ScenarioWorld,
}

impl ChainConfigTestState {
fn new() -> Self {
let mut world = world();

world.account(OWNER).balance(OWNER_BALANCE).nonce(1);

Self { world }
}

fn deploy_chain_config(&mut self, config: SovereignConfig<StaticApi>, admin: TestAddress) {
self.world
.tx()
.from(OWNER)
.typed(ChainConfigContractProxy)
.init(config, admin)
.code(CONFIG_CODE_PATH)
.new_address(CONFIG_ADDRESS)
.run();
}

fn update_chain_config(
&mut self,
config: SovereignConfig<StaticApi>,
expect_error: Option<ExpectError>,
) {
let transaction = self
.world
.tx()
.from(OWNER)
.to(CONFIG_ADDRESS)
.typed(ChainConfigContractProxy)
.update_config(config);

if let Some(error) = expect_error {
transaction.returns(error).run();
} else {
transaction.run();
}
}

fn complete_setup_phase(&mut self, expect_error: Option<ExpectError>) {
let transaction = self
.world
.tx()
.from(OWNER)
.to(CONFIG_ADDRESS)
.typed(ChainConfigContractProxy)
.complete_setup_phase(HEADER_VERIFIER_ADDRESS);

if let Some(error) = expect_error {
transaction.returns(error).run();
} else {
transaction.run();
}
}
}

#[test]
fn deploy_chain_config() {
let mut state = ChainConfigTestState::new();

let config = SovereignConfig::new(0, 1, BigUint::default(), None);
state.deploy_chain_config(config, OWNER);
}

#[test]
fn update_config() {
let mut state = ChainConfigTestState::new();

let config = SovereignConfig::new(0, 1, BigUint::default(), None);
state.deploy_chain_config(config, OWNER);

let new_config = SovereignConfig::new(2, 4, BigUint::default(), None);

state.update_chain_config(new_config, None);
}

#[test]
fn update_config_wrong_validators_array() {
let mut state = ChainConfigTestState::new();

let config = SovereignConfig::new(0, 1, BigUint::default(), None);
state.deploy_chain_config(config, OWNER);

let new_config = SovereignConfig::new(2, 1, BigUint::default(), None);

state.update_chain_config(
new_config,
Some(ExpectError(4, "Invalid min/max validator numbers")),
);
}

#[test]
fn complete_setup_phase() {
let mut state = ChainConfigTestState::new();

let config = SovereignConfig::new(0, 1, BigUint::default(), None);
state.deploy_chain_config(config, OWNER);

state.complete_setup_phase(None);
}
29 changes: 29 additions & 0 deletions chain-config/wasm-chain-config-full/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading