Skip to content

Commit

Permalink
fix: ETCM-8267 Configure and use the native token addresses in partne…
Browse files Browse the repository at this point in the history
…r-chains-cli (#68)
  • Loading branch information
AmbientTea authored Sep 25, 2024
1 parent 66fc147 commit 12d2aa3
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 9 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ This changelog is based on [Keep A Changelog](https://keepachangelog.com/en/1.1.
## Removed

## Fixed
* ETCM-8267 - fixed `partner-chains-cli` missing the native token configuration

## Added
* ETCM-7811 - native token movement observability components: `sp-native-token-management` and
Expand Down
39 changes: 39 additions & 0 deletions partner-chains-cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ pub struct MainChainAddresses {
pub committee_candidates_address: String,
pub d_parameter_policy_id: String,
pub permissioned_candidates_policy_id: String,
pub native_token: NativeTokenConfig,
}
#[derive(Deserialize, PartialEq, Clone, Debug)]
pub struct CardanoParameters {
Expand Down Expand Up @@ -376,6 +377,18 @@ pub struct SidechainParams {
pub governance_authority: MainchainAddressHash,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct AssetConfig {
policy_id: String,
asset_name: String,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct NativeTokenConfig {
pub asset: AssetConfig,
pub illiquid_supply_address: String,
}

#[derive(Deserialize)]
pub struct ChainConfig {
pub cardano: CardanoParameters,
Expand Down Expand Up @@ -408,6 +421,32 @@ pub mod config_fields {
use super::*;
use sidechain_domain::{MainchainAddressHash, UtxoId};

pub const NATIVE_TOKEN_POLICY: ConfigFieldDefinition<'static, String> = ConfigFieldDefinition {
config_file: CHAIN_CONFIG_FILE_PATH,
path: &["cardano_addresses", "native_token", "asset", "policy_id"],
name: "native token policy ID",
default: None,
_marker: PhantomData,
};

pub const NATIVE_TOKEN_ASSET_NAME: ConfigFieldDefinition<'static, String> =
ConfigFieldDefinition {
config_file: CHAIN_CONFIG_FILE_PATH,
path: &["cardano_addresses", "native_token", "asset", "asset_name"],
name: "native token asset name in hex",
default: None,
_marker: PhantomData,
};

pub const ILLIQUID_SUPPLY_ADDRESS: ConfigFieldDefinition<'static, String> =
ConfigFieldDefinition {
config_file: CHAIN_CONFIG_FILE_PATH,
path: &["cardano_addresses", "native_token", "illiquid_supply_address"],
name: "native token illiquid token supply address",
default: None,
_marker: PhantomData,
};

pub const SUBSTRATE_NODE_DATA_BASE_PATH: ConfigFieldDefinition<'static, String> =
ConfigFieldDefinition {
config_file: RESOURCES_CONFIG_FILE_PATH,
Expand Down
13 changes: 13 additions & 0 deletions partner-chains-cli/src/create_chain_spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ impl CreateChainSpecCmd {
)
.as_str(),
);
context.print("Native Token Management Configuration (unused if empty):");
context.print(&format!("- asset name: {}", config.native_token_asset_name));
context.print(&format!("- asset policy ID: {}", config.native_token_policy));
context.print(&format!("- illiquid supply address: {}", config.illiquid_supply_address));
use colored::Colorize;
if config.initial_permissioned_candidates_raw.is_empty() {
context.print("WARNING: The list of initial permissioned candidates is empty. Generated chain spec will not allow the chain to start.".red().to_string().as_str());
Expand Down Expand Up @@ -105,6 +109,9 @@ impl CreateChainSpecCmd {
"PERMISSIONED_CANDIDATES_POLICY_ID",
&config.permissioned_candidates_policy_id.to_string(),
);
context.set_env_var("NATIVE_TOKEN_POLICY_ID", &config.native_token_policy);
context.set_env_var("NATIVE_TOKEN_ASSET_NAME", &config.native_token_asset_name);
context.set_env_var("ILLIQUID_SUPPLY_VALIDATOR_ADDRESS", &config.illiquid_supply_address);
context.run_command(
format!("{node_executable} build-spec --disable-default-bootnode > chain-spec.json")
.to_string()
Expand Down Expand Up @@ -172,6 +179,9 @@ struct CreateChainSpecConfig {
committee_candidate_address: String,
d_parameter_policy_id: String,
permissioned_candidates_policy_id: String,
native_token_policy: String,
native_token_asset_name: String,
illiquid_supply_address: String,
}

impl CreateChainSpecConfig {
Expand Down Expand Up @@ -200,6 +210,9 @@ impl CreateChainSpecConfig {
c,
&config_fields::PERMISSIONED_CANDIDATES_POLICY_ID,
)?,
native_token_policy: load_config_field(c, &config_fields::NATIVE_TOKEN_POLICY)?,
native_token_asset_name: load_config_field(c, &config_fields::NATIVE_TOKEN_ASSET_NAME)?,
illiquid_supply_address: load_config_field(c, &config_fields::ILLIQUID_SUPPLY_ADDRESS)?,
})
}
}
Expand Down
29 changes: 26 additions & 3 deletions partner-chains-cli/src/create_chain_spec/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ fn test_config_content() -> serde_json::Value {
"sidechain_pub_key": "0x0390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27"
}
],
"cardano_addresses": cardano_addresses_json()
"cardano_addresses": cardano_addresses_json(),
})
}

Expand Down Expand Up @@ -174,7 +174,7 @@ fn test_config_content_with_empty_initial_permissioned_candidates() -> serde_jso
serde_json::json!({
"chain_parameters": chain_parameters_json(),
"initial_permissioned_candidates": [],
"cardano_addresses": cardano_addresses_json()
"cardano_addresses": cardano_addresses_json(),
})
}

