From ddb4f2b7a041937c63cca007e0d17dda97b578fd Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Fri, 23 Feb 2024 15:30:45 +0100 Subject: [PATCH] 455 create integration tests for stellar mainnet with archived proofs (#456) * Refactor integration test helpers * Continue refactoring * Change function signature * Fix compilation * Create mainnet_config in chain_spec.rs * Remove unused specs * Adjust provider client helper * Update default genesis of stellar relay pallet * Amend refactoring * Add new constant for wrapped currency * Choose wrapped currency based on network * Split runtime into `mainnet` and `testnet` * Amend refactoring * WIP * More WIP * WIP * More WIP * Revert changes and try again with included RPC * WIP still compiles * Duplicate code to start instant seal node * Fix merge issues * Rename genesis and impl name * Rename `spec_name` and `impl_name` These have to match what we have in the custom subxt client otherwise the integration tests will not start properly * Bump versions * Update versions in overlay config * Amend version bump * Extract `impl_name` to extra variable * Do integration tests for test and mainnet * Fix small issue in oracle agent * Fix issue about wrong runtime being executed * Small refactoring * Duplicate test for replace * Remove redundant helper function * Update overlay config files * Create test for issue execution from archive * Update testnet config files as well * Change sleep duration * Fix creation of correct `TransactionSetType` from archived entry * Small refactoring * Small refactoring of tests * Fix potential overflow * Increase default Stellar fee value from `p90` to `p95` * Increase `TIMEOUT` for vault integration tests * Fix clippy warning * Use linear backoff delay * Change DEFAULT_MAX_BACKOFF_DELAY_IN_SECS and remove restriction --- Cargo.lock | 99 +- Cargo.toml | 4 +- clients/runtime/Cargo.toml | 4 +- clients/runtime/src/integration/mod.rs | 34 +- clients/runtime/src/rpc.rs | 1 + clients/runtime/src/tests.rs | 20 +- .../stellar_relay_config_mainnet_iowa.json | 8 +- .../connection/connector/message_reader.rs | 2 +- clients/stellar-relay-lib/src/tests/mod.rs | 2 +- .../stellar_relay_config_frankfurt.json | 4 +- .../mainnet/stellar_relay_config_iowa.json | 8 +- .../stellar_relay_config_singapore.json | 4 +- clients/vault/src/oracle/agent.rs | 15 +- .../src/oracle/collector/proof_builder.rs | 17 +- clients/vault/tests/helper/constants.rs | 16 +- clients/vault/tests/helper/helper.rs | 30 +- clients/vault/tests/helper/mod.rs | 181 ++- .../vault/tests/vault_integration_tests.rs | 446 ++++--- clients/wallet/src/horizon/horizon.rs | 11 +- clients/wallet/src/stellar_wallet.rs | 14 +- clients/wallet/src/types.rs | 2 +- pallets/issue/src/lib.rs | 7 +- pallets/stellar-relay/src/lib.rs | 18 +- rpc/Cargo.toml | 32 - testchain/node/Cargo.toml | 26 +- testchain/node/src/benchmarking.rs | 3 +- testchain/node/src/chain_spec.rs | 236 ++-- testchain/node/src/command.rs | 27 +- testchain/node/src/lib.rs | 1 + testchain/node/src/main.rs | 1 + rpc/src/lib.rs => testchain/node/src/rpc.rs | 0 testchain/node/src/service.rs | 311 ++++- testchain/runtime/{ => mainnet}/Cargo.toml | 48 +- testchain/runtime/{ => mainnet}/build.rs | 0 testchain/runtime/mainnet/src/lib.rs | 1020 +++++++++++++++++ testchain/runtime/testnet/Cargo.toml | 168 +++ testchain/runtime/testnet/build.rs | 9 + testchain/runtime/{ => testnet}/src/lib.rs | 0 38 files changed, 2253 insertions(+), 576 deletions(-) delete mode 100644 rpc/Cargo.toml rename rpc/src/lib.rs => testchain/node/src/rpc.rs (100%) rename testchain/runtime/{ => mainnet}/Cargo.toml (78%) rename testchain/runtime/{ => mainnet}/build.rs (100%) create mode 100644 testchain/runtime/mainnet/src/lib.rs create mode 100644 testchain/runtime/testnet/Cargo.toml create mode 100644 testchain/runtime/testnet/build.rs rename testchain/runtime/{ => testnet}/src/lib.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index f087c92ea..3a0b32999 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7217,7 +7217,7 @@ dependencies = [ "sp-std 5.0.0", "sp-version", "spacewalk-primitives", - "spacewalk-runtime-standalone", + "spacewalk-runtime-standalone-testnet", "spacewalk-standalone", "substrate-stellar-sdk", "subxt 0.25.0", @@ -9801,33 +9801,77 @@ dependencies = [ ] [[package]] -name = "spacewalk-rpc" +name = "spacewalk-runtime-standalone-mainnet" version = "1.0.4" dependencies = [ - "jsonrpc-core", - "jsonrpsee", - "module-issue-rpc", - "module-oracle-rpc", - "module-redeem-rpc", - "module-replace-rpc", - "module-vault-registry-rpc", - "pallet-transaction-payment-rpc", - "sc-consensus-manual-seal", - "sc-rpc", - "sc-rpc-api", - "sc-transaction-pool-api", + "cfg-if 1.0.0", + "clients-info", + "currency", + "dia-oracle", + "fee", + "flate2", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "getrandom 0.2.10", + "hex", + "hex-literal 0.3.4", + "issue", + "lazy_static", + "mocktopus", + "module-issue-rpc-runtime-api", + "module-oracle-rpc-runtime-api", + "module-redeem-rpc-runtime-api", + "module-replace-rpc-runtime-api", + "module-vault-registry-rpc-runtime-api", + "nomination", + "oracle", + "orml-currencies", + "orml-oracle", + "orml-tokens", + "orml-traits", + "pallet-aura", + "pallet-balances", + "pallet-grandpa", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "parity-scale-codec", + "pooled-rewards", + "pretty_assertions", + "redeem", + "replace", + "reward", + "reward-distribution", + "scale-info", + "security", + "serde_json", "sp-api", - "sp-arithmetic", "sp-block-builder", - "sp-blockchain", + "sp-consensus-aura", "sp-core", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std 5.0.0", + "sp-transaction-pool", + "sp-version", "spacewalk-primitives", - "substrate-frame-rpc-system", + "staking", + "stellar-relay", + "substrate-wasm-builder", + "vault-registry", ] [[package]] -name = "spacewalk-runtime-standalone" -version = "1.0.4" +name = "spacewalk-runtime-standalone-testnet" +version = "1.0.3" dependencies = [ "cfg-if 1.0.0", "clients-info", @@ -9905,8 +9949,16 @@ dependencies = [ "frame-system", "futures 0.3.28", "hex-literal 0.2.2", + "jsonrpc-core", + "jsonrpsee", "log", + "module-issue-rpc", + "module-oracle-rpc", + "module-redeem-rpc", + "module-replace-rpc", + "module-vault-registry-rpc", "pallet-transaction-payment", + "pallet-transaction-payment-rpc", "parity-scale-codec", "sc-basic-authorship", "sc-cli", @@ -9917,14 +9969,18 @@ dependencies = [ "sc-consensus-manual-seal", "sc-executor", "sc-keystore", + "sc-rpc", + "sc-rpc-api", "sc-service", "sc-telemetry", "sc-transaction-pool", + "sc-transaction-pool-api", "serde", "serde_json", "sp-api", "sp-arithmetic", "sp-block-builder", + "sp-blockchain", "sp-consensus", "sp-consensus-aura", "sp-consensus-grandpa", @@ -9939,9 +9995,10 @@ dependencies = [ "sp-timestamp", "sp-transaction-pool", "spacewalk-primitives", - "spacewalk-rpc", - "spacewalk-runtime-standalone", + "spacewalk-runtime-standalone-mainnet", + "spacewalk-runtime-standalone-testnet", "substrate-build-script-utils", + "substrate-frame-rpc-system", "substrate-stellar-sdk", ] diff --git a/Cargo.toml b/Cargo.toml index 90b499544..314e73f14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,10 +19,10 @@ members = [ "pallets/stellar-relay", "pallets/vault-registry", "primitives", - "rpc", "pallets/*/rpc", "testchain/node", - "testchain/runtime", + "testchain/runtime/mainnet", + "testchain/runtime/testnet", ] [profile.release] panic = "unwind" diff --git a/clients/runtime/Cargo.toml b/clients/runtime/Cargo.toml index 22ad1a968..e87011441 100644 --- a/clients/runtime/Cargo.toml +++ b/clients/runtime/Cargo.toml @@ -57,7 +57,7 @@ oracle = { path = "../../pallets/oracle", optional = true } rand = { version = "0.7", optional = true } tempdir = { version = "0.3.7", optional = true } testchain = { package = "spacewalk-standalone", path = "../../testchain/node", optional = true } -testchain-runtime = { package = "spacewalk-runtime-standalone", path = "../../testchain/runtime", optional = true } +testchain-runtime = { package = "spacewalk-runtime-standalone-testnet", path = "../../testchain/runtime/testnet", optional = true } # Substrate Stellar Dependencies substrate-stellar-sdk = { git = "https://github.com/pendulum-chain/substrate-stellar-sdk", branch = "polkadot-v0.9.40" } @@ -68,7 +68,7 @@ wallet = { path = "../wallet" } env_logger = "0.8.3" tempdir = "0.3.7" runtime = { path = ".", features = ["testing-utils"] } -testchain-runtime = { package = "spacewalk-runtime-standalone", path = "../../testchain/runtime", features = ["testing-utils"] } +testchain-runtime = { package = "spacewalk-runtime-standalone-testnet", path = "../../testchain/runtime/testnet", features = ["testing-utils"] } diff --git a/clients/runtime/src/integration/mod.rs b/clients/runtime/src/integration/mod.rs index 148a72d38..9fad7b104 100644 --- a/clients/runtime/src/integration/mod.rs +++ b/clients/runtime/src/integration/mod.rs @@ -57,16 +57,33 @@ impl XCMCurrencyConversion for MockValue { /// Start a new instance of the parachain. The second item in the returned tuple must remain in /// scope as long as the parachain is active, since dropping it will remove the temporary directory /// that the parachain uses -pub async fn default_provider_client(key: AccountKeyring) -> (SubxtClient, TempDir) { +pub async fn default_provider_client( + key: AccountKeyring, + is_public_network: bool, +) -> (SubxtClient, TempDir) { + let chain_spec = if is_public_network { + testchain::chain_spec::mainnet_config() + } else { + testchain::chain_spec::testnet_config() + }; + + // This does not necessarily have to match the `impl_name` of the runtime. We give it a + // descriptive name because it will be shown when starting the testing client. + let impl_name = if is_public_network { + "spacewalk-standalone-mainnet" + } else { + "spacewalk-standalone-testnet" + }; + let tmp = TempDir::new("spacewalk-parachain-").expect("failed to create tempdir"); let config = SubxtClientConfig { - impl_name: "spacewalk-parachain-full-client", + impl_name, impl_version: "0.0.1", author: "SatoshiPay", copyright_start_year: 2020, db: DatabaseSource::ParityDb { path: tmp.path().join("db") }, keystore: KeystoreConfig::Path { path: tmp.path().join("keystore"), password: None }, - chain_spec: testchain::chain_spec::development_config(), + chain_spec, role: Role::Authority(key), telemetry: None, wasm_method: WasmExecutionMethod::Compiled { @@ -79,8 +96,15 @@ pub async fn default_provider_client(key: AccountKeyring) -> (SubxtClient, TempD let mut service_config = config.into_service_config(); service_config.offchain_worker.enabled = true; - let (task_manager, rpc_handlers) = - testchain::service::start_instant(service_config).await.unwrap(); + let (task_manager, rpc_handlers) = if is_public_network { + testchain::service::start_instant_mainnet(service_config) + .await + .expect("Couldn't start mainnet") + } else { + testchain::service::start_instant_testnet(service_config) + .await + .expect("Couldn't start testnet") + }; let client = SubxtClient::new(task_manager, rpc_handlers); diff --git a/clients/runtime/src/rpc.rs b/clients/runtime/src/rpc.rs index 9d0741740..a2b34c229 100644 --- a/clients/runtime/src/rpc.rs +++ b/clients/runtime/src/rpc.rs @@ -39,6 +39,7 @@ compile_error!("Tests are only supported for the standalone-metadata"); cfg_if::cfg_if! { if #[cfg(feature = "standalone-metadata")] { const DEFAULT_SPEC_VERSION: Range = 1..100; + // This has to match the `spec_name` in the runtime, otherwise the runtime will be rejected. pub const DEFAULT_SPEC_NAME: &str = "spacewalk-standalone"; // The prefix for the testchain is 42 pub const SS58_PREFIX: u16 = 42; diff --git a/clients/runtime/src/tests.rs b/clients/runtime/src/tests.rs index 4ba834167..ddb93da97 100644 --- a/clients/runtime/src/tests.rs +++ b/clients/runtime/src/tests.rs @@ -39,7 +39,9 @@ async fn set_exchange_rate(client: SubxtClient) { #[tokio::test(flavor = "multi_thread")] async fn test_getters() { - let (client, _tmp_dir) = default_provider_client(AccountKeyring::Alice).await; + let is_public_network = false; + let (client, _tmp_dir) = + default_provider_client(AccountKeyring::Alice, is_public_network).await; let parachain_rpc = setup_provider(client.clone(), AccountKeyring::Alice).await; tokio::join!( @@ -62,7 +64,9 @@ async fn test_getters() { #[ignore] #[tokio::test(flavor = "multi_thread")] async fn test_invalid_tx_matching() { - let (client, _tmp_dir) = default_provider_client(AccountKeyring::Alice).await; + let is_public_network = false; + let (client, _tmp_dir) = + default_provider_client(AccountKeyring::Alice, is_public_network).await; let parachain_rpc = setup_provider(client.clone(), AccountKeyring::Alice).await; let err = parachain_rpc.get_invalid_tx_error(AccountKeyring::Bob.into()).await; assert!(err.is_invalid_transaction().is_some()) @@ -71,7 +75,9 @@ async fn test_invalid_tx_matching() { #[ignore] #[tokio::test(flavor = "multi_thread")] async fn test_too_low_priority_matching() { - let (client, _tmp_dir) = default_provider_client(AccountKeyring::Alice).await; + let is_public_network = false; + let (client, _tmp_dir) = + default_provider_client(AccountKeyring::Alice, is_public_network).await; let parachain_rpc = setup_provider(client.clone(), AccountKeyring::Alice).await; let err = parachain_rpc.get_too_low_priority_error(AccountKeyring::Bob.into()).await; assert!(err.is_pool_too_low_priority()) @@ -79,7 +85,9 @@ async fn test_too_low_priority_matching() { #[tokio::test(flavor = "multi_thread")] async fn test_subxt_processing_events_after_dispatch_error() { - let (client, _tmp_dir) = default_provider_client(AccountKeyring::Alice).await; + let is_public_network = false; + let (client, _tmp_dir) = + default_provider_client(AccountKeyring::Alice, is_public_network).await; let oracle_provider = setup_provider(client.clone(), AccountKeyring::Bob).await; let invalid_oracle = setup_provider(client, AccountKeyring::Dave).await; @@ -100,7 +108,9 @@ async fn test_subxt_processing_events_after_dispatch_error() { #[tokio::test(flavor = "multi_thread")] async fn test_register_vault() { - let (client, _tmp_dir) = default_provider_client(AccountKeyring::Alice).await; + let is_public_network = false; + let (client, _tmp_dir) = + default_provider_client(AccountKeyring::Alice, is_public_network).await; let parachain_rpc = setup_provider(client.clone(), AccountKeyring::Alice).await; set_exchange_rate(client.clone()).await; diff --git a/clients/stellar-relay-lib/resources/config/mainnet/stellar_relay_config_mainnet_iowa.json b/clients/stellar-relay-lib/resources/config/mainnet/stellar_relay_config_mainnet_iowa.json index 2ceb54622..e470a4c39 100644 --- a/clients/stellar-relay-lib/resources/config/mainnet/stellar_relay_config_mainnet_iowa.json +++ b/clients/stellar-relay-lib/resources/config/mainnet/stellar_relay_config_mainnet_iowa.json @@ -5,14 +5,12 @@ }, "node_info": { "ledger_version": 20, - "overlay_version": 30, + "overlay_version": 32, "overlay_min_version": 27, - "version_str": "stellar-core 20.0.2 (669916b56106a72a7f79ab8b4a7898e77b28b49e)", + "version_str": "stellar-core 20.2.0 (34d82fc00426643e16b7ad59c9fde169b778eb4b)", "is_pub_net": true }, "stellar_history_archive_urls": [ - "https://stellar-history-us-iowa.satoshipay.io", - "https://stellar-history-de-fra.satoshipay.io", - "https://stellar-history-sg-sin.satoshipay.io" + "http://history.stellar.org/prd/core-live/core_live_001" ] } \ No newline at end of file diff --git a/clients/stellar-relay-lib/src/connection/connector/message_reader.rs b/clients/stellar-relay-lib/src/connection/connector/message_reader.rs index 4e308c7ad..3c5a08ec3 100644 --- a/clients/stellar-relay-lib/src/connection/connector/message_reader.rs +++ b/clients/stellar-relay-lib/src/connection/connector/message_reader.rs @@ -114,7 +114,7 @@ async fn read_message_from_stellar(connector: &mut Connector) -> Result { // The next few bytes was read. Add it to the readbuf. - lack_bytes_from_prev -= size; + lack_bytes_from_prev = lack_bytes_from_prev.saturating_sub(size); readbuf.append(&mut buff_for_reading); // make sure to cleanup the buffer buff_for_reading = vec![0; 4]; diff --git a/clients/stellar-relay-lib/src/tests/mod.rs b/clients/stellar-relay-lib/src/tests/mod.rs index 26e77bf72..a9cebc2b1 100644 --- a/clients/stellar-relay-lib/src/tests/mod.rs +++ b/clients/stellar-relay-lib/src/tests/mod.rs @@ -144,6 +144,6 @@ async fn stellar_overlay_disconnect_works() { overlay_connection.stop(); // let the disconnection call pass for a few seconds, before checking its status. - sleep(Duration::from_secs(3)); + sleep(Duration::from_secs(15)); assert!(!overlay_connection.is_alive()); } diff --git a/clients/vault/resources/config/mainnet/stellar_relay_config_frankfurt.json b/clients/vault/resources/config/mainnet/stellar_relay_config_frankfurt.json index 9d07ff048..33de56f48 100644 --- a/clients/vault/resources/config/mainnet/stellar_relay_config_frankfurt.json +++ b/clients/vault/resources/config/mainnet/stellar_relay_config_frankfurt.json @@ -5,9 +5,9 @@ }, "node_info": { "ledger_version": 20, - "overlay_version": 30, + "overlay_version": 32, "overlay_min_version": 27, - "version_str": "stellar-core 20.0.2 (669916b56106a72a7f79ab8b4a7898e77b28b49e)", + "version_str": "stellar-core 20.2.0 (34d82fc00426643e16b7ad59c9fde169b778eb4b)", "is_pub_net": true }, "stellar_history_archive_urls": [ diff --git a/clients/vault/resources/config/mainnet/stellar_relay_config_iowa.json b/clients/vault/resources/config/mainnet/stellar_relay_config_iowa.json index 2ceb54622..e470a4c39 100644 --- a/clients/vault/resources/config/mainnet/stellar_relay_config_iowa.json +++ b/clients/vault/resources/config/mainnet/stellar_relay_config_iowa.json @@ -5,14 +5,12 @@ }, "node_info": { "ledger_version": 20, - "overlay_version": 30, + "overlay_version": 32, "overlay_min_version": 27, - "version_str": "stellar-core 20.0.2 (669916b56106a72a7f79ab8b4a7898e77b28b49e)", + "version_str": "stellar-core 20.2.0 (34d82fc00426643e16b7ad59c9fde169b778eb4b)", "is_pub_net": true }, "stellar_history_archive_urls": [ - "https://stellar-history-us-iowa.satoshipay.io", - "https://stellar-history-de-fra.satoshipay.io", - "https://stellar-history-sg-sin.satoshipay.io" + "http://history.stellar.org/prd/core-live/core_live_001" ] } \ No newline at end of file diff --git a/clients/vault/resources/config/mainnet/stellar_relay_config_singapore.json b/clients/vault/resources/config/mainnet/stellar_relay_config_singapore.json index 1bebf7e3e..cc79df90d 100644 --- a/clients/vault/resources/config/mainnet/stellar_relay_config_singapore.json +++ b/clients/vault/resources/config/mainnet/stellar_relay_config_singapore.json @@ -5,9 +5,9 @@ }, "node_info": { "ledger_version": 20, - "overlay_version": 30, + "overlay_version": 32, "overlay_min_version": 27, - "version_str": "stellar-core 20.0.2 (669916b56106a72a7f79ab8b4a7898e77b28b49e)", + "version_str": "stellar-core 20.2.0 (34d82fc00426643e16b7ad59c9fde169b778eb4b)", "is_pub_net": true }, "stellar_history_archive_urls": [ diff --git a/clients/vault/src/oracle/agent.rs b/clients/vault/src/oracle/agent.rs index 76f0b08a0..55dfabac6 100644 --- a/clients/vault/src/oracle/agent.rs +++ b/clients/vault/src/oracle/agent.rs @@ -64,6 +64,8 @@ pub async fn start_oracle_agent( secret_key: &str, shutdown_sender: ShutdownSender, ) -> Result { + let is_public_network = config.is_public_network(); + tracing::info!("start_oracle_agent(): Starting connection to Stellar overlay network..."); let mut overlay_conn = connect_to_stellar_overlay_network(config.clone(), secret_key).await?; @@ -134,12 +136,7 @@ pub async fn start_oracle_agent( } })); - Ok(OracleAgent { - collector, - is_public_network: false, - message_sender: Some(sender), - shutdown_sender, - }) + Ok(OracleAgent { collector, is_public_network, message_sender: Some(sender), shutdown_sender }) } impl Drop for OracleAgent { @@ -218,12 +215,12 @@ mod tests { use serial_test::serial; #[tokio::test(flavor = "multi_thread")] - #[ntest::timeout(1_800_000)] // timeout at 30 minutes + #[ntest::timeout(600_000)] // timeout at 10 minutes #[serial] async fn test_get_proof_for_current_slot() { // let it run for a few seconds, making sure that the other tests have successfully shutdown // their connection to Stellar Node - sleep(Duration::from_secs(2)).await; + sleep(Duration::from_secs(20)).await; let shutdown_sender = ShutdownSender::new(); @@ -235,8 +232,6 @@ mod tests { ) .await .expect("Failed to start agent"); - sleep(Duration::from_secs(10)).await; - // Wait until agent is caught up with the network. let mut latest_slot = 0; while latest_slot == 0 { diff --git a/clients/vault/src/oracle/collector/proof_builder.rs b/clients/vault/src/oracle/collector/proof_builder.rs index 32ca96f70..2bbc00ac0 100644 --- a/clients/vault/src/oracle/collector/proof_builder.rs +++ b/clients/vault/src/oracle/collector/proof_builder.rs @@ -1,3 +1,4 @@ +use primitives::stellar::types::TransactionHistoryEntryExt; use std::{convert::TryFrom, future::Future}; use tracing::log; @@ -343,8 +344,16 @@ impl ScpMessageCollector { "get_txset_from_horizon_archive(): Adding archived tx set for slot {slot}" ); let mut tx_set_map = txset_map_arc.write(); - tx_set_map - .insert(slot, TransactionSetType::new(target_history_entry.tx_set.clone())); + + // Assign the transaction set based on the type defined in `ext` + let tx_set_type = match target_history_entry.clone().ext { + TransactionHistoryEntryExt::V1(generalized_tx_set) => + // If the type of `ext` is `V1` we use the contained generalized tx set + TransactionSetType::new(generalized_tx_set), + // Otherwise we can use the regular `tx_set` contained in the entry + _ => TransactionSetType::new(target_history_entry.tx_set.clone()), + }; + tx_set_map.insert(slot, tx_set_type); break } else { tracing::warn!( @@ -372,12 +381,12 @@ mod test { assert!(!check_slot_still_recoverable_from_overlay(last_slot, 30_000)); assert!(!check_slot_still_recoverable_from_overlay( last_slot, - last_slot - MAX_SLOTS_TO_REMEMBER + last_slot - MAX_SLOTS_TO_REMEMBER, )); assert!(check_slot_still_recoverable_from_overlay(last_slot, last_slot - 1)); assert!(check_slot_still_recoverable_from_overlay( last_slot, - last_slot - MAX_SLOTS_TO_REMEMBER + 1 + last_slot - MAX_SLOTS_TO_REMEMBER + 1, )); } } diff --git a/clients/vault/tests/helper/constants.rs b/clients/vault/tests/helper/constants.rs index 795682992..76bdc2624 100644 --- a/clients/vault/tests/helper/constants.rs +++ b/clients/vault/tests/helper/constants.rs @@ -2,12 +2,14 @@ use primitives::CurrencyId; use std::time::Duration; use wallet::types::PagingToken; -pub const TIMEOUT: Duration = Duration::from_secs(60); +// We increase the timout to 6 minutes because the oracle agent might sometimes need to fall back to +// archived messages which are only available after about 5 minutes +pub const TIMEOUT: Duration = Duration::from_secs(60 * 6); // Be careful when changing these values because they are used in the parachain genesis config // and only for some combination of them, secure collateralization thresholds are set. pub const DEFAULT_TESTING_CURRENCY: CurrencyId = CurrencyId::XCM(0); -pub const DEFAULT_WRAPPED_CURRENCY: CurrencyId = CurrencyId::AlphaNum4( +pub const DEFAULT_WRAPPED_CURRENCY_STELLAR_TESTNET: CurrencyId = CurrencyId::AlphaNum4( *b"USDC", [ 20, 209, 150, 49, 176, 55, 23, 217, 171, 154, 54, 110, 16, 50, 30, 226, 102, 231, 46, 199, @@ -15,6 +17,14 @@ pub const DEFAULT_WRAPPED_CURRENCY: CurrencyId = CurrencyId::AlphaNum4( ], ); +pub const DEFAULT_WRAPPED_CURRENCY_STELLAR_MAINNET: CurrencyId = CurrencyId::AlphaNum4( + *b"USDC", + [ + 59, 153, 17, 56, 14, 254, 152, 139, 160, 168, 144, 14, 177, 207, 228, 79, 54, 111, 125, + 190, 148, 107, 237, 7, 114, 64, 247, 246, 36, 223, 21, 197, + ], +); + pub const LESS_THAN_4_CURRENCY_CODE: CurrencyId = CurrencyId::AlphaNum4( *b"MXN\0", [ @@ -25,7 +35,7 @@ pub const LESS_THAN_4_CURRENCY_CODE: CurrencyId = CurrencyId::AlphaNum4( #[allow(dead_code)] pub const DEFAULT_MAINNET_DEST_SECRET_KEY: &'static str = - "SCJ7XV73Q642EPMUMSPO5ECOXWTMWR52MGPMWT6ELV3VUFPH653IOEUS"; + "SBLI7RKEJAEFGLZUBSCOFJHQBPFYIIPLBCKN7WVCWT4NEG2UJEW33N73"; pub const DEFAULT_TESTNET_DEST_SECRET_KEY: &'static str = "SA77KS7EHYNOO6VIT3RBH36WSWDIA4PUV53EDEDAST3OWEKMDZ5HCUGW"; diff --git a/clients/vault/tests/helper/helper.rs b/clients/vault/tests/helper/helper.rs index cb8a49059..e2a4ae512 100644 --- a/clients/vault/tests/helper/helper.rs +++ b/clients/vault/tests/helper/helper.rs @@ -1,4 +1,7 @@ -use crate::helper::DEFAULT_TESTING_CURRENCY; +use crate::helper::{ + DEFAULT_TESTING_CURRENCY, DEFAULT_WRAPPED_CURRENCY_STELLAR_MAINNET, + DEFAULT_WRAPPED_CURRENCY_STELLAR_TESTNET, +}; use async_trait::async_trait; use frame_support::assert_ok; use primitives::{stellar::Asset as StellarAsset, CurrencyId, StellarStroops, H256}; @@ -16,12 +19,26 @@ use stellar_relay_lib::sdk::PublicKey; use vault::{oracle::OracleAgent, ArcRwLock}; use wallet::{error::Error, StellarWallet, TransactionResponse}; -pub fn default_destination() -> SecretKey { - SecretKey::from_encoding(crate::helper::DEFAULT_TESTNET_DEST_SECRET_KEY).expect("Should work") +pub fn default_destination(is_public_network: bool) -> SecretKey { + if is_public_network { + SecretKey::from_encoding(crate::helper::DEFAULT_MAINNET_DEST_SECRET_KEY) + .expect("Should work") + } else { + SecretKey::from_encoding(crate::helper::DEFAULT_TESTNET_DEST_SECRET_KEY) + .expect("Should work") + } } -pub fn default_destination_as_binary() -> [u8; 32] { - default_destination().get_public().clone().into_binary() +pub fn default_destination_as_binary(is_public_network: bool) -> [u8; 32] { + default_destination(is_public_network).get_public().clone().into_binary() +} + +pub fn default_wrapped_currency(is_public_network: bool) -> CurrencyId { + if is_public_network { + DEFAULT_WRAPPED_CURRENCY_STELLAR_MAINNET + } else { + DEFAULT_WRAPPED_CURRENCY_STELLAR_TESTNET + } } // A simple helper function to convert StellarStroops (i64) to the up-scaled u128 @@ -82,8 +99,9 @@ pub async fn register_vault( pub async fn register_vault_with_default_destination( items: Vec<(&SpacewalkParachain, &VaultId, u128)>, + is_public_network: bool, ) -> u128 { - let public_key = default_destination().get_public().clone(); + let public_key = default_destination(is_public_network).get_public().clone(); register_vault(public_key, items).await } diff --git a/clients/vault/tests/helper/mod.rs b/clients/vault/tests/helper/mod.rs index caa17e9b5..3e3a3bce0 100644 --- a/clients/vault/tests/helper/mod.rs +++ b/clients/vault/tests/helper/mod.rs @@ -27,82 +27,88 @@ use wallet::StellarWallet; pub type StellarPublicKey = [u8; 32]; +#[async_trait] +impl SpacewalkParachainExt for SpacewalkParachain {} + lazy_static! { - pub static ref CFG: StellarOverlayConfig = random_stellar_relay_config(false); - pub static ref SECRET_KEY: String = get_test_secret_key(false); // TODO clean this up by extending the `get_test_secret_key()` function pub static ref DESTINATION_SECRET_KEY: String = "SDNQJEIRSA6YF5JNS6LQLCBF2XVWZ2NJV3YLC322RGIBJIJRIRGWKLEF".to_string(); + pub static ref ONE_TO_ONE_RATIO: FixedU128 = FixedU128::saturating_from_rational(1u128, 1u128); + pub static ref TEN_TO_ONE_RATIO: FixedU128 = FixedU128::saturating_from_rational(1u128, 10u128); } -#[async_trait] -impl SpacewalkParachainExt for SpacewalkParachain {} - -pub async fn test_with( - execute: impl FnOnce(SubxtClient, ArcRwLock, ArcRwLock) -> F, -) -> R -where - F: Future, -{ - service::init_subscriber(); - let (client, tmp_dir) = default_provider_client(AccountKeyring::Alice).await; - - // Has to be Bob because he is set as `authorized_oracle` in the genesis config - let parachain_rpc = setup_provider(client.clone(), AccountKeyring::Bob).await; - - set_exchange_rate_and_wait( - ¶chain_rpc, - DEFAULT_TESTING_CURRENCY, - // Set exchange rate to 1:1 with USD - FixedU128::saturating_from_rational(1u128, 1u128), - ) - .await; - set_exchange_rate_and_wait( - ¶chain_rpc, - DEFAULT_WRAPPED_CURRENCY, - // Set exchange rate to 10:1 with USD - FixedU128::saturating_from_rational(1u128, 10u128), - ) - .await; - - set_exchange_rate_and_wait( - ¶chain_rpc, - LESS_THAN_4_CURRENCY_CODE, - // Set exchange rate to 10:1 with USD - FixedU128::saturating_from_rational(1u128, 10u128), - ) - .await; - - set_exchange_rate_and_wait( - ¶chain_rpc, - CurrencyId::StellarNative, - // Set exchange rate to 10:1 with USD - FixedU128::saturating_from_rational(1u128, 10u128), - ) - .await; - - let path = tmp_dir.path().to_str().expect("should return a string").to_string(); +async fn initialize_wallets( + vault_stellar_secret: &String, + user_stellar_secret: &String, + path: String, + config: StellarOverlayConfig, +) -> (ArcRwLock, ArcRwLock) { let vault_wallet = Arc::new(RwLock::new( StellarWallet::from_secret_encoded_with_cache( - &SECRET_KEY, - CFG.is_public_network(), + vault_stellar_secret.as_str(), + config.is_public_network(), path.clone(), ) .unwrap(), )); - let user_wallet = Arc::new(RwLock::new( StellarWallet::from_secret_encoded_with_cache( - &DESTINATION_SECRET_KEY, - CFG.is_public_network(), + user_stellar_secret.as_str(), + config.is_public_network(), path, ) .unwrap(), )); + (vault_wallet, user_wallet) +} + +async fn setup_chain_providers( + is_public_network: bool, +) -> (SubxtClient, ArcRwLock, ArcRwLock) { + let (client, tmp_dir) = default_provider_client(AccountKeyring::Alice, is_public_network).await; + + // Has to be Bob because he is set as `authorized_oracle` in the genesis config + let parachain_rpc = setup_provider(client.clone(), AccountKeyring::Bob).await; + + let default_wrapped_currency = if is_public_network { + DEFAULT_WRAPPED_CURRENCY_STELLAR_MAINNET + } else { + DEFAULT_WRAPPED_CURRENCY_STELLAR_TESTNET + }; + + set_exchange_rate_and_wait(¶chain_rpc, DEFAULT_TESTING_CURRENCY, *ONE_TO_ONE_RATIO).await; + set_exchange_rate_and_wait(¶chain_rpc, default_wrapped_currency, *TEN_TO_ONE_RATIO).await; + set_exchange_rate_and_wait(¶chain_rpc, LESS_THAN_4_CURRENCY_CODE, *TEN_TO_ONE_RATIO).await; + set_exchange_rate_and_wait(¶chain_rpc, CurrencyId::StellarNative, *TEN_TO_ONE_RATIO).await; + + let path = tmp_dir.path().to_str().expect("should return a string").to_string(); + + let stellar_config = random_stellar_relay_config(is_public_network); + let vault_stellar_secret = get_test_secret_key(is_public_network); + // TODO set destination secret key in a better way + let user_stellar_secret = &DESTINATION_SECRET_KEY; + + let (vault_wallet, user_wallet) = + initialize_wallets(&vault_stellar_secret, &user_stellar_secret, path, stellar_config).await; + + return (client, vault_wallet, user_wallet) +} + +pub async fn test_with( + is_public_network: bool, + execute: impl FnOnce(SubxtClient, ArcRwLock, ArcRwLock) -> F, +) -> R +where + F: Future, +{ + service::init_subscriber(); + let (client, vault_wallet, user_wallet) = setup_chain_providers(is_public_network).await; execute(client, vault_wallet, user_wallet).await } pub async fn test_with_vault( + is_public_network: bool, execute: impl FnOnce( SubxtClient, ArcRwLock, @@ -116,69 +122,30 @@ where F: Future, { service::init_subscriber(); - let (client, tmp_dir) = default_provider_client(AccountKeyring::Alice).await; - let parachain_rpc = setup_provider(client.clone(), AccountKeyring::Bob).await; - set_exchange_rate_and_wait( - ¶chain_rpc, - DEFAULT_TESTING_CURRENCY, - FixedU128::saturating_from_rational(1u128, 1u128), - ) - .await; - set_exchange_rate_and_wait( - ¶chain_rpc, - DEFAULT_WRAPPED_CURRENCY, - // Set exchange rate to 10:1 with USD - FixedU128::saturating_from_rational(1u128, 10u128), - ) - .await; - - set_exchange_rate_and_wait( - ¶chain_rpc, - LESS_THAN_4_CURRENCY_CODE, - // Set exchange rate to 100:1 with USD - FixedU128::saturating_from_rational(1u128, 10u128), - ) - .await; - - set_exchange_rate_and_wait( - ¶chain_rpc, - CurrencyId::StellarNative, - // Set exchange rate to 10:1 with USD - FixedU128::saturating_from_rational(1u128, 10u128), - ) - .await; + let (client, vault_wallet, user_wallet) = setup_chain_providers(is_public_network).await; let vault_provider = setup_provider(client.clone(), AccountKeyring::Charlie).await; + let default_wrapped_currency = if is_public_network { + DEFAULT_WRAPPED_CURRENCY_STELLAR_MAINNET + } else { + DEFAULT_WRAPPED_CURRENCY_STELLAR_TESTNET + }; + let vault_id = VaultId::new( AccountKeyring::Charlie.into(), DEFAULT_TESTING_CURRENCY, - DEFAULT_WRAPPED_CURRENCY, + default_wrapped_currency, ); - let path = tmp_dir.path().to_str().expect("should return a string").to_string(); - let vault_wallet = Arc::new(RwLock::new( - StellarWallet::from_secret_encoded_with_cache( - &SECRET_KEY, - CFG.is_public_network(), - path.clone(), - ) - .unwrap(), - )); - - let user_wallet = Arc::new(RwLock::new( - StellarWallet::from_secret_encoded_with_cache( - &DESTINATION_SECRET_KEY, - CFG.is_public_network(), - path, - ) - .unwrap(), - )); + let stellar_config = random_stellar_relay_config(is_public_network); + let vault_stellar_secret = get_test_secret_key(is_public_network); let shutdown_tx = ShutdownSender::new(); - let oracle_agent = start_oracle_agent(CFG.clone(), &SECRET_KEY, shutdown_tx) - .await - .expect("failed to start agent"); + let oracle_agent = + start_oracle_agent(stellar_config.clone(), &vault_stellar_secret, shutdown_tx) + .await + .expect("failed to start agent"); let oracle_agent = Arc::new(oracle_agent); execute(client, vault_wallet, user_wallet, oracle_agent, vault_id, vault_provider).await diff --git a/clients/vault/tests/vault_integration_tests.rs b/clients/vault/tests/vault_integration_tests.rs index 98660589c..05c7db084 100644 --- a/clients/vault/tests/vault_integration_tests.rs +++ b/clients/vault/tests/vault_integration_tests.rs @@ -20,13 +20,15 @@ use stellar_relay_lib::sdk::PublicKey; use vault::{service::IssueFilter, DecimalsLookupImpl, Event as CancellationEvent, VaultIdManager}; mod helper; + use helper::*; use primitives::DecimalsLookup; +use vault::oracle::{get_test_secret_key, random_stellar_relay_config, start_oracle_agent}; #[tokio::test(flavor = "multi_thread")] #[serial] async fn test_register() { - test_with(|client, vault_wallet, _| async move { + test_with(false, |client, vault_wallet, _| async move { let (eve_id, eve_provider) = create_vault(client.clone(), AccountKeyring::Eve, CurrencyId::StellarNative).await; let (dave_id, dave_provider) = @@ -45,8 +47,21 @@ async fn test_register() { #[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_redeem_succeeds() { +async fn test_redeem_succeeds_on_mainnet() { + let is_public_network = true; + test_redeem_succeeds_on_network(is_public_network).await; +} + +#[tokio::test(flavor = "multi_thread")] +#[serial] +async fn test_redeem_succeeds_on_testnet() { + let is_public_network = false; + test_redeem_succeeds_on_network(is_public_network).await; +} + +async fn test_redeem_succeeds_on_network(is_public_network: bool) { test_with_vault( + is_public_network, |client, vault_wallet, user_wallet, oracle_agent, vault_id, vault_provider| async move { let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; @@ -55,7 +70,7 @@ async fn test_redeem_succeeds() { VaultIdManager::from_map(vault_provider.clone(), vault_wallet.clone(), vault_ids); // We issue 1 (spacewalk-chain) unit - let issue_amount = DecimalsLookupImpl::one(CurrencyId::Native); + let issue_amount = DecimalsLookupImpl::one(CurrencyId::Native) / 100; let vault_collateral = get_required_vault_collateral_for_issue( &vault_provider, issue_amount, @@ -69,7 +84,7 @@ async fn test_redeem_succeeds() { .register_vault_with_public_key( &vault_id, vault_collateral, - default_destination_as_binary() + default_destination_as_binary(is_public_network) ) .await ); @@ -113,16 +128,33 @@ async fn test_redeem_succeeds() { #[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_replace_succeeds() { +async fn test_replace_succeeds_on_mainnet() { + let is_public_network = true; + test_replace_succeeds_on_network(is_public_network).await +} + +#[tokio::test(flavor = "multi_thread")] +#[serial] +async fn test_replace_succeeds_on_testnet() { + let is_public_network = false; + test_replace_succeeds_on_network(is_public_network).await +} + +async fn test_replace_succeeds_on_network(is_public_network: bool) { test_with_vault( + is_public_network, |client, old_vault_wallet, new_vault_wallet, oracle_agent, old_vault_id, old_vault_provider| async move { - let (new_vault_id, new_vault_provider) = - create_vault(client.clone(), AccountKeyring::Eve, DEFAULT_WRAPPED_CURRENCY).await; + let (new_vault_id, new_vault_provider) = create_vault( + client.clone(), + AccountKeyring::Eve, + default_wrapped_currency(is_public_network), + ) + .await; let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; @@ -227,19 +259,28 @@ async fn test_replace_succeeds() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn test_withdraw_replace_succeeds() { + let is_public_network = false; test_with_vault( + is_public_network, |client, _vault_wallet, user_wallet, oracle_agent, old_vault_id, old_vault_provider| async move { - let (new_vault_id, new_vault_provider) = - create_vault(client.clone(), AccountKeyring::Eve, DEFAULT_WRAPPED_CURRENCY).await; + let (new_vault_id, new_vault_provider) = create_vault( + client.clone(), + AccountKeyring::Eve, + default_wrapped_currency(is_public_network), + ) + .await; let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; let issue_amount = upscaled_compatible_amount(100); - let vault_collateral = register_vault_with_default_destination(vec![ - (&old_vault_provider, &old_vault_id, issue_amount), - (&new_vault_provider, &new_vault_id, issue_amount), - ]) + let vault_collateral = register_vault_with_default_destination( + vec![ + (&old_vault_provider, &old_vault_id, issue_amount), + (&new_vault_provider, &new_vault_id, issue_amount), + ], + is_public_network, + ) .await; assert_issue( @@ -279,7 +320,7 @@ async fn test_withdraw_replace_succeeds() { &old_vault_id, 1u32.into(), vault_collateral, - address + address, ) .await .is_err()); @@ -294,15 +335,21 @@ async fn test_cancel_scheduler_succeeds() { // tests cancellation of issue, redeem and replace. // issue and replace cancellation is tested through the vault's cancellation service. // cancel_redeem is called manually + let is_public_network = false; test_with_vault( + is_public_network, |client, vault_wallet, user_wallet, oracle_agent, old_vault_id, old_vault_provider| async move { let parachain_rpc = setup_provider(client.clone(), AccountKeyring::Bob).await; let root_provider = setup_provider(client.clone(), AccountKeyring::Alice).await; let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; - let (new_vault_id, new_vault_provider) = - create_vault(client.clone(), AccountKeyring::Eve, DEFAULT_WRAPPED_CURRENCY).await; + let (new_vault_id, new_vault_provider) = create_vault( + client.clone(), + AccountKeyring::Eve, + default_wrapped_currency(is_public_network), + ) + .await; let issue_amount = upscaled_compatible_amount(200); @@ -468,97 +515,200 @@ async fn test_cancel_scheduler_succeeds() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn test_issue_cancel_succeeds() { - test_with_vault(|client, vault_wallet, _user_wallet, _, vault_id, vault_provider| async move { - let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; - let issue_set = Arc::new(RwLock::new(IssueRequestsMap::new())); - let memos_to_issue_ids = Arc::new(RwLock::new(IssueIdLookup::new())); + test_with_vault( + false, + |client, vault_wallet, _user_wallet, _, vault_id, vault_provider| async move { + let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; + let issue_set = Arc::new(RwLock::new(IssueRequestsMap::new())); + let memos_to_issue_ids = Arc::new(RwLock::new(IssueIdLookup::new())); - let issue_filter = - IssueFilter::new(&vault_wallet.read().await.public_key()).expect("Invalid filter"); + let issue_filter = + IssueFilter::new(&vault_wallet.read().await.public_key()).expect("Invalid filter"); - let issue_amount = upscaled_compatible_amount(100); - let vault_collateral = get_required_vault_collateral_for_issue( - &vault_provider, - issue_amount, - vault_id.wrapped_currency(), - vault_id.collateral_currency(), - ) - .await; + let issue_amount = upscaled_compatible_amount(100); + let vault_collateral = get_required_vault_collateral_for_issue( + &vault_provider, + issue_amount, + vault_id.wrapped_currency(), + vault_id.collateral_currency(), + ) + .await; - assert_ok!( - vault_provider - .register_vault_with_public_key( - &vault_id, - vault_collateral, - vault_wallet.read().await.public_key_raw(), - ) + assert_ok!( + vault_provider + .register_vault_with_public_key( + &vault_id, + vault_collateral, + vault_wallet.read().await.public_key_raw(), + ) + .await + ); + + let fut_user = async { + // The account of the 'user_provider' is used to request a new issue that + // will be canceled in the next step + let issue = user_provider.request_issue(issue_amount, &vault_id).await.unwrap(); + // First await the event that the issue has been requested + assert_event::(TIMEOUT, user_provider.clone(), |_| true) + .await; + assert_eq!(issue_set.read().await.len(), 1); + assert_eq!(memos_to_issue_ids.read().await.len(), 1); + + match user_provider.cancel_issue(issue.issue_id).await { + Ok(_) => { + assert!(true); + }, + Err(e) => { + panic!("Failed to Cancel Issue: {:?}", e); + }, + } + + // wait for the issue to be canceled + assert_event::(TIMEOUT, user_provider.clone(), |_| true).await; + assert!(issue_set.read().await.is_empty()); + assert!(memos_to_issue_ids.read().await.is_empty()); + }; + + let slot_tx_env_map = Arc::new(RwLock::new(HashMap::new())); + + let (issue_event_tx, _issue_event_rx) = mpsc::channel::(16); + let wallet_read = vault_wallet.read().await; + let service = join3( + vault::service::listen_for_new_transactions( + wallet_read.public_key(), + wallet_read.is_public_network(), + slot_tx_env_map.clone(), + issue_set.clone(), + memos_to_issue_ids.clone(), + issue_filter, + ), + vault::service::listen_for_issue_requests( + vault_provider.clone(), + wallet_read.public_key(), + issue_event_tx, + issue_set.clone(), + memos_to_issue_ids.clone(), + ), + vault::service::listen_for_issue_cancels( + vault_provider.clone(), + issue_set.clone(), + memos_to_issue_ids.clone(), + ), + ); + + test_service(service, fut_user).await; + }, + ) + .await; +} + +#[tokio::test(flavor = "multi_thread")] +#[serial] +async fn test_issue_execution_succeeds_from_archive() { + let is_public_network = true; + test_with_vault( + is_public_network, + |client, _vault_wallet, user_wallet, _oracle_agent, vault_id, vault_provider| async move { + let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; + + let public_key = default_destination_as_binary(is_public_network); + + let issue_amount = upscaled_compatible_amount(100); + let vault_collateral = get_required_vault_collateral_for_issue( + &vault_provider, + issue_amount, + vault_id.wrapped_currency(), + vault_id.collateral_currency(), + ) + .await; + + assert_ok!( + vault_provider + .register_vault_with_public_key(&vault_id, vault_collateral, public_key) + .await + ); + + // This call returns a RequestIssueEvent, not the IssueRequest from primitives + let issue = user_provider + .request_issue(issue_amount, &vault_id) .await - ); + .expect("Requesting issue failed"); - let fut_user = async { - // The account of the 'user_provider' is used to request a new issue that - // will be canceled in the next step - let issue = user_provider.request_issue(issue_amount, &vault_id).await.unwrap(); - // First await the event that the issue has been requested - assert_event::(TIMEOUT, user_provider.clone(), |_| true).await; - assert_eq!(issue_set.read().await.len(), 1); - assert_eq!(memos_to_issue_ids.read().await.len(), 1); - - match user_provider.cancel_issue(issue.issue_id).await { - Ok(_) => { - assert!(true); - }, - Err(e) => { - panic!("Failed to Cancel Issue: {:?}", e); - }, - } + // Send a payment to the destination of the issue request (ie the targeted vault's + // stellar account) + let stroop_amount = primitives::BalanceConversion::lookup(issue.amount + issue.fee) + .expect("Conversion should not fail"); + let destination_public_key = PublicKey::from_binary(issue.vault_stellar_public_key); + let stellar_asset = + primitives::AssetConversion::lookup(issue.asset).expect("Asset not found"); - // wait for the issue to be canceled - assert_event::(TIMEOUT, user_provider.clone(), |_| true).await; - assert!(issue_set.read().await.is_empty()); - assert!(memos_to_issue_ids.read().await.is_empty()); - }; + let transaction_response = send_payment_to_address( + user_wallet, + destination_public_key, + stellar_asset, + stroop_amount.try_into().unwrap(), + issue.issue_id.0, + false, + ) + .await + .expect("Sending payment failed"); - let slot_tx_env_map = Arc::new(RwLock::new(HashMap::new())); + assert!(transaction_response.successful); - let (issue_event_tx, _issue_event_rx) = mpsc::channel::(16); - let wallet_read = vault_wallet.read().await; - let service = join3( - vault::service::listen_for_new_transactions( - wallet_read.public_key(), - wallet_read.is_public_network(), - slot_tx_env_map.clone(), - issue_set.clone(), - memos_to_issue_ids.clone(), - issue_filter, - ), - vault::service::listen_for_issue_requests( - vault_provider.clone(), - wallet_read.public_key(), - issue_event_tx, - issue_set.clone(), - memos_to_issue_ids.clone(), - ), - vault::service::listen_for_issue_cancels( - vault_provider.clone(), - issue_set.clone(), - memos_to_issue_ids.clone(), - ), - ); + let slot = transaction_response.ledger as u64; - test_service(service, fut_user).await; - }) + // We sleep here in order to wait for the fallback to the archive to be necessary + sleep(Duration::from_secs(5 * 60)).await; + + let shutdown_tx = ShutdownSender::new(); + let stellar_config = random_stellar_relay_config(is_public_network); + let vault_stellar_secret = get_test_secret_key(is_public_network); + // Create new oracle agent with the same configuration as the previous one + let oracle_agent = + start_oracle_agent(stellar_config.clone(), &vault_stellar_secret, shutdown_tx) + .await + .expect("failed to start agent"); + let oracle_agent = Arc::new(oracle_agent); + + // Loop pending proofs until it is ready + let proof = oracle_agent.get_proof(slot).await.expect("Proof should be available"); + let tx_envelope_xdr_encoded = transaction_response.envelope_xdr; + let (envelopes_xdr_encoded, tx_set_xdr_encoded) = proof.encode(); + + join( + assert_event::(TIMEOUT, user_provider.clone(), |x| { + if &x.who == user_provider.get_account_id() { + assert_eq!(x.amount, issue.amount - issue.fee); + true + } else { + false + } + }), + user_provider + .execute_issue( + issue.issue_id, + &tx_envelope_xdr_encoded, + envelopes_xdr_encoded.as_bytes(), + tx_set_xdr_encoded.as_bytes(), + ) + .map(Result::unwrap), + ) + .await; + }, + ) .await; } #[tokio::test(flavor = "multi_thread")] #[serial] async fn test_issue_overpayment_succeeds() { + let is_public_network = false; test_with_vault( + is_public_network, |client, _vault_wallet, user_wallet, oracle_agent, vault_id, vault_provider| async move { let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; - let public_key = default_destination_as_binary(); + let public_key = default_destination_as_binary(is_public_network); let issue_amount = upscaled_compatible_amount(100); let over_payment_factor = 3; @@ -642,8 +792,21 @@ async fn test_issue_overpayment_succeeds() { #[tokio::test(flavor = "multi_thread")] #[serial] -async fn test_automatic_issue_execution_succeeds() { +async fn test_automatic_issue_execution_succeeds_on_mainnet() { + let is_public_network = true; + test_automatic_issue_execution_succeeds_on_network(is_public_network).await; +} + +#[tokio::test(flavor = "multi_thread")] +#[serial] +async fn test_automatic_issue_execution_succeeds_on_testnet() { + let is_public_network = false; + test_automatic_issue_execution_succeeds_on_network(is_public_network).await; +} + +async fn test_automatic_issue_execution_succeeds_on_network(is_public_network: bool) { test_with_vault( + is_public_network, |client, vault_wallet, user_wallet, oracle_agent, vault_id, vault_provider| async move { let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; @@ -750,14 +913,16 @@ async fn test_automatic_issue_execution_succeeds() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn test_automatic_issue_execution_succeeds_for_other_vault() { + let is_public_network = false; test_with_vault( + is_public_network, |client, vault_wallet, user_wallet, oracle_agent, vault1_id, vault1_provider| async move { let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; let vault2_provider = setup_provider(client.clone(), AccountKeyring::Eve).await; let vault2_id = VaultId::new( AccountKeyring::Eve.into(), DEFAULT_TESTING_CURRENCY, - DEFAULT_WRAPPED_CURRENCY, + default_wrapped_currency(is_public_network), ); let issue_amount = upscaled_compatible_amount(100); @@ -858,7 +1023,7 @@ async fn test_automatic_issue_execution_succeeds_for_other_vault() { let service = join4( vault::service::listen_for_new_transactions( vault_account_public_key.clone(), - CFG.is_public_network(), + is_public_network, slot_tx_env_map.clone(), issue_set_arc.clone(), memos_to_issue_ids.clone(), @@ -894,7 +1059,9 @@ async fn test_automatic_issue_execution_succeeds_for_other_vault() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn test_execute_open_requests_succeeds() { + let is_public_network = false; test_with_vault( + is_public_network, |client, vault_wallet, user_wallet, oracle_agent, vault_id, vault_provider| async move { let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; @@ -1007,7 +1174,9 @@ async fn test_execute_open_requests_succeeds() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn test_off_chain_liquidation() { + let is_public_network = false; test_with_vault( + is_public_network, |client, vault_wallet, user_wallet, oracle_agent, vault_id, vault_provider| async move { // Bob is set as an authorized oracle in the chain_spec let authorized_oracle_provider = @@ -1029,7 +1198,7 @@ async fn test_off_chain_liquidation() { .register_vault_with_public_key( &vault_id, vault_collateral, - default_destination_as_binary() + default_destination_as_binary(is_public_network) ) .await ); @@ -1060,14 +1229,15 @@ async fn test_off_chain_liquidation() { #[tokio::test(flavor = "multi_thread")] async fn test_shutdown() { - test_with(|client, vault_wallet, _| async move { + let is_public_network = false; + test_with(false, |client, vault_wallet, _| async move { let sudo_provider = setup_provider(client.clone(), AccountKeyring::Alice).await; let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; let sudo_vault_id = VaultId::new( AccountKeyring::Alice.into(), DEFAULT_TESTING_CURRENCY, - DEFAULT_WRAPPED_CURRENCY, + default_wrapped_currency(is_public_network), ); // register a vault.. @@ -1119,49 +1289,53 @@ async fn test_shutdown() { #[tokio::test(flavor = "multi_thread")] #[serial] async fn test_requests_with_incompatible_amounts_fail() { - test_with_vault(|client, vault_wallet, _user_wallet, _, vault_id, vault_provider| async move { - let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; + test_with_vault( + false, + |client, vault_wallet, _user_wallet, _, vault_id, vault_provider| async move { + let user_provider = setup_provider(client.clone(), AccountKeyring::Dave).await; - // We define an incompatible amount - let incompatible_amount = upscaled_compatible_amount(100) + 1; - let vault_collateral = get_required_vault_collateral_for_issue( - &vault_provider, - incompatible_amount, - vault_id.wrapped_currency(), - vault_id.collateral_currency(), - ) - .await; + // We define an incompatible amount + let incompatible_amount = upscaled_compatible_amount(100) + 1; + let vault_collateral = get_required_vault_collateral_for_issue( + &vault_provider, + incompatible_amount, + vault_id.wrapped_currency(), + vault_id.collateral_currency(), + ) + .await; - let wallet_read = vault_wallet.read().await; - let address = wallet_read.public_key_raw(); - assert_ok!( - vault_provider - .register_vault_with_public_key( - &vault_id, - vault_collateral, - wallet_read.public_key_raw() - ) - .await - ); - drop(wallet_read); - - // We try to request an issue with an incompatible amount - let result = user_provider.request_issue(incompatible_amount, &vault_id).await; - assert!(result.is_err()); - let error = result.unwrap_err(); - assert!(error.is_module_err("Currency", "IncompatibleAmount")); - - // We try to request a redeem with an incompatible amount - let result = user_provider.request_redeem(incompatible_amount, address, &vault_id).await; - assert!(result.is_err()); - let error = result.unwrap_err(); - assert!(error.is_module_err("Currency", "IncompatibleAmount")); - - // We try to request a replace with an incompatible amount - let result = vault_provider.request_replace(&vault_id, incompatible_amount).await; - assert!(result.is_err()); - let error = result.unwrap_err(); - assert!(error.is_module_err("Currency", "IncompatibleAmount")); - }) + let wallet_read = vault_wallet.read().await; + let address = wallet_read.public_key_raw(); + assert_ok!( + vault_provider + .register_vault_with_public_key( + &vault_id, + vault_collateral, + wallet_read.public_key_raw() + ) + .await + ); + drop(wallet_read); + + // We try to request an issue with an incompatible amount + let result = user_provider.request_issue(incompatible_amount, &vault_id).await; + assert!(result.is_err()); + let error = result.unwrap_err(); + assert!(error.is_module_err("Currency", "IncompatibleAmount")); + + // We try to request a redeem with an incompatible amount + let result = + user_provider.request_redeem(incompatible_amount, address, &vault_id).await; + assert!(result.is_err()); + let error = result.unwrap_err(); + assert!(error.is_module_err("Currency", "IncompatibleAmount")); + + // We try to request a replace with an incompatible amount + let result = vault_provider.request_replace(&vault_id, incompatible_amount).await; + assert!(result.is_err()); + let error = result.unwrap_err(); + assert!(error.is_module_err("Currency", "IncompatibleAmount")); + }, + ) .await; } diff --git a/clients/wallet/src/horizon/horizon.rs b/clients/wallet/src/horizon/horizon.rs index 528b56fa1..c275dc69c 100644 --- a/clients/wallet/src/horizon/horizon.rs +++ b/clients/wallet/src/horizon/horizon.rs @@ -30,6 +30,7 @@ use crate::{ const POLL_INTERVAL: u64 = 5000; /// See [Stellar doc](https://developers.stellar.org/api/introduction/pagination/page-arguments) pub const DEFAULT_PAGE_SIZE: u8 = 200; +const BASE_BACKOFF_DELAY_IN_SECS: u64 = 10; pub fn horizon_url(is_public_network: bool, is_need_fallback: bool) -> &'static str { if is_public_network { @@ -136,7 +137,7 @@ impl HorizonClient for reqwest::Client { let params = [("tx", &transaction_xdr)]; let mut server_error_count = 0; - let mut exponent_counter = 1; + let mut backoff_delay_counter = 1; loop { let need_fallback = if server_error_count == max_retries { @@ -166,15 +167,15 @@ impl HorizonClient for reqwest::Client { // let's wait awhile before resubmitting. tracing::warn!( - "submitting transaction with seq no: {seq_no:?} failed with {e:?}" + "submitting transaction to {base_url} with seq no: {seq_no:?} failed with {e:?}" ); - // exponentially sleep before retrying again - let sleep_duration = 2u64.pow(exponent_counter); + // Calculate linear backoff delay + let sleep_duration = backoff_delay_counter * BASE_BACKOFF_DELAY_IN_SECS; sleep(Duration::from_secs(sleep_duration)).await; // retry/resubmit again if sleep_duration < u64::from(max_backoff_delay_in_secs) { - exponent_counter += 1; + backoff_delay_counter += 1; } continue }, diff --git a/clients/wallet/src/stellar_wallet.rs b/clients/wallet/src/stellar_wallet.rs index 7c58b26a8..45b656b90 100644 --- a/clients/wallet/src/stellar_wallet.rs +++ b/clients/wallet/src/stellar_wallet.rs @@ -61,7 +61,7 @@ impl StellarWallet { /// error, this will be the default. pub(crate) const DEFAULT_MAX_RETRY_ATTEMPTS_BEFORE_FALLBACK: u8 = 3; - pub(crate) const DEFAULT_MAX_BACKOFF_DELAY_IN_SECS: u16 = 600; + pub(crate) const DEFAULT_MAX_BACKOFF_DELAY_IN_SECS: u16 = 60; } impl StellarWallet { @@ -118,10 +118,7 @@ impl StellarWallet { } pub fn with_max_backoff_delay(mut self, max_backoff_delay_in_secs: u16) -> Self { - // a number more than the default max would be too large - if max_backoff_delay_in_secs < Self::DEFAULT_MAX_BACKOFF_DELAY_IN_SECS { - self.max_backoff_delay = max_backoff_delay_in_secs; - } + self.max_backoff_delay = max_backoff_delay_in_secs; self } @@ -430,13 +427,8 @@ mod test { assert_eq!(wallet.max_backoff_delay(), StellarWallet::DEFAULT_MAX_BACKOFF_DELAY_IN_SECS); - // too big backoff delay - let expected_max_backoff_delay = 800; + let expected_max_backoff_delay = StellarWallet::DEFAULT_MAX_BACKOFF_DELAY_IN_SECS / 2; let new_wallet = wallet.with_max_backoff_delay(expected_max_backoff_delay); - assert_ne!(new_wallet.max_backoff_delay(), expected_max_backoff_delay); - - let expected_max_backoff_delay = 300; - let new_wallet = new_wallet.with_max_backoff_delay(expected_max_backoff_delay); assert_eq!(new_wallet.max_backoff_delay(), expected_max_backoff_delay); new_wallet.remove_cache_dir(); diff --git a/clients/wallet/src/types.rs b/clients/wallet/src/types.rs index 3747ed8ce..1f7e7a2ed 100644 --- a/clients/wallet/src/types.rs +++ b/clients/wallet/src/types.rs @@ -36,7 +36,7 @@ impl fmt::Display for FeeAttribute { impl Default for FeeAttribute { fn default() -> Self { - FeeAttribute::p90 + FeeAttribute::p95 } } diff --git a/pallets/issue/src/lib.rs b/pallets/issue/src/lib.rs index 4e51be3f5..e4d3dbe11 100644 --- a/pallets/issue/src/lib.rs +++ b/pallets/issue/src/lib.rs @@ -818,9 +818,10 @@ impl Pallet { ) .map_err(|e| { log::error!( - "failed to validate transaction of issue id: {} with transaction envelope: {transaction_envelope:?}", - hex::encode(issue_id.as_bytes()) - ); + "failed to validate transaction of issue id: {} with transaction envelope: {transaction_envelope:?}", + hex::encode(issue_id.as_bytes()) + ); + log::error!("error: {:?}", e); e })?; diff --git a/pallets/stellar-relay/src/lib.rs b/pallets/stellar-relay/src/lib.rs index e68beb609..a834d2836 100644 --- a/pallets/stellar-relay/src/lib.rs +++ b/pallets/stellar-relay/src/lib.rs @@ -175,8 +175,8 @@ pub mod pallet { }; let organization_satoshipay = OrganizationOf:: { name: create_bounded_vec("SatoshiPay"), id: 1.into() }; - let organization_coinqvest = - OrganizationOf:: { name: create_bounded_vec("Coinqvest"), id: 2.into() }; + let organization_whalestack = + OrganizationOf:: { name: create_bounded_vec("Whalestack"), id: 2.into() }; let organization_blockdaemon = OrganizationOf:: { name: create_bounded_vec("Blockdaemon"), id: 3.into() }; let organization_lobstr = @@ -235,25 +235,25 @@ pub mod pallet { }, // Coinqvest validators ValidatorOf:: { - name: create_bounded_vec("$coinqvest-germany"), + name: create_bounded_vec("$whalestack-germany"), public_key: create_bounded_vec( "GD6SZQV3WEJUH352NTVLKEV2JM2RH266VPEM7EH5QLLI7ZZAALMLNUVN", ), - organization_id: organization_coinqvest.id, + organization_id: organization_whalestack.id, }, ValidatorOf:: { - name: create_bounded_vec("$coinqvest-finland"), + name: create_bounded_vec("$whalestack-finland"), public_key: create_bounded_vec( "GADLA6BJK6VK33EM2IDQM37L5KGVCY5MSHSHVJA4SCNGNUIEOTCR6J5T", ), - organization_id: organization_coinqvest.id, + organization_id: organization_whalestack.id, }, ValidatorOf:: { - name: create_bounded_vec("$coinqvest-hongkong"), + name: create_bounded_vec("$whalestack-hongkong"), public_key: create_bounded_vec( "GAZ437J46SCFPZEDLVGDMKZPLFO77XJ4QVAURSJVRZK2T5S7XUFHXI2Z", ), - organization_id: organization_coinqvest.id, + organization_id: organization_whalestack.id, }, // Blockdaemon validators ValidatorOf:: { @@ -363,7 +363,7 @@ pub mod pallet { organization_satoshipay, organization_sdf, organization_franklin_templeton, - organization_coinqvest, + organization_whalestack, organization_blockdaemon, organization_lobstr, organization_public_node, diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml deleted file mode 100644 index cc9ade32f..000000000 --- a/rpc/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -authors = ["Pendulum"] -edition = "2018" -name = "spacewalk-rpc" -version = "1.0.4" - -[dependencies] -jsonrpc-core = "18.0.0" -jsonrpsee = { version = "0.16.0", features = ["server", "macros"] } - -# Parachain dependencies -primitives = { package = "spacewalk-primitives", path = "../primitives" } - -module-issue-rpc = { path = "../pallets/issue/rpc" } -module-redeem-rpc = { path = "../pallets/redeem/rpc" } -module-replace-rpc = { path = "../pallets/replace/rpc" } -module-oracle-rpc = { path = "../pallets/oracle/rpc" } -module-vault-registry-rpc = { path = "../pallets/vault-registry/rpc" } - -# Substrate dependencies -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -sc-consensus-manual-seal = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } - -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } diff --git a/testchain/node/Cargo.toml b/testchain/node/Cargo.toml index 40c47f7b1..dade93384 100644 --- a/testchain/node/Cargo.toml +++ b/testchain/node/Cargo.toml @@ -25,8 +25,8 @@ futures = "0.3.15" # Parachain dependencies primitives = { package = "spacewalk-primitives", path = "../../primitives" } -spacewalk-rpc = { path = "../../rpc" } -spacewalk-runtime = { package = "spacewalk-runtime-standalone", path = "../runtime" } +spacewalk-runtime-testnet = { package = "spacewalk-runtime-standalone-testnet", path = "../runtime/testnet" } +spacewalk-runtime-mainnet = { package = "spacewalk-runtime-standalone-mainnet", path = "../runtime/mainnet" } # Substrate dependencies sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } @@ -67,10 +67,30 @@ pallet-transaction-payment = { default-features = false, git = "https://github.c substrate-stellar-sdk = { git = "https://github.com/pendulum-chain/substrate-stellar-sdk", branch = "polkadot-v0.9.40" } +# RPC dependencies +jsonrpc-core = "18.0.0" +jsonrpsee = { version = "0.16.0", features = ["server", "macros"] } + +# Parachain dependencies +module-issue-rpc = { path = "../../pallets/issue/rpc" } +module-redeem-rpc = { path = "../../pallets/redeem/rpc" } +module-replace-rpc = { path = "../../pallets/replace/rpc" } +module-oracle-rpc = { path = "../../pallets/oracle/rpc" } +module-vault-registry-rpc = { path = "../../pallets/vault-registry/rpc" } + +# Substrate dependencies +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } +sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } +sp-blockchain= { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } + [features] default = [] runtime-benchmarks = [ - "spacewalk-runtime/runtime-benchmarks", + "spacewalk-runtime-testnet/runtime-benchmarks", + "spacewalk-runtime-mainnet/runtime-benchmarks", "frame-benchmarking/runtime-benchmarks", "frame-benchmarking-cli/runtime-benchmarks", ] diff --git a/testchain/node/src/benchmarking.rs b/testchain/node/src/benchmarking.rs index d0f092e99..9387549df 100644 --- a/testchain/node/src/benchmarking.rs +++ b/testchain/node/src/benchmarking.rs @@ -29,8 +29,9 @@ use sp_inherents::{InherentData, InherentDataProvider}; use sp_keyring::Sr25519Keyring; use sp_runtime::{OpaqueExtrinsic, SaturatedConversion}; use spacewalk_runtime::{AccountId, Balance, BalancesCall, SystemCall}; +use spacewalk_runtime_testnet as spacewalk_runtime; -use crate::service::FullClient; +use crate::service::FullTestnetClient as FullClient; use spacewalk_runtime as runtime; diff --git a/testchain/node/src/chain_spec.rs b/testchain/node/src/chain_spec.rs index 9d8590deb..3870384be 100644 --- a/testchain/node/src/chain_spec.rs +++ b/testchain/node/src/chain_spec.rs @@ -1,22 +1,21 @@ -use spacewalk_runtime::{AssetId, DiaOracleModuleConfig}; -use std::{convert::TryFrom, str::FromStr}; +use spacewalk_runtime_testnet::{AssetId, DiaOracleModuleConfig}; +use std::convert::TryFrom; use frame_support::BoundedVec; -use hex_literal::hex; use sc_service::ChainType; use sp_arithmetic::{FixedPointNumber, FixedU128}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_consensus_grandpa::AuthorityId as GrandpaId; -use sp_core::{crypto::UncheckedInto, sr25519, Pair, Public}; +use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; use primitives::{oracle::Key, CurrencyId, VaultCurrencyPair}; use serde_json::{map::Map, Value}; -use spacewalk_runtime::{ +use spacewalk_runtime_testnet::{ AccountId, AuraConfig, BalancesConfig, FeeConfig, FieldLength, GenesisConfig, GrandpaConfig, IssueConfig, NominationConfig, OracleConfig, Organization, RedeemConfig, ReplaceConfig, SecurityConfig, Signature, StatusCode, StellarRelayConfig, SudoConfig, SystemConfig, - TokensConfig, Validator, VaultRegistryConfig, DAYS, WASM_BINARY, + TokensConfig, Validator, VaultRegistryConfig, DAYS, }; // The URL for the telemetry server. @@ -32,15 +31,16 @@ pub fn get_from_seed(seed: &str) -> ::Pu } // For mainnet USDC issued by centre.io -// const WRAPPED_CURRENCY_ID: CurrencyId = CurrencyId::AlphaNum4 { -// code: *b"USDC", -// issuer: [ -// 59, 153, 17, 56, 14, 254, 152, 139, 160, 168, 144, 14, 177, 207, 228, 79, 54, 111, 125, -// 190, 148, 107, 237, 7, 114, 64, 247, 246, 36, 223, 21, 197, -// ], -// }; +const WRAPPED_CURRENCY_ID_STELLAR_MAINNET: CurrencyId = CurrencyId::AlphaNum4( + *b"USDC", + [ + 59, 153, 17, 56, 14, 254, 152, 139, 160, 168, 144, 14, 177, 207, 228, 79, 54, 111, 125, + 190, 148, 107, 237, 7, 114, 64, 247, 246, 36, 223, 21, 197, + ], +); + // For Testnet USDC issued by -const WRAPPED_CURRENCY_ID: CurrencyId = CurrencyId::AlphaNum4( +const WRAPPED_CURRENCY_ID_STELLAR_TESTNET: CurrencyId = CurrencyId::AlphaNum4( *b"USDC", [ 20, 209, 150, 49, 176, 55, 23, 217, 171, 154, 54, 110, 16, 50, 30, 226, 102, 231, 46, 199, @@ -61,10 +61,6 @@ pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) { (get_from_seed::(s), get_from_seed::(s)) } -fn get_account_id_from_string(account_id: &str) -> AccountId { - AccountId::from_str(account_id).expect("account id is not valid") -} - type AccountPublic = ::Signer; /// Helper function to generate an account ID from seed @@ -77,19 +73,19 @@ where fn get_properties() -> Map { let mut properties = Map::new(); - properties.insert("ss58Format".into(), spacewalk_runtime::SS58Prefix::get().into()); + properties.insert("ss58Format".into(), spacewalk_runtime_testnet::SS58Prefix::get().into()); properties } -pub fn local_config() -> ChainSpec { +pub fn mainnet_config() -> ChainSpec { ChainSpec::from_genesis( "spacewalk", - "local_testnet", - ChainType::Local, + "dev_mainnet", + ChainType::Development, move || { - testnet_genesis( + genesis( get_account_id_from_seed::("Alice"), - vec![], + vec![authority_keys_from_seed("Alice")], vec![ get_account_id_from_seed::("Alice"), get_account_id_from_seed::("Bob"), @@ -106,67 +102,7 @@ pub fn local_config() -> ChainSpec { ], vec![get_account_id_from_seed::("Bob")], false, - ) - }, - vec![], - None, - None, - None, - Some(get_properties()), - None, - ) -} - -pub fn beta_testnet_config() -> ChainSpec { - ChainSpec::from_genesis( - "spacewalk", - "beta_testnet", - ChainType::Live, - move || { - testnet_genesis( - get_account_id_from_string("5HeVGqvfpabwFqzV1DhiQmjaLQiFcTSmq2sH6f7atsXkgvtt"), - vec![ - ( - // 5DJ3wbdicFSFFudXndYBuvZKjucTsyxtJX5WPzQM8HysSkFY - hex!["366a092a27b4b28199a588b0155a2c9f3f0513d92481de4ee2138273926fa91c"] - .unchecked_into(), - hex!["dce82040dc0a90843897aee1cc1a96c205fe7c1165b8f46635c2547ed15a3013"] - .unchecked_into(), - ), - ( - // 5HW7ApFamN6ovtDkFyj67tRLRhp8B2kVNjureRUWWYhkTg9j - hex!["f08cc7cf45f88e6dbe312a63f6ce639061834b4208415b235f77a67b51435f63"] - .unchecked_into(), - hex!["5b4651cf045ddf55f0df7bfbb9bb4c45bbeb3c536c6ce4a98275781b8f0f0754"] - .unchecked_into(), - ), - ( - // 5FNbq8zGPZtinsfgyD4w2G3BMh75H3r2Qg3uKudTZkJtRru6 - hex!["925ad4bdf35945bea91baeb5419a7ffa07002c6a85ba334adfa7cb5b05623c1b"] - .unchecked_into(), - hex!["8de3db7b51864804d2dd5c5905d571aa34d7161537d5a0045755b72d1ac2062e"] - .unchecked_into(), - ), - ], - vec![ - // root key - get_account_id_from_string("5HeVGqvfpabwFqzV1DhiQmjaLQiFcTSmq2sH6f7atsXkgvtt"), - // faucet - get_account_id_from_string("5FHy3cvyToZ4ConPXhi43rycAcGYw2R2a8cCjfVMfyuS1Ywg"), - // vaults - get_account_id_from_string("5F7Q9FqnGwJmjLtsFGymHZXPEx2dWRVE7NW4Sw2jzEhUB5WQ"), - get_account_id_from_string("5CJncqjWDkYv4P6nccZHGh8JVoEBXvharMqVpkpJedoYNu4A"), - get_account_id_from_string("5GpnEWKTWv7xiQtDFi9Rku7DrvgHj4oqMDev4qBQhfwQE8nx"), - get_account_id_from_string("5DttG269R1NTBDWcghYxa9NmV2wHxXpTe4U8pu4jK3LCE9zi"), - // relayers - get_account_id_from_string("5DNzULM1UJXDM7NUgDL4i8Hrhe9e3vZkB3ByM1eEXMGAs4Bv"), - get_account_id_from_string("5GEXRnnv8Qz9rEwMs4TfvHme48HQvVTEDHJECCvKPzFB4pFZ"), - // oracles - get_account_id_from_string("5H8zjSWfzMn86d1meeNrZJDj3QZSvRjKxpTfuVaZ46QJZ4qs"), - get_account_id_from_string("5FPBT2BVVaLveuvznZ9A1TUtDcbxK5yvvGcMTJxgFmhcWGwj"), - ], - vec![get_account_id_from_seed::("Bob")], - false, + true, ) }, Vec::new(), @@ -178,13 +114,13 @@ pub fn beta_testnet_config() -> ChainSpec { ) } -pub fn development_config() -> ChainSpec { +pub fn testnet_config() -> ChainSpec { ChainSpec::from_genesis( "spacewalk", "dev_testnet", ChainType::Development, move || { - testnet_genesis( + genesis( get_account_id_from_seed::("Alice"), vec![authority_keys_from_seed("Alice")], vec![ @@ -203,6 +139,7 @@ pub fn development_config() -> ChainSpec { ], vec![get_account_id_from_seed::("Bob")], false, + false, ) }, Vec::new(), @@ -214,8 +151,13 @@ pub fn development_config() -> ChainSpec { ) } -fn default_pair(currency_id: CurrencyId) -> VaultCurrencyPair { - VaultCurrencyPair { collateral: currency_id, wrapped: WRAPPED_CURRENCY_ID } +fn default_pair(currency_id: CurrencyId, is_public_network: bool) -> VaultCurrencyPair { + let wrapped = if is_public_network { + WRAPPED_CURRENCY_ID_STELLAR_MAINNET + } else { + WRAPPED_CURRENCY_ID_STELLAR_TESTNET + }; + VaultCurrencyPair { collateral: currency_id, wrapped } } // Used to create bounded vecs for genesis config @@ -227,43 +169,30 @@ fn create_bounded_vec(input: &str) -> BoundedVec { bounded_vec } -fn testnet_genesis( +fn genesis( root_key: AccountId, initial_authorities: Vec<(AuraId, GrandpaId)>, endowed_accounts: Vec, authorized_oracles: Vec, start_shutdown: bool, + is_public_network: bool, ) -> GenesisConfig { - // Testnet organization - let organization_testnet_sdf = Organization { name: create_bounded_vec("sdftest"), id: 1u128 }; - // Testnet validators - let validators = vec![ - Validator { - name: create_bounded_vec("$sdftest1"), - public_key: create_bounded_vec( - "GDKXE2OZMJIPOSLNA6N6F2BVCI3O777I2OOC4BV7VOYUEHYX7RTRYA7Y", - ), - organization_id: organization_testnet_sdf.id, - }, - Validator { - name: create_bounded_vec("$sdftest2"), - public_key: create_bounded_vec( - "GCUCJTIYXSOXKBSNFGNFWW5MUQ54HKRPGJUTQFJ5RQXZXNOLNXYDHRAP", - ), - organization_id: organization_testnet_sdf.id, - }, - Validator { - name: create_bounded_vec("$sdftest3"), - public_key: create_bounded_vec( - "GC2V2EFSXN6SQTWVYA5EPJPBWWIMSD2XQNKUOHGEKB535AQE2I6IXV2Z", - ), - organization_id: organization_testnet_sdf.id, - }, - ]; - let organizations = vec![organization_testnet_sdf]; + let default_wrapped_currency = if is_public_network { + WRAPPED_CURRENCY_ID_STELLAR_MAINNET + } else { + WRAPPED_CURRENCY_ID_STELLAR_TESTNET + }; + + // It's very important that we use the correct wasm binary + let wasm_binary = if is_public_network { + spacewalk_runtime_mainnet::WASM_BINARY + } else { + spacewalk_runtime_testnet::WASM_BINARY + }; + GenesisConfig { system: SystemConfig { - code: WASM_BINARY.expect("WASM binary was not build, please build it!").to_vec(), + code: wasm_binary.expect("WASM binary was not build, please build it!").to_vec(), }, aura: AuraConfig { authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(), @@ -317,13 +246,10 @@ fn testnet_genesis( security: SecurityConfig { initial_status: if start_shutdown { StatusCode::Shutdown } else { StatusCode::Error }, }, - stellar_relay: StellarRelayConfig { - old_validators: vec![], - old_organizations: vec![], - validators, - organizations, - enactment_block_height: 0, - phantom: Default::default(), + stellar_relay: if !is_public_network { + create_stellar_testnet_config() + } else { + StellarRelayConfig::default() }, oracle: OracleConfig { max_delay: u32::MAX, @@ -331,7 +257,7 @@ fn testnet_genesis( // Changing these items means that the integration tests also have to change // because the integration tests insert dummy values for these into the oracle Key::ExchangeRate(CurrencyId::XCM(0)), - Key::ExchangeRate(WRAPPED_CURRENCY_ID), + Key::ExchangeRate(default_wrapped_currency), Key::ExchangeRate(MXN_CURRENCY_ID), ], }, @@ -344,11 +270,11 @@ fn testnet_genesis( punishment_delay: DAYS, secure_collateral_threshold: vec![ ( - default_pair(CurrencyId::XCM(0)), + default_pair(CurrencyId::XCM(0), is_public_network), FixedU128::checked_from_rational(160, 100).unwrap(), ), ( - default_pair(CurrencyId::XCM(1)), + default_pair(CurrencyId::XCM(1), is_public_network), FixedU128::checked_from_rational(160, 100).unwrap(), ), ( @@ -366,11 +292,11 @@ fn testnet_genesis( /* 150% */ premium_redeem_threshold: vec![ ( - default_pair(CurrencyId::XCM(0)), + default_pair(CurrencyId::XCM(0), is_public_network), FixedU128::checked_from_rational(140, 100).unwrap(), ), ( - default_pair(CurrencyId::XCM(1)), + default_pair(CurrencyId::XCM(1), is_public_network), FixedU128::checked_from_rational(140, 100).unwrap(), ), ( @@ -395,11 +321,11 @@ fn testnet_genesis( /* 135% */ liquidation_collateral_threshold: vec![ ( - default_pair(CurrencyId::XCM(0)), + default_pair(CurrencyId::XCM(0), is_public_network), FixedU128::checked_from_rational(120, 100).unwrap(), ), ( - default_pair(CurrencyId::XCM(1)), + default_pair(CurrencyId::XCM(1), is_public_network), FixedU128::checked_from_rational(120, 100).unwrap(), ), ( @@ -416,8 +342,8 @@ fn testnet_genesis( ], /* 110% */ system_collateral_ceiling: vec![ - (default_pair(CurrencyId::XCM(0)), 60_000 * 10u128.pow(12)), - (default_pair(CurrencyId::XCM(1)), 60_000 * 10u128.pow(12)), + (default_pair(CurrencyId::XCM(0), is_public_network), 60_000 * 10u128.pow(12)), + (default_pair(CurrencyId::XCM(1), is_public_network), 60_000 * 10u128.pow(12)), ( VaultCurrencyPair { collateral: CurrencyId::XCM(0), wrapped: MXN_CURRENCY_ID }, 60_000 * 10u128.pow(12), @@ -456,3 +382,45 @@ fn testnet_genesis( }, } } + +fn create_stellar_testnet_config() -> StellarRelayConfig { + let old_validators = Vec::new(); + let old_organizations = Vec::new(); + + // Testnet organization + let organization_testnet_sdf = Organization { name: create_bounded_vec("sdftest"), id: 1u128 }; + // Testnet validators + let validators = vec![ + Validator { + name: create_bounded_vec("$sdftest1"), + public_key: create_bounded_vec( + "GDKXE2OZMJIPOSLNA6N6F2BVCI3O777I2OOC4BV7VOYUEHYX7RTRYA7Y", + ), + organization_id: organization_testnet_sdf.id, + }, + Validator { + name: create_bounded_vec("$sdftest2"), + public_key: create_bounded_vec( + "GCUCJTIYXSOXKBSNFGNFWW5MUQ54HKRPGJUTQFJ5RQXZXNOLNXYDHRAP", + ), + organization_id: organization_testnet_sdf.id, + }, + Validator { + name: create_bounded_vec("$sdftest3"), + public_key: create_bounded_vec( + "GC2V2EFSXN6SQTWVYA5EPJPBWWIMSD2XQNKUOHGEKB535AQE2I6IXV2Z", + ), + organization_id: organization_testnet_sdf.id, + }, + ]; + let organizations = vec![organization_testnet_sdf]; + + StellarRelayConfig { + old_validators, + old_organizations, + validators, + organizations, + enactment_block_height: 0, + phantom: Default::default(), + } +} diff --git a/testchain/node/src/command.rs b/testchain/node/src/command.rs index 014da3f23..ce716860e 100644 --- a/testchain/node/src/command.rs +++ b/testchain/node/src/command.rs @@ -21,6 +21,7 @@ use sc_service::{Configuration, PartialComponents, TaskManager}; use sp_keyring::Sr25519Keyring; use spacewalk_runtime::{Block, EXISTENTIAL_DEPOSIT}; +use spacewalk_runtime_testnet as spacewalk_runtime; use crate::{ benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}, @@ -31,9 +32,9 @@ use crate::{ fn load_spec(id: &str) -> std::result::Result, String> { match id { - "" => Ok(Box::new(chain_spec::local_config())), - "dev" => Ok(Box::new(chain_spec::development_config())), - "beta" => Ok(Box::new(chain_spec::beta_testnet_config())), + "" => Ok(Box::new(chain_spec::testnet_config())), + "dev" => Ok(Box::new(chain_spec::testnet_config())), + "main" => Ok(Box::new(chain_spec::mainnet_config())), "testnet" => Ok(Box::new(chain_spec::ChainSpec::from_json_bytes( &include_bytes!("../res/testnet.json")[..], )?)), @@ -89,7 +90,7 @@ pub fn run() -> Result<()> { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, import_queue, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, @@ -97,7 +98,7 @@ pub fn run() -> Result<()> { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; Ok((cmd.run(client, config.database), task_manager)) }) }, @@ -105,7 +106,7 @@ pub fn run() -> Result<()> { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) }, @@ -113,7 +114,7 @@ pub fn run() -> Result<()> { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, import_queue, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, @@ -125,7 +126,7 @@ pub fn run() -> Result<()> { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { let PartialComponents { client, task_manager, backend, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; let aux_revert = Box::new(|client, _, blocks| { sc_consensus_grandpa::revert(client, blocks)?; Ok(()) @@ -142,7 +143,7 @@ pub fn run() -> Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { - cmd.run::(config) + cmd.run::(config) } else { Err("Benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." @@ -150,7 +151,7 @@ pub fn run() -> Result<()> { }, BenchmarkCmd::Block(cmd) => { let PartialComponents { client, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; cmd.run(client) }, #[cfg(not(feature = "runtime-benchmarks"))] @@ -161,7 +162,7 @@ pub fn run() -> Result<()> { #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => { let PartialComponents { client, backend, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; let db = backend.expose_db(); let storage = backend.expose_storage(); @@ -169,7 +170,7 @@ pub fn run() -> Result<()> { }, BenchmarkCmd::Overhead(cmd) => { let PartialComponents { client, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; let ext_builder = RemarkBuilder::new(client.clone()); cmd.run( @@ -182,7 +183,7 @@ pub fn run() -> Result<()> { }, BenchmarkCmd::Extrinsic(cmd) => { let PartialComponents { client, .. } = - spacewalk_service::new_partial(&config, false)?; + spacewalk_service::new_partial_testnet(&config, false)?; // Register the *Remark* and *TKA* builders. let ext_factory = ExtrinsicFactory(vec![ Box::new(RemarkBuilder::new(client.clone())), diff --git a/testchain/node/src/lib.rs b/testchain/node/src/lib.rs index 38e43372c..f117b8aae 100644 --- a/testchain/node/src/lib.rs +++ b/testchain/node/src/lib.rs @@ -1,2 +1,3 @@ pub mod chain_spec; +pub mod rpc; pub mod service; diff --git a/testchain/node/src/main.rs b/testchain/node/src/main.rs index 1daa8f029..426cbabb6 100644 --- a/testchain/node/src/main.rs +++ b/testchain/node/src/main.rs @@ -7,6 +7,7 @@ mod service; mod benchmarking; mod cli; mod command; +mod rpc; fn main() -> sc_cli::Result<()> { command::run() diff --git a/rpc/src/lib.rs b/testchain/node/src/rpc.rs similarity index 100% rename from rpc/src/lib.rs rename to testchain/node/src/rpc.rs diff --git a/testchain/node/src/service.rs b/testchain/node/src/service.rs index f03b553d8..a9cc1bf2b 100644 --- a/testchain/node/src/service.rs +++ b/testchain/node/src/service.rs @@ -14,13 +14,35 @@ use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; use sp_core::crypto::KeyTypeId; +use crate::rpc as spacewalk_rpc; use primitives::Block; -use spacewalk_runtime::RuntimeApi; + +use spacewalk_runtime_mainnet::RuntimeApi as MainnetRuntimeApi; +use spacewalk_runtime_testnet::RuntimeApi as TestnetRuntimeApi; // Native executor instance. -pub struct Executor; +pub struct TestnetExecutor; + +impl sc_executor::NativeExecutionDispatch for TestnetExecutor { + /// Only enable the benchmarking host functions when we actually want to benchmark. + #[cfg(feature = "runtime-benchmarks")] + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + /// Otherwise we only use the default Substrate host functions. + #[cfg(not(feature = "runtime-benchmarks"))] + type ExtendHostFunctions = (); + + fn dispatch(method: &str, data: &[u8]) -> Option> { + spacewalk_runtime_testnet::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + spacewalk_runtime_testnet::native_version() + } +} + +pub struct MainnetExecutor; -impl sc_executor::NativeExecutionDispatch for Executor { +impl sc_executor::NativeExecutionDispatch for MainnetExecutor { /// Only enable the benchmarking host functions when we actually want to benchmark. #[cfg(feature = "runtime-benchmarks")] type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; @@ -29,39 +51,44 @@ impl sc_executor::NativeExecutionDispatch for Executor { type ExtendHostFunctions = (); fn dispatch(method: &str, data: &[u8]) -> Option> { - spacewalk_runtime::api::dispatch(method, data) + spacewalk_runtime_mainnet::api::dispatch(method, data) } fn native_version() -> sc_executor::NativeVersion { - spacewalk_runtime::native_version() + spacewalk_runtime_mainnet::native_version() } } -pub type FullClient = TFullClient>; +pub type FullTestnetClient = + TFullClient>; + +pub type FullMainnetClient = + TFullClient>; + pub type FullBackend = TFullBackend; type FullSelectChain = sc_consensus::LongestChain; #[allow(clippy::type_complexity)] #[allow(clippy::redundant_clone)] -pub fn new_partial( +pub fn new_partial_mainnet( config: &Configuration, instant_seal: bool, ) -> Result< sc_service::PartialComponents< - FullClient, + FullMainnetClient, FullBackend, FullSelectChain, - sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool, + sc_consensus::DefaultImportQueue, + sc_transaction_pool::FullPool, ( sc_consensus_grandpa::GrandpaBlockImport< FullBackend, Block, - FullClient, + FullMainnetClient, FullSelectChain, >, - sc_consensus_grandpa::LinkHalf, + sc_consensus_grandpa::LinkHalf, Option, ), >, @@ -82,7 +109,7 @@ pub fn new_partial( }) .transpose()?; - let executor = NativeElseWasmExecutor::::new( + let executor = NativeElseWasmExecutor::::new( config.wasm_method, config.default_heap_pages, config.max_runtime_instances, @@ -90,7 +117,7 @@ pub fn new_partial( ); let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( + sc_service::new_full_parts::( config, telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), executor, @@ -104,12 +131,128 @@ pub fn new_partial( let select_chain = sc_consensus::LongestChain::new(backend.clone()); - // TODO check if this is needed - // let select_chain = if instant_seal { - // Some(LongestChain::new(backend.clone())) - // } else { - // None - // }; + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.role.is_authority().into(), + config.prometheus_registry(), + task_manager.spawn_essential_handle(), + client.clone(), + ); + + let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( + client.clone(), + &(client.clone() as Arc<_>), + select_chain.clone(), + telemetry.as_ref().map(|x| x.handle()), + )?; + + let slot_duration = sc_consensus_aura::slot_duration(&*client)?; + let registry = config.prometheus_registry(); + + let import_queue = if instant_seal { + // instance sealing + sc_consensus_manual_seal::import_queue( + Box::new(client.clone()), + &task_manager.spawn_essential_handle(), + registry, + ) + } else { + sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + spawner: &task_manager.spawn_essential_handle(), + registry, + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })? + }; + + Ok(sc_service::PartialComponents { + client, + backend, + task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + other: (grandpa_block_import, grandpa_link, telemetry), + }) +} + +#[allow(clippy::type_complexity)] +#[allow(clippy::redundant_clone)] +pub fn new_partial_testnet( + config: &Configuration, + instant_seal: bool, +) -> Result< + sc_service::PartialComponents< + FullTestnetClient, + FullBackend, + FullSelectChain, + sc_consensus::DefaultImportQueue, + sc_transaction_pool::FullPool, + ( + sc_consensus_grandpa::GrandpaBlockImport< + FullBackend, + Block, + FullTestnetClient, + FullSelectChain, + >, + sc_consensus_grandpa::LinkHalf, + Option, + ), + >, + ServiceError, +> { + if config.keystore_remote.is_some() { + return Err(ServiceError::Other("Remote Keystores are not supported.".to_string())) + } + + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; + + let executor = NativeElseWasmExecutor::::new( + config.wasm_method, + config.default_heap_pages, + config.max_runtime_instances, + config.runtime_cache_size, + ); + + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; + let client = Arc::new(client); + + let telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", None, worker.run()); + telemetry + }); + + let select_chain = sc_consensus::LongestChain::new(backend.clone()); let transaction_pool = sc_transaction_pool::BasicPool::new_full( config.transaction_pool.clone(), @@ -190,7 +333,7 @@ pub fn new_full(mut config: Configuration) -> Result<(TaskManager, RpcHandlers), select_chain, transaction_pool, other: (block_import, grandpa_link, mut telemetry), - } = new_partial(&config, false)?; + } = new_partial_mainnet(&config, false)?; if let Some(url) = &config.keystore_remote { match remote_keystore(url) { @@ -377,7 +520,129 @@ pub fn new_full(mut config: Configuration) -> Result<(TaskManager, RpcHandlers), } #[allow(dead_code)] -pub async fn start_instant( +pub async fn start_instant_mainnet( + config: Configuration, +) -> sc_service::error::Result<(TaskManager, RpcHandlers)> { + let sc_service::PartialComponents { + client, + backend, + mut task_manager, + import_queue, + keystore_container, + select_chain, + transaction_pool, + other: (_, _, mut telemetry), + } = new_partial_mainnet(&config, true)?; + + let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: &config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue, + block_announce_validator_builder: None, + warp_sync_params: None, + })?; + + if config.offchain_worker.enabled { + sc_service::build_offchain_workers( + &config, + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); + }; + + let prometheus_registry = config.prometheus_registry().cloned(); + + let role = config.role.clone(); + + let command_sink = if role.is_authority() { + let proposer_factory = sc_basic_authorship::ProposerFactory::new( + task_manager.spawn_handle(), + client.clone(), + transaction_pool.clone(), + prometheus_registry.as_ref(), + telemetry.as_ref().map(|x| x.handle()), + ); + + // Channel for the rpc handler to communicate with the authorship task. + let (command_sink, commands_stream) = futures::channel::mpsc::channel(1024); + + let pool = transaction_pool.pool().clone(); + let import_stream = pool.validated_pool().import_notification_stream().map(|_| { + sc_consensus_manual_seal::rpc::EngineCommand::SealNewBlock { + create_empty: true, + finalize: true, + parent_hash: None, + sender: None, + } + }); + + let authorship_future = + sc_consensus_manual_seal::run_manual_seal(sc_consensus_manual_seal::ManualSealParams { + block_import: client.clone(), + env: proposer_factory, + client: client.clone(), + pool: transaction_pool.clone(), + commands_stream: futures::stream_select!(commands_stream, import_stream), + select_chain, + consensus_data_provider: None, + create_inherent_data_providers: move |_, ()| async move { + Ok(sp_timestamp::InherentDataProvider::from_system_time()) + }, + }); + + // we spawn the future on a background thread managed by service. + task_manager.spawn_essential_handle().spawn_blocking( + "instant-seal", + Some("block-authoring"), + authorship_future, + ); + Some(command_sink) + } else { + None + }; + + let rpc_builder = { + let client = client.clone(); + let transaction_pool = transaction_pool.clone(); + + move |deny_unsafe, _| { + let deps = spacewalk_rpc::FullDeps { + client: client.clone(), + pool: transaction_pool.clone(), + deny_unsafe, + command_sink: command_sink.clone(), + }; + + spacewalk_rpc::create_full(deps).map_err(Into::into) + } + }; + + let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { + network, + client, + keystore: keystore_container.sync_keystore(), + task_manager: &mut task_manager, + transaction_pool, + rpc_builder: Box::new(rpc_builder), + backend, + system_rpc_tx, + tx_handler_controller, + config, + telemetry: telemetry.as_mut(), + sync_service, + })?; + + network_starter.start_network(); + + Ok((task_manager, rpc_handlers)) +} + +#[allow(dead_code)] +pub async fn start_instant_testnet( config: Configuration, ) -> sc_service::error::Result<(TaskManager, RpcHandlers)> { let sc_service::PartialComponents { @@ -389,7 +654,7 @@ pub async fn start_instant( select_chain, transaction_pool, other: (_, _, mut telemetry), - } = new_partial(&config, true)?; + } = new_partial_testnet(&config, true)?; let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { diff --git a/testchain/runtime/Cargo.toml b/testchain/runtime/mainnet/Cargo.toml similarity index 78% rename from testchain/runtime/Cargo.toml rename to testchain/runtime/mainnet/Cargo.toml index b5c25a00e..6b44a295b 100644 --- a/testchain/runtime/Cargo.toml +++ b/testchain/runtime/mainnet/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["Pendulum"] edition = "2021" -name = 'spacewalk-runtime-standalone' +name = 'spacewalk-runtime-standalone-mainnet' version = "1.0.4" [package.metadata.docs.rs] @@ -54,29 +54,29 @@ orml-currencies = {git = "https://github.com/open-web3-stack/open-runtime-module orml-tokens = {git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.40", default-features = false} orml-traits = {git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.40", default-features = false} -clients-info = {path = "../../pallets/clients-info", default-features = false} -currency = {path = "../../pallets/currency", default-features = false} -fee = {path = "../../pallets/fee", default-features = false} -issue = {path = "../../pallets/issue", default-features = false} -nomination = {path = "../../pallets/nomination", default-features = false} -oracle = {path = "../../pallets/oracle", default-features = false} -pooled-rewards = {path = "../../pallets/pooled-rewards", default-features = false} -redeem = {path = "../../pallets/redeem", default-features = false} -replace = {path = "../../pallets/replace", default-features = false} -reward = {path = "../../pallets/reward", default-features = false} -reward-distribution = {path = "../../pallets/reward-distribution", default-features = false} -security = {path = "../../pallets/security", default-features = false} -staking = {path = "../../pallets/staking", default-features = false} -stellar-relay = {path = "../../pallets/stellar-relay", default-features = false} -vault-registry = {path = "../../pallets/vault-registry", default-features = false} - -module-issue-rpc-runtime-api = {path = "../../pallets/issue/rpc/runtime-api", default-features = false} -module-oracle-rpc-runtime-api = {path = "../../pallets/oracle/rpc/runtime-api", default-features = false} -module-redeem-rpc-runtime-api = {path = "../../pallets/redeem/rpc/runtime-api", default-features = false} -module-replace-rpc-runtime-api = {path = "../../pallets/replace/rpc/runtime-api", default-features = false} -module-vault-registry-rpc-runtime-api = {path = "../../pallets/vault-registry/rpc/runtime-api", default-features = false} - -primitives = {package = "spacewalk-primitives", path = "../../primitives", default-features = false} +clients-info = {path = "../../../pallets/clients-info", default-features = false} +currency = {path = "../../../pallets/currency", default-features = false} +fee = {path = "../../../pallets/fee", default-features = false} +issue = {path = "../../../pallets/issue", default-features = false} +nomination = {path = "../../../pallets/nomination", default-features = false} +oracle = {path = "../../../pallets/oracle", default-features = false} +pooled-rewards = {path = "../../../pallets/pooled-rewards", default-features = false} +redeem = {path = "../../../pallets/redeem", default-features = false} +replace = {path = "../../../pallets/replace", default-features = false} +reward = {path = "../../../pallets/reward", default-features = false} +reward-distribution = {path = "../../../pallets/reward-distribution", default-features = false} +security = {path = "../../../pallets/security", default-features = false} +staking = {path = "../../../pallets/staking", default-features = false} +stellar-relay = {path = "../../../pallets/stellar-relay", default-features = false} +vault-registry = {path = "../../../pallets/vault-registry", default-features = false} + +module-issue-rpc-runtime-api = {path = "../../../pallets/issue/rpc/runtime-api", default-features = false} +module-oracle-rpc-runtime-api = {path = "../../../pallets/oracle/rpc/runtime-api", default-features = false} +module-redeem-rpc-runtime-api = {path = "../../../pallets/redeem/rpc/runtime-api", default-features = false} +module-replace-rpc-runtime-api = {path = "../../../pallets/replace/rpc/runtime-api", default-features = false} +module-vault-registry-rpc-runtime-api = {path = "../../../pallets/vault-registry/rpc/runtime-api", default-features = false} + +primitives = {package = "spacewalk-primitives", path = "../../../primitives", default-features = false} orml-oracle = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.40", default-features = false } dia-oracle = { git = "https://github.com/pendulum-chain/oracle-pallet", branch = "polkadot-v0.9.40", default-features = false } diff --git a/testchain/runtime/build.rs b/testchain/runtime/mainnet/build.rs similarity index 100% rename from testchain/runtime/build.rs rename to testchain/runtime/mainnet/build.rs diff --git a/testchain/runtime/mainnet/src/lib.rs b/testchain/runtime/mainnet/src/lib.rs new file mode 100644 index 000000000..64a161958 --- /dev/null +++ b/testchain/runtime/mainnet/src/lib.rs @@ -0,0 +1,1020 @@ +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; + +use codec::Encode; +pub use dia_oracle::dia::*; +use frame_support::{ + construct_runtime, parameter_types, + traits::{ConstU128, ConstU32, ConstU64, ConstU8, Contains}, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, IdentityFee, Weight}, + PalletId, +}; +pub use frame_system::Call as SystemCall; +use orml_currencies::BasicCurrencyAdapter; +use orml_traits::{currency::MutationHooks, parameter_type_with_key}; +pub use pallet_balances::Call as BalancesCall; +use pallet_grandpa::{ + fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, +}; +pub use pallet_timestamp::Call as TimestampCall; +use sp_api::impl_runtime_apis; +use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_core::{OpaqueMetadata, H256}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{ + AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert, NumberFor, + Zero, + }, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, DispatchError, FixedPointNumber, Perbill, Perquintill, + SaturatedConversion, +}; +use sp_std::{marker::PhantomData, prelude::*}; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +use currency::Amount; +pub use issue::{Event as IssueEvent, IssueRequest}; +pub use module_oracle_rpc_runtime_api::BalanceWrapper; +pub use nomination::Event as NominationEvent; +use oracle::dia::{DiaOracleAdapter, NativeCurrencyKey, XCMCurrencyConversion}; +pub use primitives::{ + self, AccountId, Balance, BlockNumber, CurrencyId, Hash, Moment, Nonce, Signature, + SignedFixedPoint, SignedInner, UnsignedFixedPoint, UnsignedInner, +}; +pub use redeem::{Event as RedeemEvent, RedeemRequest}; +pub use replace::{Event as ReplaceEvent, ReplaceRequest}; +pub use security::StatusCode; +pub use stellar_relay::traits::{FieldLength, Organization, Validator}; + +type VaultId = primitives::VaultId; + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + pub grandpa: Grandpa, + } +} + +pub const UNITS: Balance = 10_000_000_000; +pub const CENTS: Balance = UNITS / 100; +// 100_000_000 +pub const MILLICENTS: Balance = CENTS / 1_000; // 100_000 + +// These time units are defined in number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; +pub const WEEKS: BlockNumber = DAYS * 7; +pub const YEARS: BlockNumber = DAYS * 365; + +/// This runtime version. +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("spacewalk-standalone"), + impl_name: create_runtime_str!("spacewalk-standalone"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + transaction_version: 1, + apis: RUNTIME_API_VERSIONS, + state_version: 0, +}; + +pub const MILLISECS_PER_BLOCK: u64 = 6000; +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +pub struct BlockNumberToBalance; + +impl Convert for BlockNumberToBalance { + fn convert(a: BlockNumber) -> Balance { + a.into() + } +} + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } +} + +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + pub const BlockHashCount: BlockNumber = 250; + /// We allow for 2 seconds of compute with a 6 second average block time. + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::with_sensible_defaults( + (2u64 * Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND,0)).set_proof_size(u64::MAX), + NORMAL_DISPATCH_RATIO, + ); + pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength + ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub const SS58Prefix: u8 = 42; +} + +pub type Index = u32; + +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = BlockWeights; + type BlockLength = BlockLength; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + type DbWeight = (); + /// Runtime version. + type Version = Version; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub const MaxAuthorities: u32 = 32; +} + +impl pallet_aura::Config for Runtime { + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = MaxAuthorities; +} + +impl pallet_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type KeyOwnerProof = sp_core::Void; + type WeightInfo = (); + type MaxAuthorities = MaxAuthorities; + type MaxSetIdSessionEntries = ConstU64<0>; + type EquivocationReportSystem = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = Moment; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +const NATIVE_CURRENCY_ID: CurrencyId = CurrencyId::Native; +const PARENT_CURRENCY_ID: CurrencyId = CurrencyId::XCM(0); + +parameter_types! { + pub const GetNativeCurrencyId: CurrencyId = NATIVE_CURRENCY_ID; + pub const GetRelayChainCurrencyId: CurrencyId = PARENT_CURRENCY_ID; + pub const TransactionByteFee: Balance = MILLICENTS; +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = IdentityFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = (); +} + +impl pallet_sudo::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; +} + +// Pallet accounts +parameter_types! { + pub const FeePalletId: PalletId = PalletId(*b"mod/fees"); + pub const VaultRegistryPalletId: PalletId = PalletId(*b"mod/vreg"); +} + +parameter_types! { + // 5EYCAe5i8QbRr5WN1PvaAVqPbfXsqazk9ocaxuzcTjgXPM1e + pub FeeAccount: AccountId = FeePalletId::get().into_account_truncating(); + // 5EYCAe5i8QbRra1jndPz1WAuf1q1KHQNfu2cW1EXJ231emTd + pub VaultRegistryAccount: AccountId = VaultRegistryPalletId::get().into_account_truncating(); +} + +pub fn get_all_module_accounts() -> Vec { + vec![FeeAccount::get(), VaultRegistryAccount::get()] +} + +parameter_types! { + pub const MaxLocks: u32 = 50; +} + +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { + Zero::zero() + }; +} + +pub struct CurrencyHooks(PhantomData); + +impl MutationHooks + for CurrencyHooks +{ + type OnDust = orml_tokens::BurnDust; + type OnSlash = (); + type PreDeposit = (); + type PostDeposit = (); + type PreTransfer = (); + type PostTransfer = (); + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); +} + +impl orml_tokens::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type Amount = primitives::Amount; + type CurrencyId = CurrencyId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type CurrencyHooks = CurrencyHooks; + type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type DustRemovalWhitelist = DustRemovalWhitelist; +} + +pub struct DustRemovalWhitelist; + +impl Contains for DustRemovalWhitelist { + fn contains(a: &AccountId) -> bool { + vec![].contains(a) + } +} + +impl orml_currencies::Config for Runtime { + type MultiCurrency = Tokens; + type NativeCurrency = BasicCurrencyAdapter; + type GetNativeCurrencyId = GetNativeCurrencyId; + type WeightInfo = (); +} + +/// Existential deposit. +pub const EXISTENTIAL_DEPOSIT: u128 = 500; + +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; +} + +impl security::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = security::SubstrateWeight; +} + +pub struct CurrencyConvert; + +impl currency::CurrencyConversion, CurrencyId> for CurrencyConvert { + fn convert( + amount: ¤cy::Amount, + to: CurrencyId, + ) -> Result, DispatchError> { + Oracle::convert(amount, to) + } +} + +impl currency::Config for Runtime { + type SignedInner = SignedInner; + type SignedFixedPoint = SignedFixedPoint; + type UnsignedFixedPoint = UnsignedFixedPoint; + type Balance = Balance; + type GetRelayChainCurrencyId = GetRelayChainCurrencyId; + type AssetConversion = primitives::AssetConversion; + type BalanceConversion = primitives::BalanceConversion; + type CurrencyConversion = CurrencyConvert; + type AmountCompatibility = primitives::StellarCompatibility; +} + +impl staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SignedFixedPoint = SignedFixedPoint; + type SignedInner = SignedInner; + type CurrencyId = CurrencyId; + type GetNativeCurrencyId = GetNativeCurrencyId; + type MaxRewardCurrencies = MaxRewardCurrencies; +} + +pub type OrganizationId = u128; + +parameter_types! { + pub const OrganizationLimit: u32 = 255; + pub const ValidatorLimit: u32 = 255; + pub const IsPublicNetwork: bool = true; +} + +impl stellar_relay::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OrganizationId = OrganizationId; + type OrganizationLimit = OrganizationLimit; + type ValidatorLimit = ValidatorLimit; + type IsPublicNetwork = IsPublicNetwork; + type WeightInfo = stellar_relay::SubstrateWeight; +} + +impl vault_registry::Config for Runtime { + type PalletId = VaultRegistryPalletId; + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type WeightInfo = vault_registry::SubstrateWeight; + type GetGriefingCollateralCurrencyId = GetRelayChainCurrencyId; +} + +impl frame_system::offchain::SendTransactionTypes for Runtime +where + RuntimeCall: From, +{ + type OverarchingCall = RuntimeCall; + type Extrinsic = UncheckedExtrinsic; +} + +impl dia_oracle::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type AuthorityId = dia_oracle::crypto::DiaAuthId; + type WeightInfo = dia_oracle::weights::DiaWeightInfo; +} + +impl frame_system::offchain::SigningTypes for Runtime { + type Public = ::Signer; + type Signature = Signature; +} + +impl frame_system::offchain::CreateSignedTransaction for Runtime +where + RuntimeCall: From, +{ + fn create_transaction>( + call: RuntimeCall, + public: ::Signer, + account: AccountId, + index: Index, + ) -> Option<( + RuntimeCall, + ::SignaturePayload, + )> { + let period = BlockHashCount::get() as u64; + let current_block = System::block_number().saturated_into::().saturating_sub(1); + let tip = 0; + let extra: SignedExtra = ( + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(generic::Era::mortal(period, current_block)), + frame_system::CheckNonce::::from(index), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + ); + + let raw_payload = SignedPayload::new(call, extra).ok()?; + let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?; + let address = account; + let (call, extra, _) = raw_payload.deconstruct(); + Some((call, (sp_runtime::MultiAddress::Id(address), signature, extra))) + } +} + +pub struct ConvertPrice; + +impl Convert> for ConvertPrice { + fn convert(price: u128) -> Option { + Some(UnsignedFixedPoint::from_inner(price)) + } +} + +pub struct ConvertMoment; + +impl Convert> for ConvertMoment { + fn convert(moment: u64) -> Option { + // The provided moment is in seconds, but we need milliseconds + Some(moment.saturating_mul(1000)) + } +} + +pub struct SpacewalkNativeCurrencyKey; + +impl NativeCurrencyKey for SpacewalkNativeCurrencyKey { + fn native_symbol() -> Vec { + "LOCAL".as_bytes().to_vec() + } + + fn native_chain() -> Vec { + "LOCAL".as_bytes().to_vec() + } +} + +// It's important that this is implemented the same way as the MockOracleKeyConvertor +// because this is used in the benchmark_utils::DataCollector when feeding prices +impl XCMCurrencyConversion for SpacewalkNativeCurrencyKey { + fn convert_to_dia_currency_id(token_symbol: u8) -> Option<(Vec, Vec)> { + // todo: this code results in Execution error: + // todo: \"Unable to get required collateral for amount\": + // todo: Module(ModuleError { index: 19, error: [0, 0, 0, 0], message: None })", data: None + // } cfg_if::cfg_if! { + // if #[cfg(not(feature = "testing-utils"))] { + // if token_symbol == 0 { + // return Some((b"Kusama".to_vec(), b"KSM".to_vec())) + // } + // } + // } + // We assume that the blockchain is always 0 and the symbol represents the token symbol + let blockchain = vec![0u8]; + let symbol = vec![token_symbol]; + + Some((blockchain, symbol)) + } + + fn convert_from_dia_currency_id(blockchain: Vec, symbol: Vec) -> Option { + // We assume that the blockchain is always 0 and the symbol represents the token symbol + if blockchain.len() != 1 && blockchain[0] != 0 || symbol.len() != 1 { + return None + } + return Some(symbol[0]) + } +} + +cfg_if::cfg_if! { + if #[cfg(feature = "testing-utils")] { + type DataProviderImpl = DiaOracleAdapter< + DiaOracleModule, + UnsignedFixedPoint, + Moment, + oracle::dia::DiaOracleKeyConvertor, + ConvertPrice, + ConvertMoment, + >; + } else if #[cfg(feature = "runtime-benchmarks")] { + use oracle::testing_utils::{ + MockConvertMoment, MockConvertPrice, MockDiaOracle, MockOracleKeyConvertor, + }; + type DataProviderImpl = DiaOracleAdapter< + MockDiaOracle, + UnsignedFixedPoint, + Moment, + MockOracleKeyConvertor, + MockConvertPrice, + MockConvertMoment, + >; + } else { + // This implementation will be used when running the testchain locally + // as well as for the **vault integration tests** + type DataProviderImpl = DiaOracleAdapter< + DiaOracleModule, + UnsignedFixedPoint, + Moment, + oracle::dia::DiaOracleKeyConvertor, + ConvertPrice, + ConvertMoment, + >; + } +} + +#[cfg(any(feature = "runtime-benchmarks", feature = "testing-utils"))] +use oracle::testing_utils::MockDataFeeder; + +impl oracle::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = oracle::SubstrateWeight; + type DecimalsLookup = primitives::DefaultDecimalsLookup; + type DataProvider = DataProviderImpl; + + #[cfg(any(feature = "runtime-benchmarks", feature = "testing-utils"))] + type DataFeeder = MockDataFeeder; +} + +impl issue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type BlockNumberToBalance = BlockNumberToBalance; + type WeightInfo = issue::SubstrateWeight; +} + +impl redeem::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = redeem::SubstrateWeight; +} + +impl replace::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = replace::SubstrateWeight; +} + +parameter_types! { + pub const MaxExpectedValue: UnsignedFixedPoint = UnsignedFixedPoint::from_inner(::DIV); +} + +impl fee::Config for Runtime { + type FeePalletId = FeePalletId; + type WeightInfo = fee::SubstrateWeight; + type SignedFixedPoint = SignedFixedPoint; + type SignedInner = SignedInner; + type UnsignedFixedPoint = UnsignedFixedPoint; + type UnsignedInner = UnsignedInner; + type VaultRewards = VaultRewards; + type VaultStaking = VaultStaking; + type OnSweep = currency::SweepFunds; + type MaxExpectedValue = MaxExpectedValue; + type RewardDistribution = RewardDistribution; +} + +impl nomination::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = nomination::SubstrateWeight; +} + +impl clients_info::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = clients_info::SubstrateWeight; + type MaxNameLength = ConstU32<255>; + type MaxUriLength = ConstU32<255>; +} + +parameter_types! { + pub const DecayRate: Perquintill = Perquintill::from_percent(5); + pub const MaxCurrencies: u32 = 10; +} + +impl reward_distribution::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = reward_distribution::SubstrateWeight; + type Balance = Balance; + type DecayInterval = ConstU32<100>; + type DecayRate = DecayRate; + type VaultRewards = VaultRewards; + type MaxCurrencies = MaxCurrencies; + type OracleApi = Oracle; + type Balances = Balances; + type VaultStaking = VaultStaking; + type FeePalletId = FeePalletId; +} + +parameter_types! { + pub const MaxRewardCurrencies: u32= 10; +} + +impl pooled_rewards::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SignedFixedPoint = SignedFixedPoint; + type PoolId = CurrencyId; + type PoolRewardsCurrencyId = CurrencyId; + type StakeId = VaultId; + type MaxRewardCurrencies = MaxRewardCurrencies; +} + +construct_runtime! { + pub enum Runtime where + Block = Block, + NodeBlock = primitives::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Pallet, Call, Storage, Config, Event} = 0, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 1, + Aura: pallet_aura::{Pallet, Config} = 2, + Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event} = 3, + Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event} = 4, + Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event} = 5, + Currencies: orml_currencies::{Pallet, Call, Storage} = 7, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 8, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event} = 9, + + StellarRelay: stellar_relay::{Pallet, Call, Config, Storage, Event} = 10, + + VaultRewards: pooled_rewards::{Pallet, Storage, Event} = 15, + VaultStaking: staking::{Pallet, Storage, Event} = 16, + + Currency: currency::{Pallet} = 17, + + Security: security::{Pallet, Call, Config, Storage, Event} = 19, + VaultRegistry: vault_registry::{Pallet, Call, Config, Storage, Event, ValidateUnsigned} = 21, + Oracle: oracle::{Pallet, Call, Config, Storage, Event} = 22, + Issue: issue::{Pallet, Call, Config, Storage, Event} = 23, + Redeem: redeem::{Pallet, Call, Config, Storage, Event} = 24, + Replace: replace::{Pallet, Call, Config, Storage, Event} = 25, + Fee: fee::{Pallet, Call, Config, Storage} = 26, + Nomination: nomination::{Pallet, Call, Config, Storage, Event} = 28, + DiaOracleModule: dia_oracle::{Pallet, Call, Config, Storage, Event} = 29, + ClientsInfo: clients_info::{Pallet, Call, Storage, Event} = 30, + RewardDistribution: reward_distribution::{Pallet, Call, Storage, Event} = 31, + } +} + +/// The address format for describing accounts. +pub type Address = sp_runtime::MultiAddress; +/// Block header type as expected by this runtime. +pub type Header = generic::Header; +/// Block type as expected by this runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; +pub type SignedPayload = generic::SignedPayload; +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + define_benchmarks!( + [clients_info, ClientsInfo] + [frame_benchmarking, BaselineBench::] + [frame_system, SystemBench::] + [stellar_relay, StellarRelay] + [issue, Issue] + [fee, Fee] + [oracle, Oracle] + [redeem, Redeem] + [replace, Replace] + [vault_registry, VaultRegistry] + [nomination, Nomination] + [reward_distribution, RewardDistribution] + ); +} + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + OpaqueMetadata::new(Runtime::metadata().into()) + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx, block_hash) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_session::SessionKeys for Runtime { + fn decode_session_keys( + encoded: Vec, + ) -> Option, sp_core::crypto::KeyTypeId)>> { + SessionKeys::decode_into_raw_public_keys(&encoded) + } + + fn generate_session_keys(seed: Option>) -> Vec { + SessionKeys::generate(seed) + } + } + + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { + Grandpa::grandpa_authorities() + } + + fn current_set_id() -> fg_primitives::SetId { + Grandpa::current_set_id() + } + + fn submit_report_equivocation_unsigned_extrinsic( + _equivocation_proof: fg_primitives::EquivocationProof< + ::Hash, + NumberFor, + >, + _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, + ) -> Option<()> { + None + } + + fn generate_key_ownership_proof( + _set_id: fg_primitives::SetId, + _authority_id: GrandpaId, + ) -> Option { + // NOTE: this is the only implementation possible since we've + // defined our key owner proof type as a bottom type (i.e. a type + // with no values). + None + } + } + + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + } + + fn authorities() -> Vec { + Aura::authorities().into_inner() + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Nonce { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; + use frame_support::traits::StorageInfoTrait; + use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; + + let mut list = Vec::::new(); + list_benchmarks!(list, extra); + + let storage_info = AllPalletsWithSystem::storage_info(); + (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; + + use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; + + impl frame_system_benchmarking::Config for Runtime {} + impl baseline::Config for Runtime {} + + let whitelist: Vec = vec![ + // Block Number + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), + // Total Issuance + hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), + // Execution Phase + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), + // Event Count + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), + // System Events + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), + ]; + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + add_benchmarks!(params, batches); + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } + + impl module_issue_rpc_runtime_api::IssueApi< + Block, + AccountId, + H256, + IssueRequest + > for Runtime { + fn get_issue_requests(account_id: AccountId) -> Vec { + Issue::get_issue_requests_for_account(account_id) + } + + fn get_vault_issue_requests(vault_id: AccountId) -> Vec { + Issue::get_issue_requests_for_vault(vault_id) + } + } + + impl module_vault_registry_rpc_runtime_api::VaultRegistryApi< + Block, + VaultId, + Balance, + UnsignedFixedPoint, + CurrencyId, + AccountId, + > for Runtime { + fn get_vault_collateral(vault_id: VaultId) -> Result, DispatchError> { + let result = VaultRegistry::compute_collateral(&vault_id)?; + Ok(BalanceWrapper{amount:result.amount()}) + } + + fn get_vaults_by_account_id(account_id: AccountId) -> Result, DispatchError> { + VaultRegistry::get_vaults_by_account_id(account_id) + } + + fn get_vault_total_collateral(vault_id: VaultId) -> Result, DispatchError> { + let result = VaultRegistry::get_backing_collateral(&vault_id)?; + Ok(BalanceWrapper{amount:result.amount()}) + } + + fn get_premium_redeem_vaults() -> Result)>, DispatchError> { + let result = VaultRegistry::get_premium_redeem_vaults()?; + Ok(result.iter().map(|v| (v.0.clone(), BalanceWrapper{amount:v.1.amount()})).collect()) + } + + fn get_vaults_with_issuable_tokens() -> Result)>, DispatchError> { + let result = VaultRegistry::get_vaults_with_issuable_tokens()?; + Ok(result.into_iter().map(|v| (v.0, BalanceWrapper{amount:v.1.amount()})).collect()) + } + + fn get_vaults_with_redeemable_tokens() -> Result)>, DispatchError> { + let result = VaultRegistry::get_vaults_with_redeemable_tokens()?; + Ok(result.into_iter().map(|v| (v.0, BalanceWrapper{amount:v.1.amount()})).collect()) + } + + fn get_issuable_tokens_from_vault(vault: VaultId) -> Result, DispatchError> { + let result = VaultRegistry::get_issuable_tokens_from_vault(&vault)?; + Ok(BalanceWrapper{amount:result.amount()}) + } + + fn get_collateralization_from_vault(vault: VaultId, only_issued: bool) -> Result { + VaultRegistry::get_collateralization_from_vault(vault, only_issued) + } + + fn get_collateralization_from_vault_and_collateral(vault: VaultId, collateral: BalanceWrapper, only_issued: bool) -> Result { + let amount = Amount::new(collateral.amount, vault.collateral_currency()); + VaultRegistry::get_collateralization_from_vault_and_collateral(vault, &amount, only_issued) + } + + fn get_required_collateral_for_wrapped(amount_wrapped: BalanceWrapper, wrapped_currency_id: CurrencyId, collateral_currency_id: CurrencyId) -> Result, DispatchError> { + let amount_wrapped = Amount::new(amount_wrapped.amount, wrapped_currency_id); + let result = VaultRegistry::get_required_collateral_for_wrapped(&amount_wrapped, collateral_currency_id)?; + Ok(BalanceWrapper{amount:result.amount()}) + } + + fn get_required_collateral_for_vault(vault_id: VaultId) -> Result, DispatchError> { + let result = VaultRegistry::get_required_collateral_for_vault(vault_id)?; + Ok(BalanceWrapper{amount:result.amount()}) + } + } + + impl module_redeem_rpc_runtime_api::RedeemApi< + Block, + AccountId, + H256, + RedeemRequest + > for Runtime { + fn get_redeem_requests(account_id: AccountId) -> Vec { + Redeem::get_redeem_requests_for_account(account_id) + } + + fn get_vault_redeem_requests(vault_account_id: AccountId) -> Vec { + Redeem::get_redeem_requests_for_vault(vault_account_id) + } + } + + impl module_replace_rpc_runtime_api::ReplaceApi< + Block, + AccountId, + H256, + ReplaceRequest + > for Runtime { + fn get_old_vault_replace_requests(vault_id: AccountId) -> Vec { + Replace::get_replace_requests_for_old_vault(vault_id) + } + + fn get_new_vault_replace_requests(vault_id: AccountId) -> Vec { + Replace::get_replace_requests_for_new_vault(vault_id) + } + } + + impl module_oracle_rpc_runtime_api::OracleApi< + Block, + Balance, + CurrencyId + > for Runtime { + fn currency_to_usd(amount: BalanceWrapper, currency_id: CurrencyId) -> Result, DispatchError> { + let result = Oracle::currency_to_usd(amount.amount, currency_id)?; + Ok(BalanceWrapper{amount:result}) + } + + fn usd_to_currency(amount: BalanceWrapper, currency_id: CurrencyId) -> Result, DispatchError> { + let result = Oracle::usd_to_currency(amount.amount, currency_id)?; + Ok(BalanceWrapper{amount:result}) + } + + fn get_exchange_rate(currency_id: CurrencyId) -> Result { + let result = Oracle::get_exchange_rate(currency_id)?; + Ok(result) + } + } + +} diff --git a/testchain/runtime/testnet/Cargo.toml b/testchain/runtime/testnet/Cargo.toml new file mode 100644 index 000000000..25c2f304b --- /dev/null +++ b/testchain/runtime/testnet/Cargo.toml @@ -0,0 +1,168 @@ +[package] +authors = ["Pendulum"] +edition = "2021" +name = 'spacewalk-runtime-standalone-testnet' +version = "1.0.3" + +[package.metadata.docs.rs] +targets = ['x86_64-unknown-linux-gnu'] + +[dependencies] +codec = {package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"]} +getrandom = {version = "0.2.7", default-features = false, features = ["js"]} +scale-info = {version = "2.1.1", default-features = false, features = ["derive"]} + +cfg-if = "1.0.0" +lazy_static = "1.4.0" + +# Substrate dependencies +sp-api = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-block-builder = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-core = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-inherents = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-io = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-offchain = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-runtime = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-session = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-std = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-transaction-pool = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-version = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} + +frame-executive = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +frame-support = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +frame-system = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +pallet-balances = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +pallet-sudo = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +pallet-timestamp = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +pallet-transaction-payment = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} + +frame-system-rpc-runtime-api = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +pallet-transaction-payment-rpc-runtime-api = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} + +# Used for runtime benchmarking +frame-benchmarking = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false, optional = true} +frame-system-benchmarking = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false, optional = true} +hex-literal = {version = "0.3.4", optional = true, default-features = false} + +# Aura & GRANDPA dependencies +pallet-aura = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +pallet-grandpa = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} +sp-consensus-aura = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false} + +# Orml dependencies +orml-currencies = {git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.40", default-features = false} +orml-tokens = {git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.40", default-features = false} +orml-traits = {git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.40", default-features = false} + +clients-info = {path = "../../../pallets/clients-info", default-features = false} +currency = {path = "../../../pallets/currency", default-features = false} +fee = {path = "../../../pallets/fee", default-features = false} +issue = {path = "../../../pallets/issue", default-features = false} +nomination = {path = "../../../pallets/nomination", default-features = false} +oracle = {path = "../../../pallets/oracle", default-features = false} +pooled-rewards = {path = "../../../pallets/pooled-rewards", default-features = false} +redeem = {path = "../../../pallets/redeem", default-features = false} +replace = {path = "../../../pallets/replace", default-features = false} +reward = {path = "../../../pallets/reward", default-features = false} +reward-distribution = {path = "../../../pallets/reward-distribution", default-features = false} +security = {path = "../../../pallets/security", default-features = false} +staking = {path = "../../../pallets/staking", default-features = false} +stellar-relay = {path = "../../../pallets/stellar-relay", default-features = false} +vault-registry = {path = "../../../pallets/vault-registry", default-features = false} + +module-issue-rpc-runtime-api = {path = "../../../pallets/issue/rpc/runtime-api", default-features = false} +module-oracle-rpc-runtime-api = {path = "../../../pallets/oracle/rpc/runtime-api", default-features = false} +module-redeem-rpc-runtime-api = {path = "../../../pallets/redeem/rpc/runtime-api", default-features = false} +module-replace-rpc-runtime-api = {path = "../../../pallets/replace/rpc/runtime-api", default-features = false} +module-vault-registry-rpc-runtime-api = {path = "../../../pallets/vault-registry/rpc/runtime-api", default-features = false} + +primitives = {package = "spacewalk-primitives", path = "../../../primitives", default-features = false} + +orml-oracle = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.40", default-features = false } +dia-oracle = { git = "https://github.com/pendulum-chain/oracle-pallet", branch = "polkadot-v0.9.40", default-features = false } + +[dev-dependencies] +flate2 = "1.0" +hex = "0.4.2" +mocktopus = "0.8.0" +pretty_assertions = "0.7.2" +serde_json = "1.0" + +[build-dependencies] +substrate-wasm-builder = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40"} + +[features] +default = ["std"] +disable-runtime-api = [] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "hex-literal", + "clients-info/runtime-benchmarks", + "fee/runtime-benchmarks", + "issue/runtime-benchmarks", + "nomination/runtime-benchmarks", + "oracle/runtime-benchmarks", + "redeem/runtime-benchmarks", + "replace/runtime-benchmarks", + "reward-distribution/runtime-benchmarks", + "stellar-relay/runtime-benchmarks", + "vault-registry/runtime-benchmarks", +] +std = [ + "codec/std", + "currency/std", + "clients-info/std", + "fee/std", + "frame-executive/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "getrandom/std", + "issue/std", + "module-issue-rpc-runtime-api/std", + "module-oracle-rpc-runtime-api/std", + "module-redeem-rpc-runtime-api/std", + "module-replace-rpc-runtime-api/std", + "module-vault-registry-rpc-runtime-api/std", + "nomination/std", + "oracle/std", + "orml-currencies/std", + "orml-tokens/std", + "orml-traits/std", + "pallet-aura/std", + "pallet-balances/std", + "pallet-grandpa/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pooled-rewards/std", + "primitives/std", + "redeem/std", + "replace/std", + "reward/std", + "reward-distribution/std", + "scale-info/std", + "security/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "staking/std", + "stellar-relay/std", + "vault-registry/std", + "orml-oracle/std", + "dia-oracle/std", +] +testing-utils = ["oracle/testing-utils"] diff --git a/testchain/runtime/testnet/build.rs b/testchain/runtime/testnet/build.rs new file mode 100644 index 000000000..9b53d2457 --- /dev/null +++ b/testchain/runtime/testnet/build.rs @@ -0,0 +1,9 @@ +use substrate_wasm_builder::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() +} diff --git a/testchain/runtime/src/lib.rs b/testchain/runtime/testnet/src/lib.rs similarity index 100% rename from testchain/runtime/src/lib.rs rename to testchain/runtime/testnet/src/lib.rs