diff --git a/changelog.md b/changelog.md index 24ce75bb10..10a4332861 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,7 @@ This changelog is based on [Keep A Changelog](https://keepachangelog.com/en/1.1. ## Changed +* DParam now uses new schema, which involves `native_take` validators count. * Updated polkadot-sdk dependency to polkadot-stable2509. Partner Chains Aura modification follows changes regarding checking inherents that are also present in the new polkadot-sdk release. Pallet Session new parameters should be: `type KeyDeposit = ();` and `type Currency = Balances;`. diff --git a/demo/runtime/src/mock.rs b/demo/runtime/src/mock.rs index 4db8ede173..6c70c91288 100644 --- a/demo/runtime/src/mock.rs +++ b/demo/runtime/src/mock.rs @@ -384,6 +384,7 @@ pub fn create_inherent_data_struct( d_parameter: DParameter { num_permissioned_candidates: 0, num_registered_candidates: max(candidates.len() as u16, 1), + num_native_stake_candidates: 0, }, permissioned_candidates: vec![], registered_candidates: candidates, diff --git a/dev/local-environment/configurations/partner-chains-setup/entrypoint.sh b/dev/local-environment/configurations/partner-chains-setup/entrypoint.sh index 03c18b0fcf..aba3ffe419 100644 --- a/dev/local-environment/configurations/partner-chains-setup/entrypoint.sh +++ b/dev/local-environment/configurations/partner-chains-setup/entrypoint.sh @@ -79,6 +79,7 @@ echo "Inserting D parameter..." --genesis-utxo $GENESIS_UTXO \ --permissioned-candidates-count 3 \ --registered-candidates-count 1 \ + --native-stake-candidates-count 0 \ --payment-key-file /keys/funded_address.skey if [ $? -eq 0 ]; then diff --git a/toolkit/committee-selection/authority-selection-inherents/src/mock.rs b/toolkit/committee-selection/authority-selection-inherents/src/mock.rs index 0d06f4da2f..6c4e8d40a2 100644 --- a/toolkit/committee-selection/authority-selection-inherents/src/mock.rs +++ b/toolkit/committee-selection/authority-selection-inherents/src/mock.rs @@ -59,6 +59,7 @@ impl AuthoritySelectionDataSource for MockAuthoritySelectionDataSource { d_parameter: DParameter { num_permissioned_candidates: self.num_permissioned_candidates, num_registered_candidates: 2, + num_native_stake_candidates: 0, }, permissioned_candidates: candidates.clone(), }), diff --git a/toolkit/committee-selection/authority-selection-inherents/src/select_authorities.rs b/toolkit/committee-selection/authority-selection-inherents/src/select_authorities.rs index 6f4e464292..6e81b7b61e 100644 --- a/toolkit/committee-selection/authority-selection-inherents/src/select_authorities.rs +++ b/toolkit/committee-selection/authority-selection-inherents/src/select_authorities.rs @@ -62,6 +62,11 @@ fn select_candidates< validators.len(), sidechain_epoch ); + info!( + "JAZDA {} {}", + input.d_parameter.num_permissioned_candidates, + input.d_parameter.num_registered_candidates + ); Some(validators.into_iter().map(|member| member.into()).collect()) } else { warn!("🚫 Failed to select validators for epoch {}", sidechain_epoch); diff --git a/toolkit/committee-selection/authority-selection-inherents/src/tests.rs b/toolkit/committee-selection/authority-selection-inherents/src/tests.rs index 0ca46f5768..95ae590623 100644 --- a/toolkit/committee-selection/authority-selection-inherents/src/tests.rs +++ b/toolkit/committee-selection/authority-selection-inherents/src/tests.rs @@ -188,7 +188,11 @@ fn ariadne_all_permissioned_test() { // Expected committee: [alice, bob] let permissioned_validators = vec![ALICE, BOB]; let registered_validators = vec![CHARLIE, DAVE]; - let d_parameter = DParameter { num_permissioned_candidates: 8, num_registered_candidates: 0 }; + let d_parameter = DParameter { + num_permissioned_candidates: 8, + num_registered_candidates: 0, + num_native_stake_candidates: 0, + }; let authority_selection_inputs = create_authority_selection_inputs( &permissioned_validators, ®istered_validators, @@ -220,7 +224,11 @@ fn ariadne_only_permissioned_candidates_are_present_test() { // D-param: (4, 4) let permissioned_validators = vec![ALICE, BOB]; let registered_validators = vec![]; - let d_parameter = DParameter { num_permissioned_candidates: 4, num_registered_candidates: 4 }; + let d_parameter = DParameter { + num_permissioned_candidates: 4, + num_registered_candidates: 4, + num_native_stake_candidates: 0, + }; let authority_selection_inputs = create_authority_selection_inputs( &permissioned_validators, ®istered_validators, @@ -252,7 +260,11 @@ fn ariadne_3_to_2_test() { // D-param: (3, 2) let permissioned_validators = vec![ALICE, BOB, CHARLIE]; let registered_validators = vec![DAVE, EVE]; - let d_parameter = DParameter { num_permissioned_candidates: 3, num_registered_candidates: 2 }; + let d_parameter = DParameter { + num_permissioned_candidates: 3, + num_registered_candidates: 2, + num_native_stake_candidates: 0, + }; let authority_selection_inputs = create_authority_selection_inputs( &permissioned_validators, ®istered_validators, @@ -283,7 +295,11 @@ fn ariadne_3_to_2_with_more_available_candidates_test() { // D-param: (3, 2) let permissioned_validators = vec![ALICE, BOB, CHARLIE, DAVE, EVE]; let registered_validators = vec![FERDIE, GREG, HENRY, IDA]; - let d_parameter = DParameter { num_permissioned_candidates: 3, num_registered_candidates: 2 }; + let d_parameter = DParameter { + num_permissioned_candidates: 3, + num_registered_candidates: 2, + num_native_stake_candidates: 0, + }; let authority_selection_inputs = create_authority_selection_inputs( &permissioned_validators, ®istered_validators, @@ -321,7 +337,11 @@ fn ariadne_4_to_7_test() { // D-param: (4, 7) let permissioned_validators = vec![ALICE, BOB, CHARLIE, DAVE]; let registered_validators = vec![EVE, FERDIE, GREG, HENRY, IDA, JAMES, KIM]; - let d_parameter = DParameter { num_permissioned_candidates: 4, num_registered_candidates: 7 }; + let d_parameter = DParameter { + num_permissioned_candidates: 4, + num_registered_candidates: 7, + num_native_stake_candidates: 0, + }; let authority_selection_inputs = create_authority_selection_inputs( &permissioned_validators, ®istered_validators, @@ -352,7 +372,11 @@ fn ariadne_does_not_return_empty_committee() { let authority_selection_inputs = create_authority_selection_inputs( &[], &[], - DParameter { num_permissioned_candidates: 1, num_registered_candidates: 1 }, + DParameter { + num_permissioned_candidates: 1, + num_registered_candidates: 1, + num_native_stake_candidates: 0, + }, ); let calculated_committee = select_authorities::( UtxoId::default(), diff --git a/toolkit/committee-selection/query/src/commands.rs b/toolkit/committee-selection/query/src/commands.rs index f6c13e9b5c..35bcc9996a 100644 --- a/toolkit/committee-selection/query/src/commands.rs +++ b/toolkit/committee-selection/query/src/commands.rs @@ -87,8 +87,11 @@ mod tests { #[tokio::test] async fn ariadne_parameters_returns_correct_json_string() { - let d_parameter = - DParameter { num_permissioned_candidates: 1, num_registered_candidates: 2 }; + let d_parameter = DParameter { + num_permissioned_candidates: 1, + num_registered_candidates: 2, + num_native_stake_candidates: 0, + }; let permissioned_candidates = vec![PermissionedCandidateData { sidechain_public_key: SidechainPublicKey( hex!("0389411795514af1627765eceffcbd002719f031604fadd7d188e2dc585b4e1afb").to_vec(), @@ -130,6 +133,7 @@ mod tests { serde_json::from_str::(&cmd_output).unwrap(), serde_json::json!({ "dParameter": { + "numNativeStakeCandidates": 0, "numPermissionedCandidates": 1, "numRegisteredCandidates": 2 }, diff --git a/toolkit/committee-selection/query/src/tests/mod.rs b/toolkit/committee-selection/query/src/tests/mod.rs index f353284936..44455ba1d1 100644 --- a/toolkit/committee-selection/query/src/tests/mod.rs +++ b/toolkit/committee-selection/query/src/tests/mod.rs @@ -351,6 +351,7 @@ mod get_registration_tests { d_parameter: types::DParameter { num_permissioned_candidates: 3, num_registered_candidates: 2, + num_native_stake_candidates: 0, }, permissioned_candidates: Some( permissioned_candidates diff --git a/toolkit/committee-selection/query/src/types/ariadne.rs b/toolkit/committee-selection/query/src/types/ariadne.rs index 2c0ddb80e4..1961b3c061 100644 --- a/toolkit/committee-selection/query/src/types/ariadne.rs +++ b/toolkit/committee-selection/query/src/types/ariadne.rs @@ -24,6 +24,8 @@ pub struct DParameter { pub num_permissioned_candidates: u16, /// The number of registered candidates pub num_registered_candidates: u16, + /// The number of native stake candidates + pub num_native_stake_candidates: u16, } impl From for DParameter { @@ -31,9 +33,10 @@ impl From for DParameter { sidechain_domain::DParameter { num_permissioned_candidates, num_registered_candidates, + num_native_stake_candidates, }: sidechain_domain::DParameter, ) -> Self { - Self { num_permissioned_candidates, num_registered_candidates } + Self { num_permissioned_candidates, num_registered_candidates, num_native_stake_candidates } } } diff --git a/toolkit/data-sources/db-sync/src/candidates/tests.rs b/toolkit/data-sources/db-sync/src/candidates/tests.rs index b57f13edb3..70fbaa1c35 100644 --- a/toolkit/data-sources/db-sync/src/candidates/tests.rs +++ b/toolkit/data-sources/db-sync/src/candidates/tests.rs @@ -87,7 +87,7 @@ with_migration_versions! { .unwrap(); assert_eq!( result.d_parameter, - DParameter { num_permissioned_candidates: 1, num_registered_candidates: 3 } + DParameter { num_permissioned_candidates: 1, num_registered_candidates: 3, num_native_stake_candidates: 0 } ) } @@ -109,7 +109,7 @@ with_migration_versions! { assert_eq!(result.permissioned_candidates, Some(latest_permissioned_candidates())); assert_eq!( result.d_parameter, - DParameter { num_permissioned_candidates: 1, num_registered_candidates: 3 } + DParameter { num_permissioned_candidates: 1, num_registered_candidates: 3, num_native_stake_candidates: 0 } ) } @@ -125,7 +125,7 @@ with_migration_versions! { .unwrap(); assert_eq!( result.d_parameter, - DParameter { num_permissioned_candidates: 1, num_registered_candidates: 2 } + DParameter { num_permissioned_candidates: 1, num_registered_candidates: 2, num_native_stake_candidates: 0 } ); assert_eq!(result.permissioned_candidates, None) } @@ -236,7 +236,7 @@ mod candidate_caching { .unwrap(); assert_eq!( epoch_193_ariadne_parameters.d_parameter, - DParameter { num_permissioned_candidates: 1, num_registered_candidates: 3 } + DParameter { num_permissioned_candidates: 1, num_registered_candidates: 3, num_native_stake_candidates: 0 } ); // Remove all registrations to prove that one request was cached and the other not sqlx::raw_sql("DELETE FROM tx WHERE block_id >= 0") diff --git a/toolkit/data-sources/mock/examples/registrations.json b/toolkit/data-sources/mock/examples/registrations.json index cfd3579438..06c95dd49a 100644 --- a/toolkit/data-sources/mock/examples/registrations.json +++ b/toolkit/data-sources/mock/examples/registrations.json @@ -1,30 +1,31 @@ [ { "permissioned": [ - { - "name": "Test permissioned account 1", - "sidechain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "aura_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "grandpa_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000" - } + { + "name": "Test permissioned account 1", + "sidechain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "aura_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "grandpa_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000" + } ], "registrations": [ - { - "name": "Test registered account 2", - "sidechain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "mainchain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "mainchain_signature": "0x0000000000000000000000000000000000000000000000000000000000000000", - "sidechain_signature": "0x0000000000000000000000000000000000000000000000000000000000000000", - "registration_utxo": "0x0000000000000000000000000000000000000000000000000000000000000000#0", - "status": "Active", - "aura_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "grandpa_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000" - } + { + "name": "Test registered account 2", + "sidechain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "mainchain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "mainchain_signature": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sidechain_signature": "0x0000000000000000000000000000000000000000000000000000000000000000", + "registration_utxo": "0x0000000000000000000000000000000000000000000000000000000000000000#0", + "status": "Active", + "aura_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "grandpa_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000" + } ], "nonce": "0x0000000000000000000000000000000000000000000000000000000000000000", "d_parameter": { "permissioned": 16, - "registered": 16 + "registered": 16, + "native_stake": 0 } } -] +] \ No newline at end of file diff --git a/toolkit/data-sources/mock/registrations.json b/toolkit/data-sources/mock/registrations.json index cfd3579438..06c95dd49a 100644 --- a/toolkit/data-sources/mock/registrations.json +++ b/toolkit/data-sources/mock/registrations.json @@ -1,30 +1,31 @@ [ { "permissioned": [ - { - "name": "Test permissioned account 1", - "sidechain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "aura_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "grandpa_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000" - } + { + "name": "Test permissioned account 1", + "sidechain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "aura_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "grandpa_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000" + } ], "registrations": [ - { - "name": "Test registered account 2", - "sidechain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "mainchain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "mainchain_signature": "0x0000000000000000000000000000000000000000000000000000000000000000", - "sidechain_signature": "0x0000000000000000000000000000000000000000000000000000000000000000", - "registration_utxo": "0x0000000000000000000000000000000000000000000000000000000000000000#0", - "status": "Active", - "aura_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "grandpa_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000" - } + { + "name": "Test registered account 2", + "sidechain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "mainchain_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "mainchain_signature": "0x0000000000000000000000000000000000000000000000000000000000000000", + "sidechain_signature": "0x0000000000000000000000000000000000000000000000000000000000000000", + "registration_utxo": "0x0000000000000000000000000000000000000000000000000000000000000000#0", + "status": "Active", + "aura_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "grandpa_pub_key": "0x0000000000000000000000000000000000000000000000000000000000000000" + } ], "nonce": "0x0000000000000000000000000000000000000000000000000000000000000000", "d_parameter": { "permissioned": 16, - "registered": 16 + "registered": 16, + "native_stake": 0 } } -] +] \ No newline at end of file diff --git a/toolkit/data-sources/mock/src/candidate.rs b/toolkit/data-sources/mock/src/candidate.rs index 9654221741..d3976f9a77 100644 --- a/toolkit/data-sources/mock/src/candidate.rs +++ b/toolkit/data-sources/mock/src/candidate.rs @@ -124,17 +124,25 @@ impl From for PermissionedCandidateData { pub struct MockDParam { permissioned: u16, registered: u16, + native_stake: u16, } impl MockDParam { pub fn info_string(&self) -> String { - format!("permissioned: {}, registered: {}", self.permissioned, self.registered) + format!( + "permissioned: {}, registered: {}, native_stake: {}", + self.permissioned, self.registered, self.native_stake + ) } } impl From for DParameter { - fn from(MockDParam { permissioned, registered }: MockDParam) -> Self { - Self { num_permissioned_candidates: permissioned, num_registered_candidates: registered } + fn from(MockDParam { permissioned, registered, native_stake }: MockDParam) -> Self { + Self { + num_permissioned_candidates: permissioned, + num_registered_candidates: registered, + num_native_stake_candidates: native_stake, + } } } diff --git a/toolkit/partner-chains-cli/src/setup_main_chain_state/mod.rs b/toolkit/partner-chains-cli/src/setup_main_chain_state/mod.rs index af59ce133e..4fadd67561 100644 --- a/toolkit/partner-chains-cli/src/setup_main_chain_state/mod.rs +++ b/toolkit/partner-chains-cli/src/setup_main_chain_state/mod.rs @@ -96,6 +96,7 @@ impl CmdRun for SetupMainChainStateCmd { d_parameter.unwrap_or(DParameter { num_permissioned_candidates: 0, num_registered_candidates: 0, + num_native_stake_candidates: 0, }), chain_config.chain_parameters.genesis_utxo, )?; @@ -240,8 +241,11 @@ fn set_d_parameter_on_main_chain( CARDANO_PAYMENT_SIGNING_KEY_FILE.prompt_with_default_from_file_and_save(context); let payment_signing_key = cardano_key::get_mc_payment_signing_key_from_file(&payment_signing_key_path, context)?; - let d_parameter = - sidechain_domain::DParameter { num_permissioned_candidates, num_registered_candidates }; + let d_parameter = sidechain_domain::DParameter { + num_permissioned_candidates, + num_registered_candidates, + num_native_stake_candidates: 0, + }; let tokio_runtime = tokio::runtime::Runtime::new().map_err(|e| anyhow::anyhow!(e))?; let result = tokio_runtime.block_on(offchain.upsert_d_param( await_tx, diff --git a/toolkit/partner-chains-cli/src/setup_main_chain_state/tests.rs b/toolkit/partner-chains-cli/src/setup_main_chain_state/tests.rs index 2d1c2b774b..9689223787 100644 --- a/toolkit/partner-chains-cli/src/setup_main_chain_state/tests.rs +++ b/toolkit/partner-chains-cli/src/setup_main_chain_state/tests.rs @@ -253,7 +253,7 @@ fn upsert_permissioned_candidates_failed_io() -> MockIO { } fn new_d_parameter() -> DParameter { - DParameter::new(4, 7) + DParameter::new(4, 7, 0) } fn insert_d_parameter_io() -> MockIO { @@ -473,7 +473,11 @@ fn mock_with_ariadne_parameters_found() -> OffchainMock { OffchainMock::new() .with_get_d_param( genesis_utxo(), - Ok(Some(DParameter { num_permissioned_candidates: 6, num_registered_candidates: 4 })), + Ok(Some(DParameter { + num_permissioned_candidates: 6, + num_registered_candidates: 4, + num_native_stake_candidates: 0, + })), ) .with_get_permissioned_candidates( genesis_utxo(), @@ -485,7 +489,11 @@ fn mock_with_ariadne_parameters_same_as_in_config_response() -> OffchainMock { OffchainMock::new() .with_get_d_param( genesis_utxo(), - Ok(Some(DParameter { num_permissioned_candidates: 6, num_registered_candidates: 4 })), + Ok(Some(DParameter { + num_permissioned_candidates: 6, + num_registered_candidates: 4, + num_native_stake_candidates: 0, + })), ) .with_get_permissioned_candidates( genesis_utxo(), diff --git a/toolkit/sidechain/domain/src/lib.rs b/toolkit/sidechain/domain/src/lib.rs index 0ebe4a57e9..e6ff54506e 100644 --- a/toolkit/sidechain/domain/src/lib.rs +++ b/toolkit/sidechain/domain/src/lib.rs @@ -1166,7 +1166,7 @@ impl From for CandidateKey { Hash, )] #[cfg_attr(feature = "serde", derive(Serialize))] -/// Parameter controlling the number and proportion of registered and permissioned candidates +/// Parameter controlling the number and proportion of registered, permissioned, and native stake candidates /// selected into a Partner Chain committee, used by the Ariadne family of selection algorithms. /// /// The core idea behind the D-Param is to enable a Partner Chain to bootstrap its operation by @@ -1178,12 +1178,18 @@ pub struct DParameter { pub num_permissioned_candidates: u16, /// Expected number of registered candidates selected for a committee pub num_registered_candidates: u16, + /// Expected number of native stake candidates selected for a committee + pub num_native_stake_candidates: u16, } impl DParameter { /// Creates a new [DParameter] from member values - pub fn new(num_permissioned_candidates: u16, num_registered_candidates: u16) -> Self { - Self { num_permissioned_candidates, num_registered_candidates } + pub fn new( + num_permissioned_candidates: u16, + num_registered_candidates: u16, + num_native_stake_candidates: u16, + ) -> Self { + Self { num_permissioned_candidates, num_registered_candidates, num_native_stake_candidates } } } diff --git a/toolkit/smart-contracts/commands/src/d_parameter.rs b/toolkit/smart-contracts/commands/src/d_parameter.rs index 73456c907b..8026d0dab5 100644 --- a/toolkit/smart-contracts/commands/src/d_parameter.rs +++ b/toolkit/smart-contracts/commands/src/d_parameter.rs @@ -13,6 +13,9 @@ pub struct UpsertDParameterCmd { #[arg(long)] /// Number of registered candidates registered_candidates_count: u16, + #[arg(long)] + /// Number of native stake candidates + native_stake_candidates_count: u16, #[clap(flatten)] /// Path to the payment key file payment_key_file: PaymentFilePath, @@ -28,6 +31,7 @@ impl UpsertDParameterCmd { let d_param = DParameter { num_permissioned_candidates: self.permissioned_candidates_count, num_registered_candidates: self.registered_candidates_count, + num_native_stake_candidates: self.native_stake_candidates_count, }; let client = self.common_arguments.get_ogmios_client().await?; diff --git a/toolkit/smart-contracts/offchain/src/d_param/tests.rs b/toolkit/smart-contracts/offchain/src/d_param/tests.rs index dc4b057faf..1dcd83fe94 100644 --- a/toolkit/smart-contracts/offchain/src/d_param/tests.rs +++ b/toolkit/smart-contracts/offchain/src/d_param/tests.rs @@ -367,7 +367,11 @@ fn token_policy_id() -> [u8; 28] { } fn input_d_param() -> DParameter { - DParameter { num_registered_candidates: 30, num_permissioned_candidates: 40 } + DParameter { + num_registered_candidates: 30, + num_permissioned_candidates: 40, + num_native_stake_candidates: 0, + } } fn expected_plutus_data() -> PlutusData { diff --git a/toolkit/smart-contracts/offchain/tests/integration_tests.rs b/toolkit/smart-contracts/offchain/tests/integration_tests.rs index 07aa0333b4..41a95e5e4a 100644 --- a/toolkit/smart-contracts/offchain/tests/integration_tests.rs +++ b/toolkit/smart-contracts/offchain/tests/integration_tests.rs @@ -137,21 +137,25 @@ async fn upsert_d_param() { let client = initialize(&container).await; let genesis_utxo = run_init_governance(&client).await; assert!( - run_upsert_d_param(genesis_utxo, 0, 1, &governance_authority_payment_key(), &client) + run_upsert_d_param(genesis_utxo, 0, 1, 2, &governance_authority_payment_key(), &client) .await .is_some() ); assert!( - run_upsert_d_param(genesis_utxo, 0, 1, &governance_authority_payment_key(), &client) + run_upsert_d_param(genesis_utxo, 0, 1, 2, &governance_authority_payment_key(), &client) .await .is_none() ); assert_eq!( d_param::get_d_param(genesis_utxo, &client).await.unwrap().unwrap(), - DParameter { num_registered_candidates: 1, num_permissioned_candidates: 0 } + DParameter { + num_registered_candidates: 1, + num_permissioned_candidates: 0, + num_native_stake_candidates: 2, + } ); assert!( - run_upsert_d_param(genesis_utxo, 1, 1, &governance_authority_payment_key(), &client) + run_upsert_d_param(genesis_utxo, 1, 1, 1, &governance_authority_payment_key(), &client) .await .is_some() ) @@ -429,7 +433,7 @@ async fn governance_action_can_be_initiated_by_non_governance() { let container = image.start().await.unwrap(); let client = initialize(&container).await; let genesis_utxo = run_init_governance(&client).await; - let tx_to_sign = run_upsert_d_param(genesis_utxo, 1, 1, &eve_payment_key(), &client) + let tx_to_sign = run_upsert_d_param(genesis_utxo, 1, 1, 0, &eve_payment_key(), &client) .await .unwrap(); run_assemble_and_sign(tx_to_sign, &[GOVERNANCE_AUTHORITY_KEY], &client).await; @@ -593,12 +597,17 @@ async fn run_upsert_d_param< genesis_utxo: UtxoId, num_permissioned_candidates: u16, num_registered_candidates: u16, + num_native_stake_candidates: u16, pkey: &CardanoPaymentSigningKey, client: &T, ) -> Option { let result = d_param::upsert_d_param( genesis_utxo, - &DParameter { num_permissioned_candidates, num_registered_candidates }, + &DParameter { + num_permissioned_candidates, + num_registered_candidates, + num_native_stake_candidates, + }, pkey, client, &FixedDelayRetries::new(Duration::from_millis(500), 100), diff --git a/toolkit/smart-contracts/plutus-data/src/d_param.rs b/toolkit/smart-contracts/plutus-data/src/d_param.rs index 251cbc901b..cf2e4f3b3d 100644 --- a/toolkit/smart-contracts/plutus-data/src/d_param.rs +++ b/toolkit/smart-contracts/plutus-data/src/d_param.rs @@ -15,6 +15,33 @@ pub enum DParamDatum { /// Number of registered candidates in committee. num_registered_candidates: u16, }, + /// Schema with native stake validators + V1 { + /// Number of permissioned candidates in committee. + num_permissioned_candidates: u16, + /// Number of registered candidates in committee. + num_registered_candidates: u16, + /// Number of native stake validators in committee. + num_native_stake_candidates: u16, + }, +} + +impl DParamDatum { + fn decode_v1_appendix(data: &PlutusData) -> Result { + let d_parameter = data + .as_list() + .filter(|datum| datum.len() == 3) + .and_then(|items| { + Some(DParamDatum::V1 { + num_permissioned_candidates: items.get(0).as_u16()?, + num_registered_candidates: items.get(1).as_u16()?, + num_native_stake_candidates: items.get(2).as_u16()?, + }) + }) + .ok_or("Expected [u16, u16, u16]")?; + + Ok(d_parameter) + } } impl TryFrom for DParamDatum { @@ -27,8 +54,19 @@ impl TryFrom for DParamDatum { impl From for sidechain_domain::DParameter { fn from(datum: DParamDatum) -> Self { match datum { - DParamDatum::V0 { num_permissioned_candidates, num_registered_candidates } => { - Self { num_permissioned_candidates, num_registered_candidates } + DParamDatum::V0 { num_permissioned_candidates, num_registered_candidates } => Self { + num_permissioned_candidates, + num_registered_candidates, + num_native_stake_candidates: 0, + }, + DParamDatum::V1 { + num_permissioned_candidates, + num_registered_candidates, + num_native_stake_candidates, + } => Self { + num_permissioned_candidates, + num_registered_candidates, + num_native_stake_candidates, }, } } @@ -48,15 +86,32 @@ pub fn d_parameter_to_plutus_data(d_param: &sidechain_domain::DParameter) -> Plu let mut list = PlutusList::new(); list.add(&PlutusData::new_integer(&d_param.num_permissioned_candidates.into())); list.add(&PlutusData::new_integer(&d_param.num_registered_candidates.into())); + list.add(&PlutusData::new_integer(&d_param.num_native_stake_candidates.into())); let appendix = PlutusData::new_list(&list); VersionedGenericDatum { datum: PlutusData::new_empty_constr_plutus_data(&0u64.into()), appendix, - version: 0, + version: 1, } .into() } +/// Decodes V1 appendix of D-param. +pub fn decode_v1_appendix(data: &PlutusData) -> Result { + let d_parameter = data + .as_list() + .filter(|datum| datum.len() == 3) + .and_then(|items| { + Some(DParamDatum::V1 { + num_permissioned_candidates: items.get(0).as_u16()?, + num_registered_candidates: items.get(1).as_u16()?, + num_native_stake_candidates: items.get(2).as_u16()?, + }) + }) + .ok_or("Expected [u16, u16, u16]")?; + Ok(d_parameter) +} + impl VersionedDatumWithLegacy for DParamDatum { const NAME: &str = "DParamDatum"; @@ -83,6 +138,8 @@ impl VersionedDatumWithLegacy for DParamDatum { match version { 0 => DParamDatum::decode_legacy(appendix) .map_err(|msg| format!("Cannot parse appendix: {msg}")), + 1 => DParamDatum::decode_v1_appendix(appendix) + .map_err(|msg| format!("Cannot parse appendix: {msg}")), _ => Err(format!("Unknown version: {version}")), } } @@ -109,9 +166,10 @@ mod tests { let d_param = sidechain_domain::DParameter { num_permissioned_candidates: 17, num_registered_candidates: 42, + num_native_stake_candidates: 23, }; - let expected_plutus_data = json_to_plutus_data(v0_datum_json()); + let expected_plutus_data = json_to_plutus_data(v1_datum_json()); assert_eq!(d_parameter_to_plutus_data(&d_param), expected_plutus_data) } @@ -122,13 +180,27 @@ mod tests { { "constructor": 0, "fields": [] }, { "list": [ { "int": 17 }, - { "int": 42 } + { "int": 42 }, ] }, { "int": 0 } ] }) } + fn v1_datum_json() -> serde_json::Value { + serde_json::json!({ + "list": [ + { "constructor": 0, "fields": [] }, + { "list": [ + { "int": 17 }, + { "int": 42 }, + { "int": 23 }, + ] }, + { "int": 1 } + ] + }) + } + #[test] fn valid_v0_d_param() { let plutus_data = json_to_plutus_data(v0_datum_json()); @@ -138,4 +210,17 @@ mod tests { assert_eq!(DParamDatum::try_from(plutus_data).unwrap(), expected_datum) } + + #[test] + fn valid_v1_d_param() { + let plutus_data = json_to_plutus_data(v1_datum_json()); + + let expected_datum = DParamDatum::V1 { + num_permissioned_candidates: 17, + num_registered_candidates: 42, + num_native_stake_candidates: 13, + }; + + assert_eq!(DParamDatum::try_from(plutus_data).unwrap(), expected_datum) + } }