Expand All @@ -192,7 +192,14 @@ fn cardano_addresses_json() -> serde_json::Value {
serde_json::json!({
"committee_candidates_address": "addr_test1wz5qc7fk2pat0058w4zwvkw35ytptej3nuc3je2kgtan5dq3rt4sc",
"d_parameter_policy_id": "d0ebb61e2ba362255a7c4a253c6578884603b56fb0a68642657602d6",
"permissioned_candidates_policy_id": "58b4ba68f641d58f7f1bba07182eca9386da1e88a34d47a14638c3fe"
"permissioned_candidates_policy_id": "58b4ba68f641d58f7f1bba07182eca9386da1e88a34d47a14638c3fe",
"native_token": {
"asset": {
"policy_id": "ada83ddd029614381f00e28de0922ab0dec6983ea9dd29ae20eef9b4",
"asset_name": "5043546f6b656e44656d6f",
},
"illiquid_supply_address": "addr_test1wrhvtvx3f0g9wv9rx8kfqc60jva3e07nqujk2cspekv4mqs9rjdvz"
},
})
}

Expand All @@ -213,6 +220,10 @@ fn show_chain_parameters() -> MockIO {
MockIO::print("- committee_candidate_address: addr_test1wz5qc7fk2pat0058w4zwvkw35ytptej3nuc3je2kgtan5dq3rt4sc"),
MockIO::print("- d_parameter_policy_id: d0ebb61e2ba362255a7c4a253c6578884603b56fb0a68642657602d6"),
MockIO::print("- permissioned_candidates_policy_id: 58b4ba68f641d58f7f1bba07182eca9386da1e88a34d47a14638c3fe"),
MockIO::print("Native Token Management Configuration (unused if empty):"),
MockIO::print("- asset name: 5043546f6b656e44656d6f"),
MockIO::print("- asset policy ID: ada83ddd029614381f00e28de0922ab0dec6983ea9dd29ae20eef9b4"),
MockIO::print("- illiquid supply address: addr_test1wrhvtvx3f0g9wv9rx8kfqc60jva3e07nqujk2cspekv4mqs9rjdvz"),
])
}

