diff --git a/toolkit/cli/smart-contracts-commands/src/register.rs b/toolkit/cli/smart-contracts-commands/src/register.rs index 7c77e0c75..71bc8ce19 100644 --- a/toolkit/cli/smart-contracts-commands/src/register.rs +++ b/toolkit/cli/smart-contracts-commands/src/register.rs @@ -26,9 +26,9 @@ pub struct RegisterCmd { alias = "sidechain-public-keys", value_parser = parse_partnerchain_public_keys )] - partnerchain_public_keys: PermissionedCandidateData, + partner_chain_public_keys: PermissionedCandidateData, #[arg(long, alias = "sidechain-signature")] - partnerchain_signature: SidechainSignature, + partner_chain_signature: SidechainSignature, #[arg(long)] spo_public_key: MainchainPublicKey, #[arg(long)] @@ -44,12 +44,12 @@ impl RegisterCmd { pub_key: self.spo_public_key, signature: self.spo_signature, }, - partnerchain_pub_key: self.partnerchain_public_keys.sidechain_public_key, - partnerchain_signature: self.partnerchain_signature, + partner_chain_pub_key: self.partner_chain_public_keys.sidechain_public_key, + partner_chain_signature: self.partner_chain_signature, own_pkh: payment_key.to_pub_key_hash(), registration_utxo: self.registration_utxo, - aura_pub_key: self.partnerchain_public_keys.aura_public_key, - grandpa_pub_key: self.partnerchain_public_keys.grandpa_public_key, + aura_pub_key: self.partner_chain_public_keys.aura_public_key, + grandpa_pub_key: self.partner_chain_public_keys.grandpa_public_key, }; run_register( diff --git a/toolkit/offchain/src/register.rs b/toolkit/offchain/src/register.rs index 20d1e68b7..c078a0c68 100644 --- a/toolkit/offchain/src/register.rs +++ b/toolkit/offchain/src/register.rs @@ -359,8 +359,8 @@ mod tests { pub_key: test_values::mainchain_pub_key(), signature: MainchainSignature(Vec::new()), }, - partnerchain_pub_key: SidechainPublicKey(Vec::new()), - partnerchain_signature: SidechainSignature(Vec::new()), + partner_chain_pub_key: SidechainPublicKey(Vec::new()), + partner_chain_signature: SidechainSignature(Vec::new()), registration_utxo, own_pkh: own_pkh(), aura_pub_key: AuraPublicKey(Vec::new()), diff --git a/toolkit/offchain/tests/integration_tests.rs b/toolkit/offchain/tests/integration_tests.rs index 73abed7ef..a9f9bdd9a 100644 --- a/toolkit/offchain/tests/integration_tests.rs +++ b/toolkit/offchain/tests/integration_tests.rs @@ -12,7 +12,6 @@ use ogmios_client::{ query_ledger_state::{QueryLedgerState, QueryUtxoByUtxoId}, query_network::QueryNetwork, transactions::Transactions, - types::OgmiosTx, OgmiosClientError, }; use partner_chains_cardano_offchain::{ @@ -194,8 +193,8 @@ async fn run_register anyhow::Result; fn print(&self, msg: &str); diff --git a/toolkit/partner-chains-cli/src/register/register2.rs b/toolkit/partner-chains-cli/src/register/register2.rs index 4d475df3d..bcd891ddf 100644 --- a/toolkit/partner-chains-cli/src/register/register2.rs +++ b/toolkit/partner-chains-cli/src/register/register2.rs @@ -53,7 +53,7 @@ impl CmdRun for Register2Cmd { context.print("To finish the registration process, run the following command on the machine with the partner chain dependencies running:\n"); context.print(&format!( - "./partner-chains-cli register3 \\\n--genesis-utxo {} \\\n--registration-utxo {} \\\n--aura-pub-key {} \\\n--grandpa-pub-key {} \\\n--sidechain-pub-key {} \\\n--sidechain-signature {} \\\n--spo-public-key {} \\\n--spo-signature {}", + "./partner-chains-cli register3 \\\n--genesis-utxo {} \\\n--registration-utxo {} \\\n--aura-pub-key {} \\\n--grandpa-pub-key {} \\\n--partner-chain-pub-key {} \\\n--partner-chain-signature {} \\\n--spo-public-key {} \\\n--spo-signature {}", self.genesis_utxo, self.registration_utxo, self.aura_pub_key, self.grandpa_pub_key, self.sidechain_pub_key, self.sidechain_signature, spo_public_key, spo_signature)); Ok(()) } @@ -124,7 +124,7 @@ mod tests { fn output_result_io() -> Vec { vec![ MockIO::print("To finish the registration process, run the following command on the machine with the partner chain dependencies running:\n"), - MockIO::print("./partner-chains-cli register3 \\\n--genesis-utxo 0000000000000000000000000000000000000000000000000000000000000001#0 \\\n--registration-utxo 7e9ebd0950ae1bec5606f0cd7ac88b3c60b1103d7feb6ffa36402edae4d1b617#0 \\\n--aura-pub-key 0xdf883ee0648f33b6103017b61be702017742d501b8fe73b1d69ca0157460b777 \\\n--grandpa-pub-key 0x5a091a06abd64f245db11d2987b03218c6bd83d64c262fe10e3a2a1230e90327 \\\n--sidechain-pub-key 0x031e75acbf45ef8df98bbe24b19b28fff807be32bf88838c30c0564d7bec5301f6 \\\n--sidechain-signature 7a7e3e585a5dc248d4a2772814e1b58c90313443dd99369f994e960ecc4931442a08305743db7ab42ab9b8672e00250e1cc7c08bc018b0630a8197c4f95528a301 \\\n--spo-public-key cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7 \\\n--spo-signature aaa39fbf163ed77c69820536f5dc22854e7e13f964f1e077efde0844a09bde64c1aab4d2b401e0fe39b43c91aa931cad26fa55c8766378462c06d86c85134801"), + MockIO::print("./partner-chains-cli register3 \\\n--genesis-utxo 0000000000000000000000000000000000000000000000000000000000000001#0 \\\n--registration-utxo 7e9ebd0950ae1bec5606f0cd7ac88b3c60b1103d7feb6ffa36402edae4d1b617#0 \\\n--aura-pub-key 0xdf883ee0648f33b6103017b61be702017742d501b8fe73b1d69ca0157460b777 \\\n--grandpa-pub-key 0x5a091a06abd64f245db11d2987b03218c6bd83d64c262fe10e3a2a1230e90327 \\\n--partner-chain-pub-key 0x031e75acbf45ef8df98bbe24b19b28fff807be32bf88838c30c0564d7bec5301f6 \\\n--partner-chain-signature 7a7e3e585a5dc248d4a2772814e1b58c90313443dd99369f994e960ecc4931442a08305743db7ab42ab9b8672e00250e1cc7c08bc018b0630a8197c4f95528a301 \\\n--spo-public-key cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7 \\\n--spo-signature aaa39fbf163ed77c69820536f5dc22854e7e13f964f1e077efde0844a09bde64c1aab4d2b401e0fe39b43c91aa931cad26fa55c8766378462c06d86c85134801"), ] } // non 0 genesis utxo 8ea10040249ad3033ae7c4d4b69e0b2e2b50a90741b783491cb5ddf8ced0d861 diff --git a/toolkit/partner-chains-cli/src/register/register3.rs b/toolkit/partner-chains-cli/src/register/register3.rs index bcd57ba07..d57e316ba 100644 --- a/toolkit/partner-chains-cli/src/register/register3.rs +++ b/toolkit/partner-chains-cli/src/register/register3.rs @@ -1,18 +1,15 @@ +use crate::cardano_key::get_mc_pkey_from_file; use crate::config; use crate::config::config_fields; -use crate::config::get_cardano_network_from_file; use crate::config::CHAIN_CONFIG_FILE_PATH; -use crate::config::PC_CONTRACTS_CLI_PATH; use crate::io::IOContext; use crate::main_chain_follower::set_main_chain_follower_env; use crate::pc_contracts_cli_resources::establish_pc_contracts_cli_configuration; -use crate::smart_contracts; use crate::CmdRun; -use anyhow::Context; use clap::Parser; -use cli_commands::key_params::{PlainPublicKeyParam, SidechainPublicKeyParam}; +use partner_chains_cardano_offchain::register::Register; use sidechain_domain::mainchain_epoch::{MainchainEpochConfig, MainchainEpochDerivation}; -use sidechain_domain::{McEpochNumber, UtxoId}; +use sidechain_domain::*; #[derive(Clone, Debug, Parser)] #[command(author, version, about, long_about = None)] @@ -22,17 +19,17 @@ pub struct Register3Cmd { #[arg(long)] pub registration_utxo: UtxoId, #[arg(long)] - pub sidechain_pub_key: SidechainPublicKeyParam, + pub partner_chain_pub_key: SidechainPublicKey, #[arg(long)] - pub aura_pub_key: PlainPublicKeyParam, + pub aura_pub_key: AuraPublicKey, #[arg(long)] - pub grandpa_pub_key: PlainPublicKeyParam, + pub grandpa_pub_key: GrandpaPublicKey, #[arg(long)] - pub sidechain_signature: String, + pub partner_chain_signature: SidechainSignature, #[arg(long)] - pub spo_public_key: String, + pub spo_public_key: MainchainPublicKey, #[arg(long)] - pub spo_signature: String, + pub spo_signature: MainchainSignature, } impl CmdRun for Register3Cmd { @@ -52,33 +49,32 @@ impl CmdRun for Register3Cmd { let cardano_payment_signing_key_path = context.prompt("Path to mainchain payment signing key file", Some("payment.skey")); - let sidechain_param_arg = smart_contracts::sidechain_params_arguments(self.genesis_utxo); - let pc_contracts_cli_resources = establish_pc_contracts_cli_configuration(context)?; - let runtime_config_arguments = smart_contracts::runtime_config_arguments( - &pc_contracts_cli_resources, - &cardano_payment_signing_key_path, - ); - - let cardano_network = get_cardano_network_from_file(context)?; - - let command = format!( - "{PC_CONTRACTS_CLI_PATH} register --network {} {} --registration-utxo {} --sidechain-public-keys {}:{}:{} --sidechain-signature {} --spo-public-key {} --spo-signature {} --ada-based-staking {}", - cardano_network, - sidechain_param_arg, - self.registration_utxo, - self.sidechain_pub_key, - self.aura_pub_key, - self.grandpa_pub_key, - self.sidechain_signature, - self.spo_public_key, - self.spo_signature, - runtime_config_arguments - ); + let payment_signing_key = + get_mc_pkey_from_file(&cardano_payment_signing_key_path, context)?; - context - .run_command(&command) - .context("The registration transaction could not be submitted")?; + let candidate_registration = CandidateRegistration { + stake_ownership: AdaBasedStaking { + pub_key: self.spo_public_key.clone(), + signature: self.spo_signature.clone(), + }, + partner_chain_pub_key: self.partner_chain_pub_key.clone(), + partner_chain_signature: self.partner_chain_signature.clone(), + own_pkh: payment_signing_key.to_pub_key_hash(), + registration_utxo: self.registration_utxo, + aura_pub_key: self.aura_pub_key.clone(), + grandpa_pub_key: self.grandpa_pub_key.clone(), + }; + let offchain = context.offchain_impl(&pc_contracts_cli_resources.ogmios)?; + + let runtime = tokio::runtime::Runtime::new().map_err(|e| anyhow::anyhow!(e))?; + runtime + .block_on(offchain.register( + self.genesis_utxo, + &candidate_registration, + payment_signing_key, + )) + .map_err(|e| anyhow::anyhow!("Candidate registration failed: {e:?}!"))?; if context.prompt_yes_no("Show registration status?", true) { context.print("The registration status will be queried from a db-sync instance for which a valid connection string is required. Please note that this db-sync instance needs to be up and synced with the main chain."); @@ -111,7 +107,7 @@ fn prepare_mc_follower_env(context: &C) -> anyhow::Result<()> { fn show_registration_status( context: &impl IOContext, mc_epoch_number: McEpochNumber, - mc_public_key: String, + mc_public_key: MainchainPublicKey, ) -> Result<(), anyhow::Error> { let temp_dir = context.new_tmp_dir(); let temp_dir_path = temp_dir @@ -123,7 +119,7 @@ fn show_registration_status( .ok_or_else(|| anyhow::anyhow!("⚠️ Unable to load node executable"))?; let command = format!( "{} registration-status --mainchain-pub-key {} --mc-epoch-number {} --chain chain-spec.json --base-path {temp_dir_path}", - node_executable, mc_public_key, mc_epoch_number + node_executable, mc_public_key.to_hex_string(), mc_epoch_number ); let output = context.run_command(&command)?; context.print("Registration status:"); @@ -137,9 +133,11 @@ struct McEpochConfigJson { } fn get_current_mainchain_epoch(context: &impl IOContext) -> Result { - let chain_config_json = context - .read_file(config::CHAIN_CONFIG_FILE_PATH) - .ok_or_else(|| anyhow::anyhow!("⚠️ The chain configuration file `partner-chains-cli-chain-config.json` is missing or invalid."))?; + let chain_config_json = context.read_file(config::CHAIN_CONFIG_FILE_PATH).ok_or_else(|| { + anyhow::anyhow!( + "⚠️ The chain configuration file `{CHAIN_CONFIG_FILE_PATH}` is missing or invalid." + ) + })?; let mc_epoch_config = serde_json::from_str::(&chain_config_json)?; mc_epoch_config @@ -159,17 +157,30 @@ mod tests { pc_contracts_cli_resources::{ tests::establish_pc_contracts_cli_configuration_io, PcContractsCliResources, }, - tests::{MockIO, MockIOContext}, + tests::{MockIO, MockIOContext, OffchainMock, OffchainMocks}, }; + use hex_literal::hex; + use partner_chains_cardano_offchain::OffchainError; use serde_json::json; use sp_core::offchain::Timestamp; #[test] fn happy_path() { + let offchain_mock = OffchainMock::new().with_register( + genesis_utxo(), + new_candidate_registration(), + payment_signing_key(), + Ok(Some(McTxHash::default())), + ); + let mock_context = MockIOContext::new() .with_json_file("/path/to/payment.skey", payment_skey_content()) .with_json_file(CHAIN_CONFIG_FILE_PATH, chain_config_content()) .with_json_file(RESOURCES_CONFIG_FILE_PATH, resource_config_content()) + .with_offchain_mocks(OffchainMocks::new_with_mock( + "http://localhost:1337", + offchain_mock, + )) .with_expected_io( vec![ intro_msg_io(), @@ -178,7 +189,7 @@ mod tests { None, PcContractsCliResources::default(), )], - run_registration_command_io(), + vec![MockIO::file_read("/path/to/payment.skey")], prompt_for_registration_status_y(), show_registration_status_io(), ] @@ -193,10 +204,20 @@ mod tests { #[test] fn registration_call_fails() { + let offchain_mock = OffchainMock::new().with_register( + genesis_utxo(), + new_candidate_registration(), + payment_signing_key(), + Err(OffchainError::InternalError("".to_string())), + ); let mock_context = MockIOContext::new() .with_json_file("/path/to/payment.skey", payment_skey_content()) .with_json_file(CHAIN_CONFIG_FILE_PATH, chain_config_content()) .with_json_file(RESOURCES_CONFIG_FILE_PATH, resource_config_content()) + .with_offchain_mocks(OffchainMocks::new_with_mock( + "http://localhost:1337", + offchain_mock, + )) .with_expected_io( vec![ intro_msg_io(), @@ -205,7 +226,8 @@ mod tests { None, PcContractsCliResources::default(), )], - run_registration_command_fail_io(), + vec![MockIO::file_read("/path/to/payment.skey")], + // run_registration_command_fail_io(), ] .into_iter() .flatten() @@ -218,10 +240,20 @@ mod tests { #[test] fn not_show_registration_status() { + let offchain_mock = OffchainMock::new().with_register( + genesis_utxo(), + new_candidate_registration(), + payment_signing_key(), + Ok(Some(McTxHash::default())), + ); let mock_context = MockIOContext::new() .with_json_file("/path/to/payment.skey", payment_skey_content()) .with_json_file(CHAIN_CONFIG_FILE_PATH, chain_config_content()) .with_json_file(RESOURCES_CONFIG_FILE_PATH, resource_config_content()) + .with_offchain_mocks(OffchainMocks::new_with_mock( + "http://localhost:1337", + offchain_mock, + )) .with_expected_io( vec![ intro_msg_io(), @@ -230,7 +262,7 @@ mod tests { None, PcContractsCliResources::default(), )], - run_registration_command_io(), + vec![MockIO::file_read("/path/to/payment.skey")], prompt_for_registration_status_n(), ] .into_iter() @@ -289,41 +321,31 @@ mod tests { MockIO::print("Registrations status for epoch 25:"), MockIO::new_tmp_dir(), MockIO::file_read(RESOURCES_CONFIG_FILE_PATH), - MockIO::run_command("/path/to/node registration-status --mainchain-pub-key cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7 --mc-epoch-number 25 --chain chain-spec.json --base-path /tmp/MockIOContext_tmp_dir", "{\"epoch\":1,\"validators\":[{\"public_key\":\"cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7\",\"status\":\"Registered\"}]}"), + MockIO::run_command("/path/to/node registration-status --mainchain-pub-key 0xcef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7 --mc-epoch-number 25 --chain chain-spec.json --base-path /tmp/MockIOContext_tmp_dir", "{\"epoch\":1,\"validators\":[{\"public_key\":\"cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7\",\"status\":\"Registered\"}]}"), MockIO::print("Registration status:"), MockIO::print("{\"epoch\":1,\"validators\":[{\"public_key\":\"cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7\",\"status\":\"Registered\"}]}"), ] } - fn run_registration_command_io() -> Vec { - vec![ - MockIO::file_read(CHAIN_CONFIG_FILE_PATH), - MockIO::run_command("./pc-contracts-cli register --network mainnet --genesis-utxo f17e6d3aa72095e04489d13d776bf05a66b5a8c49d89397c28b18a1784b9950e#0 --registration-utxo cdefe62b0a0016c2ccf8124d7dda71f6865283667850cc7b471f761d2bc1eb13#0 --sidechain-public-keys 0x020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1:79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf:1a55db596380bc63f5ee964565359b5ea8e0096c798c3281692df097abbd9aa4b657f887915ad2a52fc85c674ef4044baeaf7149546af93a2744c379b9798f07 --sidechain-signature cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854 --spo-public-key cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7 --spo-signature aaa39fbf163ed77c69820536f5dc22854e7e13f964f1e077efde0844a09bde64c1aab4d2b401e0fe39b43c91aa931cad26fa55c8766378462c06d86c85134801 --ada-based-staking --kupo-host localhost --kupo-port 1442 --ogmios-host localhost --ogmios-port 1337 --payment-signing-key-file /path/to/payment.skey", "{\"endpoint\":\"CommitteeCandidateReg\",\"transactionId\":\"1ab93b52d20ce114bfdb48a256ac48f3d8d46d00aec585c38a904b672a70e3a3\"}"), - ] - } - - fn run_registration_command_fail_io() -> Vec { - vec![ - MockIO::file_read(CHAIN_CONFIG_FILE_PATH), - MockIO::run_command_with_result( - "./pc-contracts-cli register --network mainnet --genesis-utxo f17e6d3aa72095e04489d13d776bf05a66b5a8c49d89397c28b18a1784b9950e#0 --registration-utxo cdefe62b0a0016c2ccf8124d7dda71f6865283667850cc7b471f761d2bc1eb13#0 --sidechain-public-keys 0x020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1:79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf:1a55db596380bc63f5ee964565359b5ea8e0096c798c3281692df097abbd9aa4b657f887915ad2a52fc85c674ef4044baeaf7149546af93a2744c379b9798f07 --sidechain-signature cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854 --spo-public-key cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7 --spo-signature aaa39fbf163ed77c69820536f5dc22854e7e13f964f1e077efde0844a09bde64c1aab4d2b401e0fe39b43c91aa931cad26fa55c8766378462c06d86c85134801 --ada-based-staking --kupo-host localhost --kupo-port 1442 --ogmios-host localhost --ogmios-port 1337 --payment-signing-key-file /path/to/payment.skey", - Err(anyhow::anyhow!("TxRefNotFound"))), - ] - } - fn mock_register3_cmd() -> Register3Cmd { Register3Cmd { - genesis_utxo: "f17e6d3aa72095e04489d13d776bf05a66b5a8c49d89397c28b18a1784b9950e#0".parse().unwrap(), + genesis_utxo: genesis_utxo(), registration_utxo: "cdefe62b0a0016c2ccf8124d7dda71f6865283667850cc7b471f761d2bc1eb13#0".parse().unwrap(), - sidechain_pub_key: "020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1".parse().unwrap(), + partner_chain_pub_key: "020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1".parse().unwrap(), aura_pub_key: "79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf".parse().unwrap(), grandpa_pub_key: "1a55db596380bc63f5ee964565359b5ea8e0096c798c3281692df097abbd9aa4b657f887915ad2a52fc85c674ef4044baeaf7149546af93a2744c379b9798f07".parse().unwrap(), - sidechain_signature: "cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854".to_string(), - spo_public_key: "cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7".to_string(), - spo_signature: "aaa39fbf163ed77c69820536f5dc22854e7e13f964f1e077efde0844a09bde64c1aab4d2b401e0fe39b43c91aa931cad26fa55c8766378462c06d86c85134801".to_string(), + partner_chain_signature: SidechainSignature(hex_literal::hex!("cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854").to_vec()), + spo_public_key: MainchainPublicKey(hex_literal::hex!("cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7")), + spo_signature: MainchainSignature(hex_literal::hex!("aaa39fbf163ed77c69820536f5dc22854e7e13f964f1e077efde0844a09bde64c1aab4d2b401e0fe39b43c91aa931cad26fa55c8766378462c06d86c85134801").to_vec()), } } + fn genesis_utxo() -> UtxoId { + "f17e6d3aa72095e04489d13d776bf05a66b5a8c49d89397c28b18a1784b9950e#0" + .parse() + .unwrap() + } + fn payment_skey_content() -> serde_json::Value { serde_json::json!({ "type": "PaymentSigningKeyShelley_ed25519", @@ -332,6 +354,12 @@ mod tests { }) } + fn payment_signing_key() -> MainchainPrivateKey { + MainchainPrivateKey(hex!( + "d75c630516c33a66b11b3444a70b65083aeb21353bd919cc5e3daa02c9732a84" + )) + } + fn chain_config_content() -> serde_json::Value { json!({ "chain_parameters": chain_parameters_json(), @@ -360,12 +388,12 @@ mod tests { { "aura_pub_key": "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d", "grandpa_pub_key": "0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee", - "sidechain_pub_key": "0x020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1" + "partner_chain_pub_key": "0x020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1" }, { "aura_pub_key": "0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", "grandpa_pub_key": "0xd17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae69", - "sidechain_pub_key": "0x0390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27" + "partner_chain_pub_key": "0x0390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27" } ], }) @@ -388,4 +416,19 @@ mod tests { fn mock_timestamp() -> Timestamp { Timestamp::from_unix_millis(1668658000000u64) } + + fn new_candidate_registration() -> CandidateRegistration { + CandidateRegistration { + stake_ownership: AdaBasedStaking { + pub_key: MainchainPublicKey(hex!("cef2d1630c034d3b9034eb7903d61f419a3074a1ad01d4550cc72f2b733de6e7")), + signature: MainchainSignature(hex!("aaa39fbf163ed77c69820536f5dc22854e7e13f964f1e077efde0844a09bde64c1aab4d2b401e0fe39b43c91aa931cad26fa55c8766378462c06d86c85134801").to_vec()) + }, + partner_chain_pub_key: SidechainPublicKey(hex!("020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1").to_vec()), + partner_chain_signature: SidechainSignature(hex!("cb6df9de1efca7a3998a8ead4e02159d5fa99c3e0d4fd6432667390bb4726854").to_vec()), + own_pkh: MainchainAddressHash(hex!("7fa48bb8fb5d6804fad26237738ce490d849e4567161e38ab8415ff3")), + registration_utxo: UtxoId { tx_hash: McTxHash(hex!("cdefe62b0a0016c2ccf8124d7dda71f6865283667850cc7b471f761d2bc1eb13")), index: UtxoIndex(0) }, + aura_pub_key: AuraPublicKey(hex!("79c3b7fc0b7697b9414cb87adcb37317d1cab32818ae18c0e97ad76395d1fdcf").to_vec()), + grandpa_pub_key: GrandpaPublicKey(hex!("1a55db596380bc63f5ee964565359b5ea8e0096c798c3281692df097abbd9aa4b657f887915ad2a52fc85c674ef4044baeaf7149546af93a2744c379b9798f07").to_vec()) + } + } } diff --git a/toolkit/partner-chains-cli/src/tests/mod.rs b/toolkit/partner-chains-cli/src/tests/mod.rs index 10e6ddf3a..ad6ea82da 100644 --- a/toolkit/partner-chains-cli/src/tests/mod.rs +++ b/toolkit/partner-chains-cli/src/tests/mod.rs @@ -4,10 +4,13 @@ use anyhow::anyhow; use ogmios_client::types::OgmiosTx; use partner_chains_cardano_offchain::d_param::UpsertDParam; use partner_chains_cardano_offchain::init_governance::InitGovernance; +use partner_chains_cardano_offchain::register::Register; use partner_chains_cardano_offchain::scripts_data::{GetScriptsData, ScriptsData}; use partner_chains_cardano_offchain::OffchainError; use pretty_assertions::assert_eq; -use sidechain_domain::{DParameter, MainchainAddressHash, MainchainPrivateKey, McTxHash, UtxoId}; +use sidechain_domain::{ + CandidateRegistration, DParameter, MainchainAddressHash, MainchainPrivateKey, McTxHash, UtxoId, +}; use sp_core::offchain::Timestamp; use std::collections::HashMap; use std::panic::{catch_unwind, resume_unwind, UnwindSafe}; @@ -256,6 +259,10 @@ pub struct OffchainMock { Result, >, pub upsert_d_param: HashMap<(UtxoId, DParameter, [u8; 32]), Result, String>>, + pub register: HashMap< + (UtxoId, CandidateRegistration, MainchainPrivateKey), + Result, OffchainError>, + >, } impl OffchainMock { @@ -295,6 +302,19 @@ impl OffchainMock { ) -> Self { Self { upsert_d_param: [((genesis_utxo, d_param, payment_key.0), result)].into(), ..self } } + + pub(crate) fn with_register( + self, + genesis_utxo: UtxoId, + candidate_registration: CandidateRegistration, + payment_key: MainchainPrivateKey, + result: Result, OffchainError>, + ) -> Self { + Self { + register: [((genesis_utxo, candidate_registration, payment_key), result)].into(), + ..self + } + } } impl GetScriptsData for OffchainMock { @@ -338,6 +358,22 @@ impl UpsertDParam for OffchainMock { } } +impl Register for OffchainMock { + async fn register( + &self, + genesis_utxo: UtxoId, + candidate_registration: &CandidateRegistration, + payment_signing_key: MainchainPrivateKey, + ) -> Result, OffchainError> { + self.register + .get(&(genesis_utxo, candidate_registration.clone(), payment_signing_key.clone())) + .cloned() + .unwrap_or_else(|| { + Err(OffchainError::InternalError(format!("No mock for register({genesis_utxo}, {candidate_registration:?}, {payment_signing_key:?})"))) + }) + } +} + impl Drop for MockIOContext { fn drop(&mut self) { if std::thread::panicking() { diff --git a/toolkit/primitives/domain/src/lib.rs b/toolkit/primitives/domain/src/lib.rs index 2b5c7a197..671ca6148 100644 --- a/toolkit/primitives/domain/src/lib.rs +++ b/toolkit/primitives/domain/src/lib.rs @@ -201,6 +201,7 @@ pub struct AssetName(pub BoundedVec>); const MAINCHAIN_PUBLIC_KEY_LEN: usize = 32; #[derive(Clone, PartialEq, Eq, Encode, Decode, ToDatum, TypeInfo, MaxEncodedLen, Hash)] +#[cfg_attr(feature = "std", byte_string(to_hex_string))] #[byte_string(debug, hex_serialize, hex_deserialize, decode_hex)] pub struct MainchainPublicKey(pub [u8; MAINCHAIN_PUBLIC_KEY_LEN]); @@ -266,7 +267,7 @@ impl MainchainAddressHash { } } -#[derive(Clone, Encode, Decode, TypeInfo, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, TypeInfo, PartialEq, Eq, Hash)] #[byte_string(debug, hex_serialize, decode_hex)] pub struct MainchainSignature(pub Vec); @@ -309,11 +310,11 @@ impl ScEpochNumber { } } -#[derive(Clone, PartialEq, Eq, Encode, Decode, ToDatum, TypeInfo, PartialOrd, Ord)] -#[byte_string(debug, hex_serialize, hex_deserialize, as_ref)] +#[derive(Clone, PartialEq, Eq, Encode, Decode, ToDatum, TypeInfo, PartialOrd, Ord, Hash)] +#[byte_string(debug, hex_serialize, hex_deserialize, decode_hex, as_ref)] pub struct SidechainPublicKey(pub Vec); -#[derive(Clone, Encode, Decode, TypeInfo, PartialEq, Eq)] +#[derive(Clone, Encode, Decode, TypeInfo, PartialEq, Eq, Hash)] #[byte_string(debug, hex_serialize, hex_deserialize, decode_hex)] pub struct SidechainSignature(pub Vec); @@ -601,8 +602,8 @@ impl SidechainPublicKeysSorted { } } -#[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, PartialOrd, Ord)] -#[byte_string(debug, hex_serialize, hex_deserialize)] +#[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, PartialOrd, Ord, Hash)] +#[byte_string(debug, hex_serialize, hex_deserialize, decode_hex)] pub struct AuraPublicKey(pub Vec); impl AuraPublicKey { pub fn try_into_sr25519(&self) -> Option { @@ -610,8 +611,8 @@ impl AuraPublicKey { } } -#[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, PartialOrd, Ord)] -#[byte_string(debug, hex_serialize, hex_deserialize)] +#[derive(Clone, PartialEq, Eq, Encode, Decode, TypeInfo, PartialOrd, Ord, Hash)] +#[byte_string(debug, hex_serialize, hex_deserialize, decode_hex)] pub struct GrandpaPublicKey(pub Vec); impl GrandpaPublicKey { pub fn try_into_ed25519(&self) -> Option { @@ -639,11 +640,11 @@ pub struct PermissionedCandidateData { pub grandpa_public_key: GrandpaPublicKey, } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct CandidateRegistration { pub stake_ownership: AdaBasedStaking, - pub partnerchain_pub_key: SidechainPublicKey, - pub partnerchain_signature: SidechainSignature, + pub partner_chain_pub_key: SidechainPublicKey, + pub partner_chain_signature: SidechainSignature, pub own_pkh: MainchainAddressHash, pub registration_utxo: UtxoId, pub aura_pub_key: AuraPublicKey, @@ -653,8 +654,8 @@ pub struct CandidateRegistration { impl CandidateRegistration { pub fn matches_keys(&self, other: &Self) -> bool { self.stake_ownership == other.stake_ownership - && self.partnerchain_pub_key == other.partnerchain_pub_key - && self.partnerchain_signature == other.partnerchain_signature + && self.partner_chain_pub_key == other.partner_chain_pub_key + && self.partner_chain_signature == other.partner_chain_signature && self.aura_pub_key == other.aura_pub_key && self.grandpa_pub_key == other.grandpa_pub_key } @@ -662,7 +663,7 @@ impl CandidateRegistration { /// AdaBasedStaking is a variant of Plutus type StakeOwnership. /// The other variant, TokenBasedStaking, is not supported -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct AdaBasedStaking { pub pub_key: MainchainPublicKey, pub signature: MainchainSignature, diff --git a/toolkit/primitives/plutus-data/src/registered_candidates.rs b/toolkit/primitives/plutus-data/src/registered_candidates.rs index e5efacc79..7f888ba43 100644 --- a/toolkit/primitives/plutus-data/src/registered_candidates.rs +++ b/toolkit/primitives/plutus-data/src/registered_candidates.rs @@ -80,8 +80,8 @@ pub fn candidate_registration_to_plutus_data( ) -> PlutusData { RegisterValidatorDatum::V0 { stake_ownership: candidate_registration.stake_ownership.clone(), - sidechain_pub_key: candidate_registration.partnerchain_pub_key.clone(), - sidechain_signature: candidate_registration.partnerchain_signature.clone(), + sidechain_pub_key: candidate_registration.partner_chain_pub_key.clone(), + sidechain_signature: candidate_registration.partner_chain_signature.clone(), registration_utxo: candidate_registration.registration_utxo, own_pkh: candidate_registration.own_pkh, aura_pub_key: candidate_registration.aura_pub_key.clone(), @@ -103,8 +103,8 @@ impl From for CandidateRegistration { grandpa_pub_key, } => CandidateRegistration { stake_ownership, - partnerchain_pub_key: sidechain_pub_key, - partnerchain_signature: sidechain_signature, + partner_chain_pub_key: sidechain_pub_key, + partner_chain_signature: sidechain_signature, registration_utxo, own_pkh, aura_pub_key,