Expand Down Expand Up @@ -249,6 +260,15 @@ fn set_env_vars_io() -> MockIO {
"PERMISSIONED_CANDIDATES_POLICY_ID",
"58b4ba68f641d58f7f1bba07182eca9386da1e88a34d47a14638c3fe",
),
MockIO::set_env_var(
"NATIVE_TOKEN_POLICY_ID",
"ada83ddd029614381f00e28de0922ab0dec6983ea9dd29ae20eef9b4",
),
MockIO::set_env_var("NATIVE_TOKEN_ASSET_NAME", "5043546f6b656e44656d6f"),
MockIO::set_env_var(
"ILLIQUID_SUPPLY_VALIDATOR_ADDRESS",
"addr_test1wrhvtvx3f0g9wv9rx8kfqc60jva3e07nqujk2cspekv4mqs9rjdvz",
),
])
}

Expand Down Expand Up @@ -349,5 +369,8 @@ fn read_chain_config_io() -> MockIO {
MockIO::file_read(CHAIN_CONFIG_FILE_PATH), // committee candidates address
MockIO::file_read(CHAIN_CONFIG_FILE_PATH), // d parameter policy id
MockIO::file_read(CHAIN_CONFIG_FILE_PATH), // permissioned candidates policy id
MockIO::file_read(CHAIN_CONFIG_FILE_PATH), // native token policy id
MockIO::file_read(CHAIN_CONFIG_FILE_PATH), // native token asset name
MockIO::file_read(CHAIN_CONFIG_FILE_PATH), // illiquid supply validator address
])
}
12 changes: 12 additions & 0 deletions partner-chains-cli/src/generate_keys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,18 @@ pub fn set_dummy_env_vars<C: IOContext>(context: &C) {
"PERMISSIONED_CANDIDATES_POLICY_ID",
"00000000000000000000000000000000000000000000000000000000",
);
context.set_env_var(
"NATIVE_TOKEN_POLICY_ID",
"00000000000000000000000000000000000000000000000000000000",
);
context.set_env_var(
"NATIVE_TOKEN_ASSET_NAME",
"00000000000000000000000000000000000000000000000000000000",
);
context.set_env_var(
"ILLIQUID_SUPPLY_VALIDATOR_ADDRESS",
"00000000000000000000000000000000000000000000000000000000",
);
}

pub fn generate_spo_keys<C: IOContext>(
Expand Down
12 changes: 12 additions & 0 deletions partner-chains-cli/src/generate_keys/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,18 @@ pub mod scenarios {
"PERMISSIONED_CANDIDATES_POLICY_ID",
"00000000000000000000000000000000000000000000000000000000",
),
MockIO::set_env_var(
"NATIVE_TOKEN_POLICY_ID",
"00000000000000000000000000000000000000000000000000000000",
),
MockIO::set_env_var(
"NATIVE_TOKEN_ASSET_NAME",
"00000000000000000000000000000000000000000000000000000000",
),
MockIO::set_env_var(
"ILLIQUID_SUPPLY_VALIDATOR_ADDRESS",
"00000000000000000000000000000000000000000000000000000000",
),
])
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::config::config_fields::{
CARDANO_NETWORK, COMMITTEE_CANDIDATES_ADDRESS, D_PARAMETER_POLICY_ID,
INITIAL_PERMISSIONED_CANDIDATES, PERMISSIONED_CANDIDATES_POLICY_ID,
CARDANO_NETWORK, COMMITTEE_CANDIDATES_ADDRESS, D_PARAMETER_POLICY_ID, ILLIQUID_SUPPLY_ADDRESS,
INITIAL_PERMISSIONED_CANDIDATES, NATIVE_TOKEN_ASSET_NAME, NATIVE_TOKEN_POLICY,
PERMISSIONED_CANDIDATES_POLICY_ID,
};
use crate::config::{
get_cardano_network_from_file, CardanoNetwork, SidechainParams, PC_CONTRACTS_CLI_PATH,
Expand All @@ -13,6 +14,7 @@ use crate::prepare_configuration::prepare_cardano_params::prepare_cardano_params
use crate::smart_contracts;
use anyhow::anyhow;
use serde_json::Value;
use sidechain_domain::PolicyId;

// pc-contracts-cli addresses command requires providing a signing key, but the key has no influence on
// its output, thus using a dummy key
Expand Down Expand Up @@ -41,6 +43,7 @@ pub fn prepare_main_chain_config<C: IOContext>(
if INITIAL_PERMISSIONED_CANDIDATES.load_from_file(context).is_none() {
INITIAL_PERMISSIONED_CANDIDATES.save_to_file(&vec![], context)
}
prepare_native_token(context)?;
context.eprint(OUTRO);
Ok(())
}
Expand Down Expand Up @@ -126,6 +129,31 @@ fn run_pc_contracts_cli_addresses<C: IOContext>(
.ok_or(anyhow!("Permissioned candidates policy id from pc-contracts-cli addresses command output cannot be converted to string"))?
.to_string(),
context);
ILLIQUID_SUPPLY_ADDRESS.save_to_file(
&addresses_json.pointer("/addresses/IlliquidCirculationSupplyValidator")
.ok_or(anyhow!("Illiquid circulation supply validator address is missing from pc-contracts-cli addresses command output"))?
.as_str()
.ok_or(anyhow!("Illiquid circulation supply validator address from pc-contracts-cli addresses command output cannot be converted to string"))?
.to_string(),
context,
);
Ok(())
}

fn prepare_native_token<C: IOContext>(context: &C) -> anyhow::Result<()> {
context.print(
"Partner Chains can store their initial token supply on Cardano as Cardano native tokens.",
);
context.print("Creation of the native token is not supported by this wizard and must be performed manually before this step.");
if context.prompt_yes_no("Do you want to configure a native token for you Partner Chain?", true)
{
NATIVE_TOKEN_POLICY.prompt_with_default_from_file_and_save(context);
NATIVE_TOKEN_ASSET_NAME.prompt_with_default_from_file_and_save(context);
} else {
NATIVE_TOKEN_POLICY.save_to_file(&PolicyId::default().to_hex_string(), context);
NATIVE_TOKEN_ASSET_NAME.save_to_file(&"0x".into(), context);
}

Ok(())
}

Expand Down Expand Up @@ -211,6 +239,8 @@ mod tests {
"addr_test1wz5fe8fmxx4v83gzfsdlnhgxm8x7zpldegrqh2wakl3wteqe834r4";
const TEST_PERMISSIONED_CANDIDATES_POLICY_ID: &str =
"13db1ba564b3b264f45974fece44b2beb0a2326b10e65a0f7f300dfb";
const TEST_ILLIQUID_SUPPLY_ADDRESS: &str =
"addr_test1wqn2pkvvmesmxtfa4tz7w8gh8vumr52lpkrhcs4dkg30uqq77h5z4";
const PC_CONTRACTS_CLI_VERSION_CMD_OUTPUT: &str =
"Version: 5.0.0, a770e9bbdcc9410575f8d47c0890801b4ae5c31a";
const PC_CONTRACTS_CLI: &str = "./pc-contracts-cli";
Expand All @@ -229,6 +259,38 @@ mod tests {
),
])
}

pub fn prompt_and_save_native_asset_scripts() -> MockIO {
MockIO::Group(vec![
MockIO::print("Partner Chains can store their initial token supply on Cardano as Cardano native tokens."),
MockIO::print("Creation of the native token is not supported by this wizard and must be performed manually before this step."),
MockIO::prompt_yes_no(
"Do you want to configure a native token for you Partner Chain?",
true,
true,
),
MockIO::file_read(NATIVE_TOKEN_POLICY.config_file),
MockIO::prompt(
NATIVE_TOKEN_POLICY.name,
None,
"ada83ddd029614381f00e28de0922ab0dec6983ea9dd29ae20eef9b4",
),
MockIO::file_read(NATIVE_TOKEN_POLICY.config_file),
MockIO::file_write_json_contains(
NATIVE_TOKEN_POLICY.config_file,
&NATIVE_TOKEN_POLICY.json_pointer(),
"ada83ddd029614381f00e28de0922ab0dec6983ea9dd29ae20eef9b4",
),
MockIO::file_read(NATIVE_TOKEN_ASSET_NAME.config_file),
MockIO::prompt(NATIVE_TOKEN_ASSET_NAME.name, None, "5043546f6b656e44656d6f"),
MockIO::file_read(NATIVE_TOKEN_ASSET_NAME.config_file),
MockIO::file_write_json_contains(
NATIVE_TOKEN_ASSET_NAME.config_file,
&NATIVE_TOKEN_ASSET_NAME.json_pointer(),
"5043546f6b656e44656d6f",
),
])
}
}

#[test]
Expand Down Expand Up @@ -281,12 +343,19 @@ mod tests {
PERMISSIONED_CANDIDATES_POLICY_ID,
TEST_PERMISSIONED_CANDIDATES_POLICY_ID,
),
save_to_existing_file(
ILLIQUID_SUPPLY_ADDRESS,
TEST_ILLIQUID_SUPPLY_ADDRESS,
),
MockIO::file_read(INITIAL_PERMISSIONED_CANDIDATES.config_file),
MockIO::file_read(INITIAL_PERMISSIONED_CANDIDATES.config_file),
MockIO::file_write_json(
INITIAL_PERMISSIONED_CANDIDATES.config_file,
test_chain_config(),
),

scenarios::prompt_and_save_native_asset_scripts(),

MockIO::eprint(OUTRO),
]);
prepare_main_chain_config(&mock_context, test_sidechain_params()).expect("should succeed");
Expand Down Expand Up @@ -349,7 +418,12 @@ mod tests {
PERMISSIONED_CANDIDATES_POLICY_ID,
TEST_PERMISSIONED_CANDIDATES_POLICY_ID,
),
save_to_existing_file(
ILLIQUID_SUPPLY_ADDRESS,
TEST_ILLIQUID_SUPPLY_ADDRESS,
),
MockIO::file_read(INITIAL_PERMISSIONED_CANDIDATES.config_file),
scenarios::prompt_and_save_native_asset_scripts(),
MockIO::eprint(OUTRO),
]);
prepare_main_chain_config(&mock_context, test_sidechain_params()).expect("should succeed");
Expand Down Expand Up @@ -393,7 +467,10 @@ mod tests {
"cardano_addresses": {
"committee_candidates_address": TEST_COMMITTEE_CANDIDATES_ADDRESS,
"d_parameter_policy_id": TEST_D_PARAMETER_POLICY_ID,
"permissioned_candidates_policy_id": TEST_PERMISSIONED_CANDIDATES_POLICY_ID
"permissioned_candidates_policy_id": TEST_PERMISSIONED_CANDIDATES_POLICY_ID,
"native_token": {
"illiquid_supply_address": TEST_ILLIQUID_SUPPLY_ADDRESS,
}
},
"initial_permissioned_candidates": []
})
Expand All @@ -411,7 +488,8 @@ mod tests {
"DParameterValidator": "addr_test1wpqqhw53gnqqpv0t694qlnafkvv2yl4fkusvq5lue9z4srqrqjdh3",
"MerkleRootTokenValidator": "addr_test1wz3gsl0z2wsrqeav0mr869avzln5kuz5dl8wal4mlm6w5nsast866",
"CheckpointValidator": "addr_test1wrln5wjm88f3sg7yg58nt4mlefr45qq89pg3yf6l39kavlqu5jnwk",
"CommitteeHashValidator": "addr_test1wrpf0tq92fgwc3t3y2fe8pf7tgzuneehfh0p6hvp8y5kemsyrkaa5"
"CommitteeHashValidator": "addr_test1wrpf0tq92fgwc3t3y2fe8pf7tgzuneehfh0p6hvp8y5kemsyrkaa5",
"IlliquidCirculationSupplyValidator": TEST_ILLIQUID_SUPPLY_ADDRESS
},
"validatorHashes": {
"CommitteeCandidateValidator": "a89c9d3b31aac3c5024c1bf9dd06d9cde107edca060ba9ddb7e2e5e4",
Expand Down
Loading

0 comments on commit 12d2aa3

Please sign in to comment.