From ecb7c6fb5ebbd8eea8961edd451d9431f631bb14 Mon Sep 17 00:00:00 2001 From: Gregory Hill Date: Thu, 21 Jul 2022 14:24:59 +0100 Subject: [PATCH 1/3] refactor!: remove theft reporting Signed-off-by: Gregory Hill --- Cargo.lock | 72 --- README.md | 1 - crates/btc-relay/src/benchmarking.rs | 48 +- crates/btc-relay/src/default_weights.rs | 58 ++ crates/btc-relay/src/lib.rs | 105 +++- crates/btc-relay/src/tests.rs | 28 +- crates/issue/src/benchmarking.rs | 12 +- crates/redeem/src/benchmarking.rs | 8 +- crates/refund/src/benchmarking.rs | 4 +- crates/relay/Cargo.toml | 97 --- crates/relay/README.md | 11 - crates/relay/rpc/Cargo.toml | 13 - crates/relay/rpc/runtime-api/Cargo.toml | 20 - crates/relay/rpc/runtime-api/src/lib.rs | 17 - crates/relay/rpc/src/lib.rs | 67 --- crates/relay/src/benchmarking.rs | 200 ------- crates/relay/src/default_weights.rs | 178 ------ crates/relay/src/ext.rs | 103 ---- crates/relay/src/lib.rs | 441 -------------- crates/relay/src/mock.rs | 377 ------------ crates/relay/src/tests.rs | 538 ----------------- crates/relay/src/types.rs | 6 - crates/replace/src/benchmarking.rs | 8 +- crates/vault-registry/src/types.rs | 1 + parachain/Cargo.toml | 1 - parachain/runtime/interlay/Cargo.toml | 5 - parachain/runtime/interlay/src/lib.rs | 32 +- parachain/runtime/kintsugi/Cargo.toml | 5 - parachain/runtime/kintsugi/src/lib.rs | 32 +- parachain/runtime/runtime-tests/Cargo.toml | 6 - parachain/runtime/testnet-interlay/Cargo.toml | 5 - parachain/runtime/testnet-interlay/src/lib.rs | 32 +- parachain/runtime/testnet-kintsugi/Cargo.toml | 5 - parachain/runtime/testnet-kintsugi/src/lib.rs | 32 +- parachain/src/service.rs | 2 - rpc/Cargo.toml | 1 - rpc/src/lib.rs | 4 - standalone/runtime/Cargo.toml | 5 - standalone/runtime/src/lib.rs | 30 +- standalone/runtime/tests/mock/mod.rs | 10 +- standalone/runtime/tests/test_btc_relay.rs | 10 +- standalone/runtime/tests/test_relayers.rs | 553 ------------------ 42 files changed, 264 insertions(+), 2919 deletions(-) delete mode 100644 crates/relay/Cargo.toml delete mode 100644 crates/relay/README.md delete mode 100644 crates/relay/rpc/Cargo.toml delete mode 100644 crates/relay/rpc/runtime-api/Cargo.toml delete mode 100644 crates/relay/rpc/runtime-api/src/lib.rs delete mode 100644 crates/relay/rpc/src/lib.rs delete mode 100644 crates/relay/src/benchmarking.rs delete mode 100644 crates/relay/src/default_weights.rs delete mode 100644 crates/relay/src/ext.rs delete mode 100644 crates/relay/src/lib.rs delete mode 100644 crates/relay/src/mock.rs delete mode 100644 crates/relay/src/tests.rs delete mode 100644 crates/relay/src/types.rs delete mode 100644 standalone/runtime/tests/test_relayers.rs diff --git a/Cargo.lock b/Cargo.lock index 954a707f8a..73cf097917 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3531,7 +3531,6 @@ dependencies = [ "module-oracle-rpc-runtime-api", "module-redeem-rpc-runtime-api", "module-refund-rpc-runtime-api", - "module-relay-rpc-runtime-api", "module-replace-rpc-runtime-api", "module-vault-registry-rpc-runtime-api", "pallet-transaction-payment-rpc", @@ -3602,7 +3601,6 @@ dependencies = [ "module-oracle-rpc", "module-redeem-rpc", "module-refund-rpc", - "module-relay-rpc", "module-replace-rpc", "module-vault-registry-rpc", "pallet-transaction-payment-rpc", @@ -3647,7 +3645,6 @@ dependencies = [ "module-oracle-rpc-runtime-api", "module-redeem-rpc-runtime-api", "module-refund-rpc-runtime-api", - "module-relay-rpc-runtime-api", "module-replace-rpc-runtime-api", "module-vault-registry-rpc-runtime-api", "nomination", @@ -3677,7 +3674,6 @@ dependencies = [ "pretty_assertions", "redeem", "refund", - "relay", "replace", "reward", "scale-info", @@ -3783,7 +3779,6 @@ dependencies = [ "module-oracle-rpc-runtime-api", "module-redeem-rpc-runtime-api", "module-refund-rpc-runtime-api", - "module-relay-rpc-runtime-api", "module-replace-rpc-runtime-api", "module-vault-registry-rpc-runtime-api", "nomination", @@ -3819,7 +3814,6 @@ dependencies = [ "polkadot-parachain", "redeem", "refund", - "relay", "replace", "reward", "scale-info", @@ -4138,7 +4132,6 @@ dependencies = [ "module-oracle-rpc-runtime-api", "module-redeem-rpc-runtime-api", "module-refund-rpc-runtime-api", - "module-relay-rpc-runtime-api", "module-replace-rpc-runtime-api", "module-vault-registry-rpc-runtime-api", "nomination", @@ -4173,7 +4166,6 @@ dependencies = [ "polkadot-parachain", "redeem", "refund", - "relay", "replace", "reward", "scale-info", @@ -5462,28 +5454,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "module-relay-rpc" -version = "1.2.0" -dependencies = [ - "jsonrpsee", - "module-relay-rpc-runtime-api", - "parity-scale-codec", - "sp-api", - "sp-blockchain", - "sp-runtime", -] - -[[package]] -name = "module-relay-rpc-runtime-api" -version = "1.2.0" -dependencies = [ - "frame-support", - "parity-scale-codec", - "sp-api", - "sp-std", -] - [[package]] name = "module-replace-rpc" version = "1.2.0" @@ -7127,7 +7097,6 @@ dependencies = [ "module-oracle-rpc-runtime-api", "module-redeem-rpc-runtime-api", "module-refund-rpc-runtime-api", - "module-relay-rpc-runtime-api", "module-replace-rpc-runtime-api", "module-vault-registry-rpc-runtime-api", "nomination", @@ -7162,7 +7131,6 @@ dependencies = [ "polkadot-runtime-parachains", "redeem", "refund", - "relay", "replace", "reward", "scale-info", @@ -9351,42 +9319,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "relay" -version = "1.2.0" -dependencies = [ - "bitcoin", - "btc-relay", - "currency", - "fee", - "frame-benchmarking", - "frame-support", - "frame-system", - "hex", - "interbtc-primitives", - "mocktopus", - "nomination", - "oracle", - "orml-tokens", - "orml-traits", - "pallet-timestamp", - "parity-scale-codec", - "redeem", - "refund", - "replace", - "reward", - "scale-info", - "security", - "serde", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "staking", - "vault-registry", -] - [[package]] name = "remote-externalities" version = "0.10.0-dev" @@ -12371,7 +12303,6 @@ dependencies = [ "module-oracle-rpc-runtime-api", "module-redeem-rpc-runtime-api", "module-refund-rpc-runtime-api", - "module-relay-rpc-runtime-api", "module-replace-rpc-runtime-api", "module-vault-registry-rpc-runtime-api", "nomination", @@ -12407,7 +12338,6 @@ dependencies = [ "polkadot-parachain", "redeem", "refund", - "relay", "replace", "reward", "scale-info", @@ -12471,7 +12401,6 @@ dependencies = [ "module-oracle-rpc-runtime-api", "module-redeem-rpc-runtime-api", "module-refund-rpc-runtime-api", - "module-relay-rpc-runtime-api", "module-replace-rpc-runtime-api", "module-vault-registry-rpc-runtime-api", "nomination", @@ -12507,7 +12436,6 @@ dependencies = [ "polkadot-parachain", "redeem", "refund", - "relay", "replace", "reward", "scale-info", diff --git a/README.md b/README.md index 1dd242a358..d91313a57a 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,6 @@ The Substrate runtime makes use of various custom pallets that are found in the - [oracle](crates/oracle): Trusted providers use this to set exchange rates and Bitcoin fee estimates. - [redeem](crates/redeem): Handles redeeming of interBTC for BTC on Bitcoin. - [refund](crates/refund): Handles refunds for when a vault receives more BTC than it can cover. -- [relay](crates/relay): Handles block submission and theft reporting. - [replace](crates/replace): Handles replacing vaults. - [reward](crates/reward): Scalable reward distribution. - [security](crates/security): Handles status and error changes. diff --git a/crates/btc-relay/src/benchmarking.rs b/crates/btc-relay/src/benchmarking.rs index 5c584b72b5..08727f7ef4 100644 --- a/crates/btc-relay/src/benchmarking.rs +++ b/crates/btc-relay/src/benchmarking.rs @@ -24,7 +24,7 @@ fn mine_genesis(account_id: T::AccountId, address: &BtcAddress, heigh let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::initialize(account_id, block_header, height).unwrap(); + BtcRelay::::_initialize(account_id, block_header, height).unwrap(); block } @@ -76,6 +76,52 @@ fn mine_block_with_one_tx( } benchmarks! { + initialize { + let height = 0u32; + let origin: T::AccountId = account("Origin", 0, 0); + let stake = 100u32; + + let address = BtcAddress::P2PKH(H160::from([0; 20])); + let block = BlockBuilder::new() + .with_version(4) + .with_coinbase(&address, 50, 3) + .with_timestamp(1588813835) + .mine(U256::from(2).pow(254.into())).unwrap(); + let block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); + }: _(RawOrigin::Signed(origin), block_header, height) + + store_block_header { + let origin: T::AccountId = account("Origin", 0, 0); + + let address = BtcAddress::P2PKH(H160::from([0; 20])); + let height = 0; + let stake = 100u32; + + let init_block = BlockBuilder::new() + .with_version(4) + .with_coinbase(&address, 50, 3) + .with_timestamp(1588813835) + .mine(U256::from(2).pow(254.into())).unwrap(); + + let init_block_hash = init_block.header.hash; + let raw_block_header = RawBlockHeader::from_bytes(&init_block.header.try_format().unwrap()) + .expect("could not serialize block header"); + let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); + + BtcRelay::::_initialize(origin.clone(), block_header, height).unwrap(); + + let block = BlockBuilder::new() + .with_previous_hash(init_block_hash) + .with_version(4) + .with_coinbase(&address, 50, 3) + .with_timestamp(1588814835) + .mine(U256::from(2).pow(254.into())).unwrap(); + + let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()) + .expect("could not serialize block header"); + + }: _(RawOrigin::Signed(origin), raw_block_header) + verify_and_validate_transaction { let origin: T::AccountId = account("Origin", 0, 0); diff --git a/crates/btc-relay/src/default_weights.rs b/crates/btc-relay/src/default_weights.rs index b0515d73ed..4d7c549fb5 100644 --- a/crates/btc-relay/src/default_weights.rs +++ b/crates/btc-relay/src/default_weights.rs @@ -34,6 +34,8 @@ use sp_std::marker::PhantomData; /// Weight functions needed for btc_relay. pub trait WeightInfo { + fn initialize() -> Weight; + fn store_block_header() -> Weight; fn verify_and_validate_transaction() -> Weight; fn verify_transaction_inclusion() -> Weight; fn validate_transaction() -> Weight; @@ -42,6 +44,34 @@ pub trait WeightInfo { /// Weights for btc_relay using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { + // Storage: Security ParachainStatus (r:1 w:0) + // Storage: BTCRelay BestBlock (r:1 w:1) + // Storage: BTCRelay ChainCounter (r:1 w:1) + // Storage: BTCRelay Chains (r:1 w:1) + // Storage: Security ActiveBlockCount (r:1 w:0) + // Storage: BTCRelay ChainsHashes (r:0 w:1) + // Storage: BTCRelay StartBlockHeight (r:0 w:1) + // Storage: BTCRelay BestBlockHeight (r:0 w:1) + // Storage: BTCRelay ChainsIndex (r:0 w:1) + // Storage: BTCRelay BlockHeaders (r:0 w:1) + fn initialize() -> Weight { + (52_878_000 as Weight) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(8 as Weight)) + } + // Storage: Security ParachainStatus (r:1 w:0) + // Storage: BTCRelay BlockHeaders (r:2 w:1) + // Storage: BTCRelay ChainsIndex (r:1 w:1) + // Storage: BTCRelay DisableDifficultyCheck (r:1 w:0) + // Storage: BTCRelay ChainsHashes (r:1 w:1) + // Storage: Security ActiveBlockCount (r:1 w:0) + // Storage: BTCRelay BestBlock (r:0 w:1) + // Storage: BTCRelay BestBlockHeight (r:0 w:1) + fn store_block_header() -> Weight { + (68_306_000 as Weight) + .saturating_add(T::DbWeight::get().reads(7 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } // Storage: Security ParachainStatus (r:1 w:0) // Storage: BTCRelay DisableInclusionCheck (r:1 w:0) // Storage: BTCRelay BestBlockHeight (r:1 w:0) @@ -73,6 +103,34 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { + // Storage: Security ParachainStatus (r:1 w:0) + // Storage: BTCRelay BestBlock (r:1 w:1) + // Storage: BTCRelay ChainCounter (r:1 w:1) + // Storage: BTCRelay Chains (r:1 w:1) + // Storage: Security ActiveBlockCount (r:1 w:0) + // Storage: BTCRelay ChainsHashes (r:0 w:1) + // Storage: BTCRelay StartBlockHeight (r:0 w:1) + // Storage: BTCRelay BestBlockHeight (r:0 w:1) + // Storage: BTCRelay ChainsIndex (r:0 w:1) + // Storage: BTCRelay BlockHeaders (r:0 w:1) + fn initialize() -> Weight { + (52_878_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(5 as Weight)) + .saturating_add(RocksDbWeight::get().writes(8 as Weight)) + } + // Storage: Security ParachainStatus (r:1 w:0) + // Storage: BTCRelay BlockHeaders (r:2 w:1) + // Storage: BTCRelay ChainsIndex (r:1 w:1) + // Storage: BTCRelay DisableDifficultyCheck (r:1 w:0) + // Storage: BTCRelay ChainsHashes (r:1 w:1) + // Storage: Security ActiveBlockCount (r:1 w:0) + // Storage: BTCRelay BestBlock (r:0 w:1) + // Storage: BTCRelay BestBlockHeight (r:0 w:1) + fn store_block_header() -> Weight { + (68_306_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(7 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + } // Storage: Security ParachainStatus (r:1 w:0) // Storage: BTCRelay DisableInclusionCheck (r:1 w:0) // Storage: BTCRelay BestBlockHeight (r:1 w:0) diff --git a/crates/btc-relay/src/lib.rs b/crates/btc-relay/src/lib.rs index 21a9909fbc..238619ea4d 100644 --- a/crates/btc-relay/src/lib.rs +++ b/crates/btc-relay/src/lib.rs @@ -106,6 +106,90 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// One time function to initialize the BTC-Relay with the first block + /// + /// # Arguments + /// + /// * `block_header_bytes` - 80 byte raw Bitcoin block header. + /// * `block_height` - starting Bitcoin block height of the submitted block header. + /// + /// # + /// - Storage Reads: + /// - One storage read to check that parachain is not shutdown. O(1) + /// - One storage read to check if relayer authorization is disabled. O(1) + /// - One storage read to check if relayer is authorized. O(1) + /// - Storage Writes: + /// - One storage write to store block hash. O(1) + /// - One storage write to store block header. O(1) + /// - One storage write to initialize main chain. O(1) + /// - One storage write to store best block hash. O(1) + /// - One storage write to store best block height. O(1) + /// - Events: + /// - One event for initialization. + /// + /// Total Complexity: O(1) + /// # + #[pallet::weight(::WeightInfo::initialize())] + #[transactional] + pub fn initialize( + origin: OriginFor, + raw_block_header: RawBlockHeader, + block_height: u32, + ) -> DispatchResultWithPostInfo { + let relayer = ensure_signed(origin)?; + + let block_header = Self::parse_raw_block_header(&raw_block_header)?; + Self::_initialize(relayer, block_header, block_height)?; + + // don't take tx fees on success + Ok(Pays::No.into()) + } + + /// Stores a single new block header + /// + /// # Arguments + /// + /// * `raw_block_header` - 80 byte raw Bitcoin block header. + /// + /// # + /// Key: C (len of chains), P (len of positions) + /// - Storage Reads: + /// - One storage read to check that parachain is not shutdown. O(1) + /// - One storage read to check if relayer authorization is disabled. O(1) + /// - One storage read to check if relayer is authorized. O(1) + /// - One storage read to check if block header is stored. O(1) + /// - One storage read to retrieve parent block hash. O(1) + /// - One storage read to check if difficulty check is disabled. O(1) + /// - One storage read to retrieve last re-target. O(1) + /// - One storage read to retrieve all Chains. O(C) + /// - Storage Writes: + /// - One storage write to store block hash. O(1) + /// - One storage write to store block header. O(1) + /// - One storage mutate to extend main chain. O(1) + /// - One storage write to store best block hash. O(1) + /// - One storage write to store best block height. O(1) + /// - Notable Computation: + /// - O(P) sort to reorg chains. + /// - Events: + /// - One event for block stored (fork or extension). + /// + /// Total Complexity: O(C + P) + /// # + #[pallet::weight(::WeightInfo::store_block_header())] + #[transactional] + pub fn store_block_header( + origin: OriginFor, + raw_block_header: RawBlockHeader, + ) -> DispatchResultWithPostInfo { + let relayer = ensure_signed(origin)?; + + let block_header = Self::parse_raw_block_header(&raw_block_header)?; + Self::_store_block_header(&relayer, block_header)?; + + // don't take tx fees on success + Ok(Pays::No.into()) + } + /// Verifies the inclusion of `tx_id` into the relay, and validates the given raw Bitcoin transaction, according /// to the supported transaction format (see ) /// @@ -244,8 +328,6 @@ pub mod pallet { InvalidHeaderSize, /// Block already stored DuplicateBlock, - /// Block already stored and is not head - OutdatedBlock, /// Previous block hash not found PrevBlock, /// Invalid chain ID @@ -453,7 +535,7 @@ pub const MAIN_CHAIN_ID: u32 = 0; #[cfg_attr(test, mockable)] impl Pallet { - pub fn initialize(relayer: T::AccountId, basic_block_header: BlockHeader, block_height: u32) -> DispatchResult { + pub fn _initialize(relayer: T::AccountId, basic_block_header: BlockHeader, block_height: u32) -> DispatchResult { // Check if BTC-Relay was already initialized ensure!(!Self::best_block_exists(), Error::::AlreadyInitialized); @@ -481,22 +563,7 @@ impl Pallet { Ok(()) } - /// wraps _store_block_header, but differentiates between DuplicateError and OutdatedError - #[transactional] - pub fn store_block_header(relayer: &T::AccountId, basic_block_header: BlockHeader) -> DispatchResult { - let ret = Self::_store_block_header(relayer, basic_block_header); - if let Err(err) = ret { - if err == DispatchError::from(Error::::DuplicateBlock) { - // if this is not the chain head, return OutdatedBlock error - let this_header_hash = basic_block_header.hash; - let best_header_hash = Self::get_best_block(); - ensure!(this_header_hash == best_header_hash, Error::::OutdatedBlock); - } - } - ret - } - - fn _store_block_header(relayer: &T::AccountId, basic_block_header: BlockHeader) -> DispatchResult { + pub fn _store_block_header(relayer: &T::AccountId, basic_block_header: BlockHeader) -> DispatchResult { let prev_header = Self::get_block_header_from_hash(basic_block_header.hash_prev_block)?; // check if the prev block is the highest block in the chain diff --git a/crates/btc-relay/src/tests.rs b/crates/btc-relay/src/tests.rs index 9adfaac6ef..183e8db298 100644 --- a/crates/btc-relay/src/tests.rs +++ b/crates/btc-relay/src/tests.rs @@ -108,7 +108,7 @@ fn initialize_once_succeeds() { let block_header_hash = block_header.hash; BTCRelay::best_block_exists.mock_safe(|| MockResult::Return(false)); - assert_ok!(BTCRelay::initialize(relayer_id, block_header, block_height)); + assert_ok!(BTCRelay::_initialize(relayer_id, block_header, block_height)); System::assert_has_event(TestEvent::BTCRelay(Event::Initialized { block_height, @@ -127,7 +127,7 @@ fn initialize_best_block_already_set_fails() { BTCRelay::best_block_exists.mock_safe(|| MockResult::Return(true)); assert_err!( - BTCRelay::initialize(relayer_id, sample_block_header(), block_height), + BTCRelay::_initialize(relayer_id, sample_block_header(), block_height), TestError::AlreadyInitialized ); }) @@ -142,7 +142,7 @@ fn initialize_with_invalid_difficulty_period_should_fail() { BTCRelay::best_block_exists.mock_safe(|| MockResult::Return(false)); assert_err!( - BTCRelay::initialize(relayer_id, block_header, block_height), + BTCRelay::_initialize(relayer_id, block_header, block_height), TestError::InvalidStartHeight ); }) @@ -157,7 +157,7 @@ fn initialize_with_valid_difficulty_period_should_succeed() { let block_header_hash = block_header.hash; BTCRelay::best_block_exists.mock_safe(|| MockResult::Return(false)); - assert_ok!(BTCRelay::initialize(relayer_id, block_header, block_height)); + assert_ok!(BTCRelay::_initialize(relayer_id, block_header, block_height)); System::assert_has_event(TestEvent::BTCRelay(Event::Initialized { block_height, @@ -191,7 +191,7 @@ fn store_block_header_on_mainchain_succeeds() { BTCRelay::get_block_chain_from_id.mock_safe(move |_: u32| MockResult::Return(Ok(prev_blockchain.clone()))); let block_header_hash = block_header.hash; - assert_ok!(BTCRelay::store_block_header(&3, rich_header.block_header)); + assert_ok!(BTCRelay::_store_block_header(&3, rich_header.block_header)); let store_main_event = TestEvent::BTCRelay(Event::StoreMainChainHeader { block_height: block_height + 1, @@ -229,7 +229,7 @@ fn store_block_header_on_fork_succeeds() { // simulate that initialize has been called BTCRelay::increment_chain_counter().unwrap(); - assert_ok!(BTCRelay::store_block_header(&3, block_header)); + assert_ok!(BTCRelay::_store_block_header(&3, block_header)); let store_fork_event = TestEvent::BTCRelay(Event::StoreForkHeader { chain_id, @@ -363,7 +363,7 @@ mod store_block_header_tests { genesis.update_hash().unwrap(); let block_height = 0; - assert_ok!(BTCRelay::initialize(3, genesis, block_height)); + assert_ok!(BTCRelay::_initialize(3, genesis, block_height)); // second block to the mainchain - otherwise we can't create a fork let a2 = from_prev(12, genesis.hash); @@ -407,7 +407,7 @@ mod store_block_header_tests { fn store_header_and_check_invariants(block: &BlockHeader) { check_store_block_header_invariants(); - assert_ok!(BTCRelay::store_block_header(&3, block.clone())); + assert_ok!(BTCRelay::_store_block_header(&3, block.clone())); Security::set_active_block_number( ext::security::active_block_number::() + BTCRelay::parachain_confirmations(), ); @@ -434,7 +434,7 @@ mod store_block_header_tests { .collect::>(); let block_height = 0; - assert_ok!(BTCRelay::initialize(3, final_chain[0].clone(), block_height)); + assert_ok!(BTCRelay::_initialize(3, final_chain[0].clone(), block_height)); assert_best_block(&final_chain[0], block_height); // submit a temporary block such that final_chain[1] will be considered a fork @@ -503,7 +503,7 @@ mod store_block_header_tests { BTCRelay::verify_block_header.mock_safe(|_, _, _| MockResult::Return(Ok(()))); let genesis = sample_block_header(); - assert_ok!(BTCRelay::initialize(3, genesis, 0)); + assert_ok!(BTCRelay::_initialize(3, genesis, 0)); // store some blocks so that we don't get confirmation errors let blocks = successors(Some(genesis.clone()), |prev| Some(from_prev(0, prev.hash))).skip(1); @@ -523,7 +523,7 @@ mod store_block_header_tests { let relayer_id = 3; let genesis = parse_from_hex("03000000e6a65096db85d2ed2dfab33dea50b338341e1aeb5d0ce411000000000000000098420532fa55a0bca5f043f8f8f16a2b73761e822178692cb99ced039e2a32a0ea3f97558e4116183a9cc34a"); - assert_ok!(BTCRelay::initialize(relayer_id, genesis, 0)); // 363730 + assert_ok!(BTCRelay::_initialize(relayer_id, genesis, 0)); // 363730 let fork_blocks: Vec = vec![ "020000009e576e5a71f5af67e4dac515f8f3c02e536bb452d720a3060000000000000000699ff8e92806063b23a2e70009ec8d10cfc97a9a8a9a508f1b6b189b06845c7d644097558e411618b943d647", @@ -592,7 +592,7 @@ mod store_block_header_tests { fn store_block_header_no_prev_block_fails() { run_test(|| { assert_err!( - BTCRelay::store_block_header(&3, sample_block_header()), + BTCRelay::_store_block_header(&3, sample_block_header()), TestError::BlockNotFound, ); }) @@ -1620,7 +1620,7 @@ fn store_generated_block_headers() { run_test(|| { let mut last_block = BlockBuilder::new().with_coinbase(&miner, 50, 0).mine(target).unwrap(); let last_block_header = BTCRelay::parse_raw_block_header(&get_header(&last_block)).unwrap(); - assert_ok!(BTCRelay::initialize(3, last_block_header, 0)); + assert_ok!(BTCRelay::_initialize(3, last_block_header, 0)); for i in 1..20 { last_block = BlockBuilder::new() .with_coinbase(&miner, 50, i) @@ -1629,7 +1629,7 @@ fn store_generated_block_headers() { .unwrap(); let raw_header = get_header(&last_block); let block_header = parse_block_header(&raw_header).unwrap(); - assert_ok!(BTCRelay::store_block_header(&3, block_header)); + assert_ok!(BTCRelay::_store_block_header(&3, block_header)); } let main_chain: BlockChain = BTCRelay::get_block_chain_from_id(crate::MAIN_CHAIN_ID).unwrap(); assert_eq!(main_chain.start_height, 0); diff --git a/crates/issue/src/benchmarking.rs b/crates/issue/src/benchmarking.rs index a06d6f728a..748398637b 100644 --- a/crates/issue/src/benchmarking.rs +++ b/crates/issue/src/benchmarking.rs @@ -86,7 +86,7 @@ fn mine_blocks(end_height: u32) { let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); Security::::set_active_block_number(1u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); + BtcRelay::::_initialize(relayer_id.clone(), block_header, height).unwrap(); let transaction = TransactionBuilder::new() .with_version(2) @@ -121,7 +121,7 @@ fn mine_blocks(end_height: u32) { let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); + BtcRelay::::_store_block_header(&relayer_id, block_header).unwrap(); } } @@ -154,7 +154,7 @@ benchmarks! { let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); Security::::set_active_block_number(1u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); + BtcRelay::::_initialize(relayer_id.clone(), block_header, height).unwrap(); let vault_btc_address = BtcAddress::dummy(); @@ -189,7 +189,7 @@ benchmarks! { let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); + BtcRelay::::_store_block_header(&relayer_id, block_header).unwrap(); Security::::set_active_block_number(Security::::active_block_number() + BtcRelay::::parachain_confirmations()); }: _(RawOrigin::Signed(origin), amount, vault_id) @@ -234,7 +234,7 @@ benchmarks! { let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); Security::::set_active_block_number(1u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); + BtcRelay::::_initialize(relayer_id.clone(), block_header, height).unwrap(); let transaction = TransactionBuilder::new() .with_version(2) @@ -273,7 +273,7 @@ benchmarks! { let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); + BtcRelay::::_store_block_header(&relayer_id, block_header).unwrap(); Security::::set_active_block_number(Security::::active_block_number() + BtcRelay::::parachain_confirmations()); VaultRegistry::::_set_system_collateral_ceiling(get_currency_pair::(), 1_000_000_000u32.into()); diff --git a/crates/redeem/src/benchmarking.rs b/crates/redeem/src/benchmarking.rs index b632711a39..3d5b280059 100644 --- a/crates/redeem/src/benchmarking.rs +++ b/crates/redeem/src/benchmarking.rs @@ -98,7 +98,7 @@ fn mine_blocks(end_height: u32) { let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); Security::::set_active_block_number(1u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); + BtcRelay::::_initialize(relayer_id.clone(), block_header, height).unwrap(); let transaction = TransactionBuilder::new() .with_version(2) @@ -133,7 +133,7 @@ fn mine_blocks(end_height: u32) { let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); + BtcRelay::::_store_block_header(&relayer_id, block_header).unwrap(); } } @@ -261,7 +261,7 @@ benchmarks! { let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); Security::::set_active_block_number(1u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); + BtcRelay::::_initialize(relayer_id.clone(), block_header, height).unwrap(); let value = 0; let transaction = TransactionBuilder::new() @@ -301,7 +301,7 @@ benchmarks! { let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); + BtcRelay::::_store_block_header(&relayer_id, block_header).unwrap(); Security::::set_active_block_number(Security::::active_block_number() + BtcRelay::::parachain_confirmations() + 1u32.into()); diff --git a/crates/refund/src/benchmarking.rs b/crates/refund/src/benchmarking.rs index 513d2203f0..a9825fe16c 100644 --- a/crates/refund/src/benchmarking.rs +++ b/crates/refund/src/benchmarking.rs @@ -73,7 +73,7 @@ benchmarks! { let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); Security::::set_active_block_number(1u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); + BtcRelay::::_initialize(relayer_id.clone(), block_header, height).unwrap(); let value = 0; let transaction = TransactionBuilder::new() @@ -113,7 +113,7 @@ benchmarks! { let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); + BtcRelay::::_store_block_header(&relayer_id, block_header).unwrap(); Security::::set_active_block_number(Security::::active_block_number() + BtcRelay::::parachain_confirmations() + 1u32.into()); diff --git a/crates/relay/Cargo.toml b/crates/relay/Cargo.toml deleted file mode 100644 index 7666969a11..0000000000 --- a/crates/relay/Cargo.toml +++ /dev/null @@ -1,97 +0,0 @@ -[package] -name = "relay" -version = "1.2.0" -authors = ["Interlay Ltd"] -edition = "2021" - -[dependencies] -serde = { version = "1.0.130", default-features = false, features = ["derive"], optional = true } -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -scale-info = { version = "2.0.0", default-features = false, features = ["derive"] } - -# Substrate dependencies -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false, optional = true } - -# Parachain dependencies -bitcoin = { path = "../bitcoin", default-features = false } -btc-relay = { path = "../btc-relay", default-features = false } -oracle = { path = "../oracle", default-features = false } -fee = { path = "../fee", default-features = false } -redeem = { path = "../redeem", default-features = false } -replace = { path = "../replace", default-features = false } -security = { path = "../security", default-features = false } -currency = { path = "../currency", default-features = false } -vault-registry = { path = "../vault-registry", default-features = false } -refund = { path = "../refund", default-features = false } -nomination = { path = "../../crates/nomination", default-features = false } -primitives = { package = "interbtc-primitives", path = "../../primitives", default-features = false } - -# Orml dependencies -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "e1caed6585f97110c2fd6f5fbcde9eea011457df", default-features = false, optional = true } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "e1caed6585f97110c2fd6f5fbcde9eea011457df", default-features = false, optional = true } - -[dev-dependencies] -mocktopus = "0.7.0" -hex = "0.4.2" -frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" } - -# Parachain dependencies -primitives = { package = "interbtc-primitives", path = "../../primitives" } -reward = { path = "../reward" } -staking = { path = "../staking" } - -# Orml dependencies -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "e1caed6585f97110c2fd6f5fbcde9eea011457df" } -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", rev = "e1caed6585f97110c2fd6f5fbcde9eea011457df" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - - "sp-io/std", - "sp-core/std", - "sp-std/std", - "sp-arithmetic/std", - "sp-runtime/std", - - "frame-support/std", - "frame-system/std", - "frame-benchmarking/std", - - "bitcoin/std", - "btc-relay/std", - "oracle/std", - "fee/std", - "redeem/std", - "replace/std", - "security/std", - "currency/std", - "vault-registry/std", - "refund/std", - "nomination/std", - "primitives/std", - - "orml-tokens/std", - "orml-traits/std", -] -runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - - "bitcoin/runtime-benchmarks", - - "orml-tokens", - "orml-traits", -] diff --git a/crates/relay/README.md b/crates/relay/README.md deleted file mode 100644 index 5ce2f6ffe0..0000000000 --- a/crates/relay/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Relay Module - -High-level functionality and state associated with block relaying and theft reporting. - -## Installation - -Run `cargo build` from the root folder of this directory. - -## Testing - -Run `cargo test` from the root folder of this directory. diff --git a/crates/relay/rpc/Cargo.toml b/crates/relay/rpc/Cargo.toml deleted file mode 100644 index 9482e46c06..0000000000 --- a/crates/relay/rpc/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "module-relay-rpc" -version = "1.2.0" -authors = ["Interlay Ltd"] -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0" } -jsonrpsee = { version = "0.13.0", features = ["server", "macros"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" } -module-relay-rpc-runtime-api = { path = "runtime-api" } diff --git a/crates/relay/rpc/runtime-api/Cargo.toml b/crates/relay/rpc/runtime-api/Cargo.toml deleted file mode 100644 index 1264313d1c..0000000000 --- a/crates/relay/rpc/runtime-api/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "module-relay-rpc-runtime-api" -version = "1.2.0" -authors = ["Interlay Ltd"] -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } -sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false } - -[features] -default = ["std"] -std = [ - "codec/std", - "frame-support/std", - "sp-api/std", - "sp-std/std", -] diff --git a/crates/relay/rpc/runtime-api/src/lib.rs b/crates/relay/rpc/runtime-api/src/lib.rs deleted file mode 100644 index 461478efec..0000000000 --- a/crates/relay/rpc/runtime-api/src/lib.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Runtime API definition for the Relay Pallet. - -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::Codec; -use frame_support::dispatch::DispatchResult; -use sp_std::prelude::Vec; - -sp_api::decl_runtime_apis! { - pub trait RelayApi where - AccountId: Codec, - { - fn is_transaction_invalid( - vault_id: AccountId, raw_tx: Vec - ) -> DispatchResult; - } -} diff --git a/crates/relay/rpc/src/lib.rs b/crates/relay/rpc/src/lib.rs deleted file mode 100644 index 9798ba77f2..0000000000 --- a/crates/relay/rpc/src/lib.rs +++ /dev/null @@ -1,67 +0,0 @@ -//! RPC interface for the Relay Pallet. - -use codec::Codec; -use jsonrpsee::{ - core::{async_trait, Error as JsonRpseeError, RpcResult}, - proc_macros::rpc, - types::error::{CallError, ErrorCode, ErrorObject}, -}; -use sp_api::ProvideRuntimeApi; -use sp_blockchain::HeaderBackend; -use sp_runtime::{generic::BlockId, traits::Block as BlockT}; -use std::sync::Arc; - -pub use module_relay_rpc_runtime_api::RelayApi as RelayRuntimeApi; - -#[rpc(client, server)] -pub trait RelayApi { - #[method(name = "relay_isTransactionInvalid")] - fn is_transaction_invalid(&self, vault_id: VaultId, raw_tx: Vec, at: Option) -> RpcResult<()>; -} - -fn internal_err(message: T) -> JsonRpseeError { - JsonRpseeError::Call(CallError::Custom(ErrorObject::owned( - ErrorCode::InternalError.code(), - message.to_string(), - None::<()>, - ))) -} - -/// A struct that implements the [`RelayApi`]. -pub struct Relay { - client: Arc, - _marker: std::marker::PhantomData, -} - -impl Relay { - /// Create new `Relay` with the given reference to the client. - pub fn new(client: Arc) -> Self { - Relay { - client, - _marker: Default::default(), - } - } -} - -#[async_trait] -impl RelayApiServer<::Hash, VaultId> for Relay -where - Block: BlockT, - C: Send + Sync + 'static + ProvideRuntimeApi + HeaderBackend, - C::Api: RelayRuntimeApi, - VaultId: Codec, -{ - fn is_transaction_invalid( - &self, - vault_id: VaultId, - raw_tx: Vec, - at: Option<::Hash>, - ) -> RpcResult<()> { - let api = self.client.runtime_api(); - let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash)); - - api.is_transaction_invalid(&at, vault_id, raw_tx) - .map_err(|err| internal_err(format!("Runtime error: {:?}", err)))? - .map_err(|err| internal_err(format!("Transaction is valid: {:?}", err))) - } -} diff --git a/crates/relay/src/benchmarking.rs b/crates/relay/src/benchmarking.rs deleted file mode 100644 index 446a03dee0..0000000000 --- a/crates/relay/src/benchmarking.rs +++ /dev/null @@ -1,200 +0,0 @@ -use super::*; -use crate::types::BalanceOf; -use bitcoin::{ - formatter::{Formattable, TryFormattable}, - types::{ - BlockBuilder, H256Le, RawBlockHeader, TransactionBuilder, TransactionInputBuilder, TransactionInputSource, - TransactionOutput, - }, -}; -use btc_relay::{BtcAddress, BtcPublicKey, Pallet as BtcRelay}; -use currency::{ - getters::{get_relay_chain_currency_id as get_collateral_currency_id, *}, - Amount, -}; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite}; -use frame_support::{assert_ok, traits::Get}; -use frame_system::RawOrigin; -use oracle::Pallet as Oracle; -use orml_traits::MultiCurrency; -use primitives::{CurrencyId, VaultId}; -use security::Pallet as Security; -use sp_core::{H160, U256}; -use sp_runtime::traits::One; -use sp_std::prelude::*; -use vault_registry::{ - types::{Vault, Wallet}, - Pallet as VaultRegistry, -}; - -#[cfg(test)] -use crate::Pallet as Relay; - -type UnsignedFixedPoint = ::UnsignedFixedPoint; - -fn deposit_tokens(currency_id: CurrencyId, account_id: &T::AccountId, amount: BalanceOf) { - assert_ok!(>::deposit(currency_id, account_id, amount)); -} - -fn mint_collateral(account_id: &T::AccountId, amount: BalanceOf) { - deposit_tokens::(get_collateral_currency_id::(), account_id, amount); - deposit_tokens::(get_native_currency_id::(), account_id, amount); -} - -fn register_public_key(vault_id: DefaultVaultId) { - let origin = RawOrigin::Signed(vault_id.account_id.clone()); - assert_ok!(VaultRegistry::::register_public_key( - origin.into(), - BtcPublicKey::dummy() - )); -} - -benchmarks! { - - initialize { - let height = 0u32; - let origin: T::AccountId = account("Origin", 0, 0); - let stake = 100u32; - - let address = BtcAddress::P2PKH(H160::from([0; 20])); - let block = BlockBuilder::new() - .with_version(4) - .with_coinbase(&address, 50, 3) - .with_timestamp(1588813835) - .mine(U256::from(2).pow(254.into())).unwrap(); - let block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); - }: _(RawOrigin::Signed(origin), block_header, height) - - store_block_header { - let origin: T::AccountId = account("Origin", 0, 0); - - let address = BtcAddress::P2PKH(H160::from([0; 20])); - let height = 0; - let stake = 100u32; - - let init_block = BlockBuilder::new() - .with_version(4) - .with_coinbase(&address, 50, 3) - .with_timestamp(1588813835) - .mine(U256::from(2).pow(254.into())).unwrap(); - - let init_block_hash = init_block.header.hash; - let raw_block_header = RawBlockHeader::from_bytes(&init_block.header.try_format().unwrap()) - .expect("could not serialize block header"); - let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - - BtcRelay::::initialize(origin.clone(), block_header, height).unwrap(); - - let block = BlockBuilder::new() - .with_previous_hash(init_block_hash) - .with_version(4) - .with_coinbase(&address, 50, 3) - .with_timestamp(1588814835) - .mine(U256::from(2).pow(254.into())).unwrap(); - - let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()) - .expect("could not serialize block header"); - - }: _(RawOrigin::Signed(origin), raw_block_header) - - report_vault_theft { - let origin: T::AccountId = account("Origin", 0, 0); - let relayer_id: T::AccountId = account("Relayer", 0, 0); - - let vault_address = BtcAddress::P2PKH(H160::from_slice(&[ - 126, 125, 148, 208, 221, 194, 29, 131, 191, 188, 252, 119, 152, 228, 84, 126, 223, 8, - 50, 170, - ])); - - let address = BtcAddress::P2PKH(H160([0; 20])); - - let vault_id: VaultId = VaultId::new( - account("Vault", 0, 0), - T::GetGriefingCollateralCurrencyId::get(), - ::GetWrappedCurrencyId::get() - ); - - register_public_key::(vault_id.clone()); - - let mut vault = Vault { - wallet: Wallet::new(), - id: vault_id.clone(), - ..Vault::new(vault_id.clone()) - }; - vault.wallet.add_btc_address(vault_address); - VaultRegistry::::insert_vault( - &vault_id, - vault - ); - - VaultRegistry::::_set_liquidation_collateral_threshold(vault_id.currencies.clone(), UnsignedFixedPoint::::one()); - VaultRegistry::::_set_system_collateral_ceiling(vault_id.currencies.clone(), 1_000_000_000u32.into()); - - mint_collateral::(&vault_id.account_id, 1000u32.into()); - assert_ok!(VaultRegistry::::try_deposit_collateral(&vault_id, &Amount::new(1000u32.into(), T::GetGriefingCollateralCurrencyId::get()))); - - let height = 0; - let block = BlockBuilder::new() - .with_version(4) - .with_coinbase(&address, 50, 3) - .with_timestamp(1588813835) - .mine(U256::from(2).pow(254.into())).unwrap(); - - let block_hash = block.header.hash; - let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); - let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - - Security::::set_active_block_number(1u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); - - let value = 0; - let transaction = TransactionBuilder::new() - .with_version(2) - .add_input( - TransactionInputBuilder::new() - .with_sequence(4294967295) - .with_source(TransactionInputSource::FromOutput(H256Le::from_bytes_le(&[ - 193, 80, 65, 160, 109, 235, 107, 56, 24, 176, 34, 250, 197, 88, 218, 76, - 226, 9, 127, 8, 96, 200, 246, 66, 16, 91, 186, 217, 210, 155, 224, 42, - ]), 1)) - .with_script(&[ - 73, 48, 70, 2, 33, 0, 207, 210, 162, 211, 50, 178, 154, 220, 225, 25, 197, - 90, 159, 173, 211, 192, 115, 51, 32, 36, 183, 226, 114, 81, 62, 81, 98, 60, - 161, 89, 147, 72, 2, 33, 0, 155, 72, 45, 127, 123, 77, 71, 154, 255, 98, - 189, 205, 174, 165, 70, 103, 115, 125, 86, 248, 212, 214, 61, 208, 62, 195, - 239, 101, 30, 217, 162, 84, 1, 33, 3, 37, 248, 176, 57, 161, 24, 97, 101, - 156, 155, 240, 63, 67, 252, 78, 160, 85, 243, 167, 28, 214, 12, 123, 31, - 212, 116, 171, 87, 143, 153, 119, 250, - ]) - .build(), - ) - .add_output(TransactionOutput::payment(value.into(), &address)) - .build(); - - let block = BlockBuilder::new() - .with_previous_hash(block_hash) - .with_version(4) - .with_coinbase(&address, 50, 3) - .with_timestamp(1588813835) - .add_transaction(transaction.clone()) - .mine(U256::from(2).pow(254.into())).unwrap(); - - let tx_id = transaction.tx_id(); - let proof = block.merkle_proof(&[tx_id]).unwrap().try_format().unwrap(); - let raw_tx = transaction.format_with(true); - - let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); - let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); - Security::::set_active_block_number(Security::::active_block_number() + - BtcRelay::::parachain_confirmations() + 1u32.into()); - - Oracle::::_set_exchange_rate( - get_collateral_currency_id::(), - ::UnsignedFixedPoint::one() - ).unwrap(); - }: _(RawOrigin::Signed(origin), vault_id, proof, raw_tx) -} - -impl_benchmark_test_suite!(Relay, crate::mock::ExtBuilder::build_with(|_| {}), crate::mock::Test); diff --git a/crates/relay/src/default_weights.rs b/crates/relay/src/default_weights.rs deleted file mode 100644 index b421d084db..0000000000 --- a/crates/relay/src/default_weights.rs +++ /dev/null @@ -1,178 +0,0 @@ -//! Autogenerated weights for relay -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-09-07, STEPS: `100`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 - -// Executed Command: -// target/release/interbtc-standalone -// benchmark -// --chain -// dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet -// relay -// --extrinsic -// * -// --steps -// 100 -// --repeat -// 10 -// --output -// crates/relay/src/default_weights.rs -// --template -// .deploy/weight-template.hbs - - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for relay. -pub trait WeightInfo { - fn initialize() -> Weight; - fn store_block_header() -> Weight; - fn report_vault_theft() -> Weight; -} - -/// Weights for relay using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - // Storage: Security ParachainStatus (r:1 w:0) - // Storage: BTCRelay BestBlock (r:1 w:1) - // Storage: BTCRelay ChainCounter (r:1 w:1) - // Storage: BTCRelay Chains (r:1 w:1) - // Storage: Security ActiveBlockCount (r:1 w:0) - // Storage: BTCRelay ChainsHashes (r:0 w:1) - // Storage: BTCRelay StartBlockHeight (r:0 w:1) - // Storage: BTCRelay BestBlockHeight (r:0 w:1) - // Storage: BTCRelay ChainsIndex (r:0 w:1) - // Storage: BTCRelay BlockHeaders (r:0 w:1) - fn initialize() -> Weight { - (52_878_000 as Weight) - .saturating_add(T::DbWeight::get().reads(5 as Weight)) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) - } - // Storage: Security ParachainStatus (r:1 w:0) - // Storage: BTCRelay BlockHeaders (r:2 w:1) - // Storage: BTCRelay ChainsIndex (r:1 w:1) - // Storage: BTCRelay DisableDifficultyCheck (r:1 w:0) - // Storage: BTCRelay ChainsHashes (r:1 w:1) - // Storage: Security ActiveBlockCount (r:1 w:0) - // Storage: BTCRelay BestBlock (r:0 w:1) - // Storage: BTCRelay BestBlockHeight (r:0 w:1) - fn store_block_header() -> Weight { - (68_306_000 as Weight) - .saturating_add(T::DbWeight::get().reads(7 as Weight)) - .saturating_add(T::DbWeight::get().writes(5 as Weight)) - } - // Storage: Security ParachainStatus (r:1 w:0) - // Storage: Relay TheftReports (r:1 w:1) - // Storage: BTCRelay DisableInclusionCheck (r:1 w:0) - // Storage: BTCRelay BestBlockHeight (r:1 w:0) - // Storage: BTCRelay Chains (r:1 w:0) - // Storage: BTCRelay BlockHeaders (r:1 w:0) - // Storage: BTCRelay StableBitcoinConfirmations (r:1 w:0) - // Storage: Security ActiveBlockCount (r:1 w:0) - // Storage: BTCRelay StableParachainConfirmations (r:1 w:0) - // Storage: VaultRegistry Vaults (r:1 w:1) - // Storage: Staking Nonce (r:1 w:0) - // Storage: Staking TotalCurrentStake (r:1 w:1) - // Storage: Staking Stake (r:1 w:1) - // Storage: Staking SlashPerToken (r:1 w:0) - // Storage: Staking SlashTally (r:1 w:1) - // Storage: Fee TheftFee (r:1 w:0) - // Storage: Fee TheftFeeMax (r:1 w:0) - // Storage: Oracle Aggregate (r:1 w:0) - // Storage: Tokens Accounts (r:2 w:2) - // Storage: VaultRegistry TotalUserVaultCollateral (r:1 w:1) - // Storage: Staking TotalStake (r:1 w:1) - // Storage: Staking RewardTally (r:1 w:1) - // Storage: Staking RewardPerToken (r:1 w:0) - // Storage: System Account (r:2 w:1) - // Storage: VaultRegistry SecureCollateralThreshold (r:1 w:0) - // Storage: VaultRegistry LiquidationVaultAccountId (r:1 w:0) - // Storage: VaultRegistry LiquidationVault (r:1 w:1) - // Storage: Rewards Stake (r:1 w:1) - // Storage: Rewards TotalStake (r:1 w:1) - // Storage: Rewards RewardTally (r:1 w:1) - // Storage: Rewards RewardPerToken (r:1 w:0) - fn report_vault_theft() -> Weight { - (478_713_000 as Weight) - .saturating_add(T::DbWeight::get().reads(33 as Weight)) - .saturating_add(T::DbWeight::get().writes(15 as Weight)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - // Storage: Security ParachainStatus (r:1 w:0) - // Storage: BTCRelay BestBlock (r:1 w:1) - // Storage: BTCRelay ChainCounter (r:1 w:1) - // Storage: BTCRelay Chains (r:1 w:1) - // Storage: Security ActiveBlockCount (r:1 w:0) - // Storage: BTCRelay ChainsHashes (r:0 w:1) - // Storage: BTCRelay StartBlockHeight (r:0 w:1) - // Storage: BTCRelay BestBlockHeight (r:0 w:1) - // Storage: BTCRelay ChainsIndex (r:0 w:1) - // Storage: BTCRelay BlockHeaders (r:0 w:1) - fn initialize() -> Weight { - (52_878_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(5 as Weight)) - .saturating_add(RocksDbWeight::get().writes(8 as Weight)) - } - // Storage: Security ParachainStatus (r:1 w:0) - // Storage: BTCRelay BlockHeaders (r:2 w:1) - // Storage: BTCRelay ChainsIndex (r:1 w:1) - // Storage: BTCRelay DisableDifficultyCheck (r:1 w:0) - // Storage: BTCRelay ChainsHashes (r:1 w:1) - // Storage: Security ActiveBlockCount (r:1 w:0) - // Storage: BTCRelay BestBlock (r:0 w:1) - // Storage: BTCRelay BestBlockHeight (r:0 w:1) - fn store_block_header() -> Weight { - (68_306_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(7 as Weight)) - .saturating_add(RocksDbWeight::get().writes(5 as Weight)) - } - // Storage: Security ParachainStatus (r:1 w:0) - // Storage: Relay TheftReports (r:1 w:1) - // Storage: BTCRelay DisableInclusionCheck (r:1 w:0) - // Storage: BTCRelay BestBlockHeight (r:1 w:0) - // Storage: BTCRelay Chains (r:1 w:0) - // Storage: BTCRelay BlockHeaders (r:1 w:0) - // Storage: BTCRelay StableBitcoinConfirmations (r:1 w:0) - // Storage: Security ActiveBlockCount (r:1 w:0) - // Storage: BTCRelay StableParachainConfirmations (r:1 w:0) - // Storage: VaultRegistry Vaults (r:1 w:1) - // Storage: Staking Nonce (r:1 w:0) - // Storage: Staking TotalCurrentStake (r:1 w:1) - // Storage: Staking Stake (r:1 w:1) - // Storage: Staking SlashPerToken (r:1 w:0) - // Storage: Staking SlashTally (r:1 w:1) - // Storage: Fee TheftFee (r:1 w:0) - // Storage: Fee TheftFeeMax (r:1 w:0) - // Storage: Oracle Aggregate (r:1 w:0) - // Storage: Tokens Accounts (r:2 w:2) - // Storage: VaultRegistry TotalUserVaultCollateral (r:1 w:1) - // Storage: Staking TotalStake (r:1 w:1) - // Storage: Staking RewardTally (r:1 w:1) - // Storage: Staking RewardPerToken (r:1 w:0) - // Storage: System Account (r:2 w:1) - // Storage: VaultRegistry SecureCollateralThreshold (r:1 w:0) - // Storage: VaultRegistry LiquidationVaultAccountId (r:1 w:0) - // Storage: VaultRegistry LiquidationVault (r:1 w:1) - // Storage: Rewards Stake (r:1 w:1) - // Storage: Rewards TotalStake (r:1 w:1) - // Storage: Rewards RewardTally (r:1 w:1) - // Storage: Rewards RewardPerToken (r:1 w:0) - fn report_vault_theft() -> Weight { - (478_713_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(33 as Weight)) - .saturating_add(RocksDbWeight::get().writes(15 as Weight)) - } -} - diff --git a/crates/relay/src/ext.rs b/crates/relay/src/ext.rs deleted file mode 100644 index 416d63b2ef..0000000000 --- a/crates/relay/src/ext.rs +++ /dev/null @@ -1,103 +0,0 @@ -#[cfg(test)] -use mocktopus::macros::mockable; - -#[cfg_attr(test, mockable)] -pub(crate) mod vault_registry { - use crate::DefaultVaultId; - use ::vault_registry::VaultStatus; - use frame_support::dispatch::{DispatchError, DispatchResult}; - use vault_registry::types::DefaultVault; - - pub fn get_active_vault_from_id( - vault_id: &DefaultVaultId, - ) -> Result, DispatchError> { - >::get_active_vault_from_id(vault_id) - } - - pub fn liquidate_theft_vault( - vault_id: &DefaultVaultId, - reporter_id: T::AccountId, - ) -> DispatchResult { - let _ = >::liquidate_vault_with_status( - vault_id, - VaultStatus::CommittedTheft, - Some(reporter_id), - )?; - Ok(()) - } -} - -#[cfg_attr(test, mockable)] -pub(crate) mod btc_relay { - use bitcoin::types::{BlockHeader, H256Le, MerkleProof, RawBlockHeader}; - use frame_support::dispatch::DispatchResult; - use sp_runtime::DispatchError; - - pub fn initialize( - relayer: T::AccountId, - block_header: BlockHeader, - block_height: u32, - ) -> DispatchResult { - >::initialize(relayer, block_header, block_height) - } - - pub fn store_block_header(relayer: &T::AccountId, block_header: BlockHeader) -> DispatchResult { - >::store_block_header(relayer, block_header) - } - - pub(crate) fn verify_transaction_inclusion( - tx_id: H256Le, - merkle_proof: MerkleProof, - ) -> DispatchResult { - >::_verify_transaction_inclusion(tx_id, merkle_proof, None) - } - - pub fn parse_raw_block_header( - raw_block_header: &RawBlockHeader, - ) -> Result { - >::parse_raw_block_header(raw_block_header) - } - - pub fn parse_merkle_proof(raw_merkle_proof: &[u8]) -> Result { - >::parse_merkle_proof(raw_merkle_proof) - } -} - -#[cfg_attr(test, mockable)] -pub(crate) mod redeem { - use frame_support::dispatch::DispatchError; - use redeem::types::DefaultRedeemRequest; - use sp_core::H256; - - pub(crate) fn get_open_or_completed_redeem_request_from_id( - id: &H256, - ) -> Result, DispatchError> { - >::get_open_or_completed_redeem_request_from_id(id) - } -} - -#[cfg_attr(test, mockable)] -pub(crate) mod replace { - use frame_support::dispatch::DispatchError; - use replace::types::DefaultReplaceRequest; - use sp_core::H256; - - pub(crate) fn get_open_or_completed_replace_request( - id: &H256, - ) -> Result, DispatchError> { - >::get_open_or_completed_replace_request(id) - } -} - -#[cfg_attr(test, mockable)] -pub(crate) mod refund { - use frame_support::dispatch::DispatchError; - use refund::types::DefaultRefundRequest; - use sp_core::H256; - - pub(crate) fn get_open_or_completed_refund_request_from_id( - id: &H256, - ) -> Result, DispatchError> { - >::get_open_or_completed_refund_request_from_id(id) - } -} diff --git a/crates/relay/src/lib.rs b/crates/relay/src/lib.rs deleted file mode 100644 index 8cd5fa1948..0000000000 --- a/crates/relay/src/lib.rs +++ /dev/null @@ -1,441 +0,0 @@ -//! # Relay Pallet -//! Based on the [specification](https://spec.interlay.io/spec/relay.html). - -#![deny(warnings)] -#![cfg_attr(test, feature(proc_macro_hygiene))] -#![cfg_attr(not(feature = "std"), no_std)] - -mod ext; -pub mod types; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -mod default_weights; -pub use default_weights::WeightInfo; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; - -#[cfg(test)] -extern crate mocktopus; - -#[cfg(test)] -use mocktopus::macros::mockable; - -pub use security; - -use crate::types::BalanceOf; -use bitcoin::{parser::parse_transaction, types::*}; -use btc_relay::{types::OpReturnPaymentData, BtcAddress}; -use frame_support::{dispatch::DispatchResult, ensure, transactional, weights::Pays}; -use frame_system::ensure_signed; -use sp_std::{ - convert::{TryFrom, TryInto}, - vec::Vec, -}; -use types::DefaultVaultId; -use vault_registry::Wallet; - -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - /// ## Configuration - /// The pallet's configuration trait. - #[pallet::config] - pub trait Config: - frame_system::Config - + security::Config - + vault_registry::Config - + btc_relay::Config - + redeem::Config - + replace::Config - + refund::Config - + fee::Config - { - /// The overarching event type. - type Event: From> + IsType<::Event>; - - /// Weight information for the extrinsics in this module. - type WeightInfo: WeightInfo; - } - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - VaultTheft { - vault_id: DefaultVaultId, - tx_id: H256Le, - }, - VaultDoublePayment { - vault_id: DefaultVaultId, - tx_id_1: H256Le, - tx_id_2: H256Le, - }, - } - - #[pallet::error] - pub enum Error { - /// Vault already reported - VaultAlreadyReported, - /// Vault BTC address not in transaction input - VaultNoInputToTransaction, - /// Valid redeem transaction - ValidRedeemTransaction, - /// Valid replace transaction - ValidReplaceTransaction, - /// Valid refund transaction - ValidRefundTransaction, - /// Valid merge transaction - ValidMergeTransaction, - /// Failed to parse transaction - InvalidTransaction, - /// Unable to convert value - TryIntoIntError, - /// Expected two unique transactions - DuplicateTransaction, - /// Expected duplicate OP_RETURN ids - ExpectedDuplicate, - } - - /// Mapping of Bitcoin transaction identifiers (SHA256 hashes) to account - /// identifiers of Vaults accused of theft. - #[pallet::storage] - #[pallet::getter(fn theft_report)] - pub(super) type TheftReports = - StorageDoubleMap<_, Blake2_128Concat, DefaultVaultId, Blake2_128Concat, H256Le, Option<()>, ValueQuery>; - - #[pallet::hooks] - impl Hooks for Pallet {} - - #[pallet::pallet] - pub struct Pallet(_); - - // The pallet's dispatchable functions. - #[pallet::call] - impl Pallet { - /// One time function to initialize the BTC-Relay with the first block - /// - /// # Arguments - /// - /// * `block_header_bytes` - 80 byte raw Bitcoin block header. - /// * `block_height` - starting Bitcoin block height of the submitted block header. - /// - /// # - /// - Storage Reads: - /// - One storage read to check that parachain is not shutdown. O(1) - /// - One storage read to check if relayer authorization is disabled. O(1) - /// - One storage read to check if relayer is authorized. O(1) - /// - Storage Writes: - /// - One storage write to store block hash. O(1) - /// - One storage write to store block header. O(1) - /// - One storage write to initialize main chain. O(1) - /// - One storage write to store best block hash. O(1) - /// - One storage write to store best block height. O(1) - /// - Events: - /// - One event for initialization. - /// - /// Total Complexity: O(1) - /// # - #[pallet::weight(::WeightInfo::initialize())] - #[transactional] - pub fn initialize( - origin: OriginFor, - raw_block_header: RawBlockHeader, - block_height: u32, - ) -> DispatchResultWithPostInfo { - let relayer = ensure_signed(origin)?; - - let block_header = ext::btc_relay::parse_raw_block_header::(&raw_block_header)?; - ext::btc_relay::initialize::(relayer, block_header, block_height)?; - - // don't take tx fees on success - Ok(Pays::No.into()) - } - - /// Stores a single new block header - /// - /// # Arguments - /// - /// * `raw_block_header` - 80 byte raw Bitcoin block header. - /// - /// # - /// Key: C (len of chains), P (len of positions) - /// - Storage Reads: - /// - One storage read to check that parachain is not shutdown. O(1) - /// - One storage read to check if relayer authorization is disabled. O(1) - /// - One storage read to check if relayer is authorized. O(1) - /// - One storage read to check if block header is stored. O(1) - /// - One storage read to retrieve parent block hash. O(1) - /// - One storage read to check if difficulty check is disabled. O(1) - /// - One storage read to retrieve last re-target. O(1) - /// - One storage read to retrieve all Chains. O(C) - /// - Storage Writes: - /// - One storage write to store block hash. O(1) - /// - One storage write to store block header. O(1) - /// - One storage mutate to extend main chain. O(1) - /// - One storage write to store best block hash. O(1) - /// - One storage write to store best block height. O(1) - /// - Notable Computation: - /// - O(P) sort to reorg chains. - /// - Events: - /// - One event for block stored (fork or extension). - /// - /// Total Complexity: O(C + P) - /// # - #[pallet::weight(::WeightInfo::store_block_header())] - #[transactional] - pub fn store_block_header( - origin: OriginFor, - raw_block_header: RawBlockHeader, - ) -> DispatchResultWithPostInfo { - let relayer = ensure_signed(origin)?; - - let block_header = ext::btc_relay::parse_raw_block_header::(&raw_block_header)?; - ext::btc_relay::store_block_header::(&relayer, block_header)?; - - // don't take tx fees on success - Ok(Pays::No.into()) - } - - /// Report misbehavior by a Vault, providing a fraud proof (malicious Bitcoin transaction - /// and the corresponding transaction inclusion proof). This fully slashes the Vault. - /// - /// # Arguments - /// - /// * `origin`: Any signed user. - /// * `vault_id`: The account of the vault to check. - /// * `raw_merkle_proof`: The proof of tx inclusion. - /// * `raw_tx`: The raw Bitcoin transaction. - #[pallet::weight(::WeightInfo::report_vault_theft())] - #[transactional] - pub fn report_vault_theft( - origin: OriginFor, - vault_id: DefaultVaultId, - raw_merkle_proof: Vec, - raw_tx: Vec, - ) -> DispatchResultWithPostInfo { - let reporter_id = ensure_signed(origin)?; - - let merkle_proof = ext::btc_relay::parse_merkle_proof::(&raw_merkle_proof)?; - let transaction = parse_transaction(raw_tx.as_slice()).map_err(|_| Error::::InvalidTransaction)?; - let tx_id = transaction.tx_id(); - - // throw if already reported - ensure!( - !>::contains_key(&vault_id, &tx_id), - Error::::VaultAlreadyReported, - ); - - ext::btc_relay::verify_transaction_inclusion::(tx_id, merkle_proof)?; - Self::_is_parsed_transaction_invalid(&vault_id, transaction)?; - - ext::vault_registry::liquidate_theft_vault::(&vault_id, reporter_id)?; - - >::mutate(&vault_id, &tx_id, |inner| { - let _ = inner.insert(()); - }); - - Self::deposit_event(Event::::VaultTheft { vault_id, tx_id }); - - // don't take tx fees on success - Ok(Pays::No.into()) - } - - /// Report Vault double payment, providing two fraud proofs (malicious Bitcoin transactions - /// and the corresponding transaction inclusion proofs). This fully slashes the Vault. - /// - /// This can be used for any multiple of payments, i.e., a vault making two, three, four, etc. payments - /// by proving just one double payment. - /// - /// # Arguments - /// - /// * `origin`: Any signed user. - /// * `vault_id`: The account of the vault to check. - /// * `raw_merkle_proofs`: The proofs of tx inclusion. - /// * `raw_txs`: The raw Bitcoin transactions. - #[pallet::weight(::WeightInfo::report_vault_theft())] - #[transactional] - pub fn report_vault_double_payment( - origin: OriginFor, - vault_id: DefaultVaultId, - raw_merkle_proofs: (Vec, Vec), - raw_txs: (Vec, Vec), - ) -> DispatchResultWithPostInfo { - let reporter_id = ensure_signed(origin)?; - - // Attention: this test fails early before parsing but does NOT ensure uniqueness - ensure!(raw_txs.0 != raw_txs.1, Error::::DuplicateTransaction); - - let parse_and_verify = |raw_tx, raw_proof| -> Result { - let merkle_proof = ext::btc_relay::parse_merkle_proof::(raw_proof)?; - let transaction = parse_transaction(raw_tx).map_err(|_| Error::::InvalidTransaction)?; - // ensure transaction is included - ext::btc_relay::verify_transaction_inclusion::(transaction.tx_id(), merkle_proof)?; - Ok(transaction) - }; - - let left_tx = parse_and_verify(&raw_txs.0, &raw_merkle_proofs.0)?; - let right_tx = parse_and_verify(&raw_txs.1, &raw_merkle_proofs.1)?; - - let left_tx_id = left_tx.tx_id(); - let right_tx_id = right_tx.tx_id(); - - // transactions must be unique - ensure!(left_tx_id != right_tx_id, Error::::DuplicateTransaction); - - let vault = ext::vault_registry::get_active_vault_from_id::(&vault_id)?; - // ensure that the payment is made from one of the registered wallets of the Vault, - // this prevents a transaction with the same OP_RETURN flagging this Vault for theft - ensure!( - Self::has_input_from_wallet(&left_tx, &vault.wallet) - && Self::has_input_from_wallet(&right_tx, &vault.wallet), - Error::::VaultNoInputToTransaction - ); - - match ( - OpReturnPaymentData::::try_from(left_tx), - OpReturnPaymentData::::try_from(right_tx), - ) { - (Ok(left), Ok(right)) => { - // verify that the OP_RETURN matches, amounts are not relevant as Vaults - // might transfer any amount in the theft transaction - ensure!(left.op_return == right.op_return, Error::::ExpectedDuplicate); - - ext::vault_registry::liquidate_theft_vault::(&vault_id, reporter_id)?; - - >::mutate(&vault_id, &left_tx_id, |inner| { - let _ = inner.insert(()); - }); - >::mutate(&vault_id, &right_tx_id, |inner| { - let _ = inner.insert(()); - }); - - Self::deposit_event(Event::::VaultDoublePayment { - vault_id, - tx_id_1: left_tx_id, - tx_id_2: right_tx_id, - }); - - // don't take tx fees on success - Ok(Pays::No.into()) - } - _ => Err(Error::::InvalidTransaction.into()), - } - } - } -} - -// "Internal" functions, callable by code. -#[cfg_attr(test, mockable)] -impl Pallet { - pub(crate) fn has_input_from_wallet(transaction: &Transaction, wallet: &Wallet) -> bool { - // collect all addresses that feature in the inputs of the transaction - let input_addresses: Vec> = transaction - .clone() - .inputs - .into_iter() - .map(|input| input.extract_address()) - .collect(); - - // TODO: can a vault steal funds if it registers a P2WPKH-P2SH since we - // would extract the `P2WPKHv0`? - input_addresses.into_iter().any(|address_result| match address_result { - Ok(address) => wallet.has_btc_address(&address), - _ => false, - }) - } - - /// Checks if the vault is sending a valid request transaction. - /// - /// # Arguments - /// - /// * `request_value` - amount of btc as specified in the request - /// * `request_address` - recipient btc address - /// * `payment_data` - all payment data extracted from tx - /// * `wallet` - vault btc addresses - pub(crate) fn is_valid_request_transaction( - request_value: BalanceOf, - request_address: BtcAddress, - payment_data: &OpReturnPaymentData, - wallet: &Wallet, - ) -> bool { - let request_value = match TryInto::::try_into(request_value).map_err(|_e| Error::::TryIntoIntError) { - Ok(value) => value as i64, - Err(_) => return false, - }; - - match payment_data.ensure_valid_payment_to(request_value, request_address, None) { - Ok(None) => true, - Ok(Some(return_to_self)) if wallet.has_btc_address(&return_to_self) => true, - _ => false, - } - } - - /// Check if a vault transaction is invalid. Returns `Ok` if invalid or `Err` otherwise. - /// This method should be callable over RPC for a staked-relayer client to check validity. - /// - /// # Arguments - /// - /// `vault_id`: the vault. - /// `raw_tx`: the BTC transaction by the vault. - pub fn is_transaction_invalid(vault_id: &DefaultVaultId, raw_tx: Vec) -> DispatchResult { - let tx = parse_transaction(raw_tx.as_slice()).map_err(|_| Error::::InvalidTransaction)?; - Self::_is_parsed_transaction_invalid(vault_id, tx) - } - - /// Check if a vault transaction is invalid. Returns `Ok` if invalid or `Err` otherwise. - pub fn _is_parsed_transaction_invalid(vault_id: &DefaultVaultId, tx: Transaction) -> DispatchResult { - let vault = ext::vault_registry::get_active_vault_from_id::(vault_id)?; - - // check if vault's btc address features in an input of the transaction - ensure!( - Self::has_input_from_wallet(&tx, &vault.wallet), - // since the transaction does not have any inputs that correspond - // to any of the vault's registered BTC addresses, return Err - Error::::VaultNoInputToTransaction - ); - - // Vaults are required to move funds for redeem, replace and refund operations. - // Each transaction MUST feature at least two or three outputs as follows: - // * recipient: the recipient of the redeem / replace - // * op_return: the associated ID encoded in the OP_RETURN - // * vault: any "spare change" the vault is transferring - - if let Ok(payment_data) = OpReturnPaymentData::::try_from(tx) { - // redeem requests - if let Ok(req) = ext::redeem::get_open_or_completed_redeem_request_from_id::(&payment_data.op_return) { - ensure!( - !Self::is_valid_request_transaction(req.amount_btc, req.btc_address, &payment_data, &vault.wallet), - Error::::ValidRedeemTransaction - ); - }; - - // replace requests - if let Ok(req) = ext::replace::get_open_or_completed_replace_request::(&payment_data.op_return) { - ensure!( - !Self::is_valid_request_transaction(req.amount, req.btc_address, &payment_data, &vault.wallet), - Error::::ValidReplaceTransaction - ); - }; - - // refund requests - if let Ok(req) = ext::refund::get_open_or_completed_refund_request_from_id::(&payment_data.op_return) { - ensure!( - !Self::is_valid_request_transaction(req.amount_btc, req.btc_address, &payment_data, &vault.wallet), - Error::::ValidRefundTransaction - ); - }; - } - - Ok(()) - } -} diff --git a/crates/relay/src/mock.rs b/crates/relay/src/mock.rs deleted file mode 100644 index 206b7c850f..0000000000 --- a/crates/relay/src/mock.rs +++ /dev/null @@ -1,377 +0,0 @@ -use crate as relay; -use crate::{Config, Error}; -use currency::Amount; -use frame_support::{ - parameter_types, - traits::{ConstU32, Everything, GenesisBuild}, - PalletId, -}; -use mocktopus::{macros::mockable, mocking::clear_mocks}; -use orml_traits::parameter_type_with_key; -pub use primitives::{CurrencyId, CurrencyId::Token, TokenSymbol::*}; -use primitives::{VaultCurrencyPair, VaultId}; -use sp_arithmetic::{FixedI128, FixedPointNumber, FixedU128}; -use sp_core::H256; -use sp_runtime::{ - testing::{Header, TestXt}, - traits::{BlakeTwo256, IdentityLookup, Zero}, -}; - -type TestExtrinsic = TestXt; -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -// Configure a mock runtime to test the pallet. -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Storage, Config, Event}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - - // Tokens & Balances - Tokens: orml_tokens::{Pallet, Storage, Config, Event}, - - Rewards: reward::{Pallet, Call, Storage, Event}, - - // Operational - BTCRelay: btc_relay::{Pallet, Call, Config, Storage, Event}, - Security: security::{Pallet, Call, Storage, Event}, - Relay: relay::{Pallet, Call, Storage, Event}, - VaultRegistry: vault_registry::{Pallet, Call, Config, Storage, Event}, - Oracle: oracle::{Pallet, Call, Config, Storage, Event}, - Redeem: redeem::{Pallet, Call, Config, Storage, Event}, - Replace: replace::{Pallet, Call, Config, Storage, Event}, - Fee: fee::{Pallet, Call, Config, Storage}, - Refund: refund::{Pallet, Call, Config, Storage, Event}, - Nomination: nomination::{Pallet, Call, Config, Storage, Event}, - Staking: staking::{Pallet, Storage, Event}, - Currency: currency::{Pallet}, - } -); - -pub type AccountId = u64; -pub type Balance = u128; -pub type RawAmount = i128; -pub type BlockNumber = u64; -pub type Moment = u64; -pub type Index = u64; -pub type SignedFixedPoint = FixedI128; -pub type SignedInner = i128; -pub type UnsignedFixedPoint = FixedU128; -pub type UnsignedInner = u128; - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const SS58Prefix: u8 = 42; -} - -impl frame_system::Config for Test { - type BaseCallFilter = Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type Origin = Origin; - type Call = Call; - type Index = Index; - type BlockNumber = BlockNumber; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type Event = TestEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = SS58Prefix; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -pub const DEFAULT_COLLATERAL_CURRENCY: CurrencyId = Token(DOT); -pub const DEFAULT_NATIVE_CURRENCY: CurrencyId = Token(INTR); -pub const DEFAULT_WRAPPED_CURRENCY: CurrencyId = Token(IBTC); - -pub const DEFAULT_CURRENCY_PAIR: VaultCurrencyPair = VaultCurrencyPair { - collateral: DEFAULT_COLLATERAL_CURRENCY, - wrapped: DEFAULT_WRAPPED_CURRENCY, -}; - -parameter_types! { - pub const GetCollateralCurrencyId: CurrencyId = DEFAULT_COLLATERAL_CURRENCY; - pub const GetNativeCurrencyId: CurrencyId = DEFAULT_NATIVE_CURRENCY; - pub const GetWrappedCurrencyId: CurrencyId = DEFAULT_WRAPPED_CURRENCY; - pub const MaxLocks: u32 = 50; -} - -parameter_type_with_key! { - pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { - Zero::zero() - }; -} - -impl orml_tokens::Config for Test { - type Event = Event; - type Balance = Balance; - type Amount = RawAmount; - type CurrencyId = CurrencyId; - type WeightInfo = (); - type ExistentialDeposits = ExistentialDeposits; - type OnDust = (); - type MaxLocks = MaxLocks; - type DustRemovalWhitelist = Everything; - type MaxReserves = ConstU32<0>; // we don't use named reserves - type ReserveIdentifier = (); // we don't use named reserves - type OnNewTokenAccount = (); - type OnKilledTokenAccount = (); -} - -impl reward::Config for Test { - type Event = TestEvent; - type SignedFixedPoint = SignedFixedPoint; - type RewardId = VaultId; - type CurrencyId = CurrencyId; - type GetNativeCurrencyId = GetNativeCurrencyId; - type GetWrappedCurrencyId = GetWrappedCurrencyId; -} - -parameter_types! { - pub const MinimumPeriod: Moment = 5; -} - -impl pallet_timestamp::Config for Test { - type Moment = Moment; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; - type WeightInfo = (); -} - -impl security::Config for Test { - type Event = TestEvent; -} - -parameter_types! { - pub const VaultPalletId: PalletId = PalletId(*b"mod/vreg"); -} - -impl frame_system::offchain::SendTransactionTypes for Test -where - Call: From, -{ - type OverarchingCall = Call; - type Extrinsic = TestExtrinsic; -} - -impl vault_registry::Config for Test { - type PalletId = VaultPalletId; - type Event = TestEvent; - type Balance = Balance; - type WeightInfo = (); - type GetGriefingCollateralCurrencyId = GetNativeCurrencyId; -} - -pub struct CurrencyConvert; -impl currency::CurrencyConversion, CurrencyId> for CurrencyConvert { - fn convert( - amount: ¤cy::Amount, - to: CurrencyId, - ) -> Result, sp_runtime::DispatchError> { - let amount = convert_to(to, amount.amount())?; - Ok(Amount::new(amount, to)) - } -} - -#[cfg_attr(test, mockable)] -pub fn convert_to(to: CurrencyId, amount: Balance) -> Result { - Ok(amount) // default conversion 1:1 - overwritable with mocktopus -} - -impl currency::Config for Test { - type SignedInner = SignedInner; - type SignedFixedPoint = SignedFixedPoint; - type UnsignedFixedPoint = UnsignedFixedPoint; - type Balance = Balance; - type GetNativeCurrencyId = GetNativeCurrencyId; - type GetRelayChainCurrencyId = GetCollateralCurrencyId; - type GetWrappedCurrencyId = GetWrappedCurrencyId; - type CurrencyConversion = CurrencyConvert; -} - -impl staking::Config for Test { - type Event = TestEvent; - type SignedFixedPoint = SignedFixedPoint; - type SignedInner = SignedInner; - type CurrencyId = CurrencyId; - type GetNativeCurrencyId = GetNativeCurrencyId; -} - -impl oracle::Config for Test { - type Event = TestEvent; - type WeightInfo = (); -} - -parameter_types! { - pub const FeePalletId: PalletId = PalletId(*b"mod/fees"); - pub const MaxExpectedValue: UnsignedFixedPoint = UnsignedFixedPoint::from_inner(::DIV); -} - -impl fee::Config for Test { - type FeePalletId = FeePalletId; - type WeightInfo = (); - type SignedFixedPoint = SignedFixedPoint; - type SignedInner = SignedInner; - type UnsignedFixedPoint = UnsignedFixedPoint; - type UnsignedInner = UnsignedInner; - type VaultRewards = Rewards; - type VaultStaking = Staking; - type OnSweep = (); - type MaxExpectedValue = MaxExpectedValue; -} - -impl refund::Config for Test { - type Event = TestEvent; - type WeightInfo = (); -} - -parameter_types! { - pub const ParachainBlocksPerBitcoinBlock: BlockNumber = 100; -} - -impl btc_relay::Config for Test { - type Event = TestEvent; - type ParachainBlocksPerBitcoinBlock = ParachainBlocksPerBitcoinBlock; - type WeightInfo = (); -} - -impl redeem::Config for Test { - type Event = TestEvent; - type WeightInfo = (); -} - -impl replace::Config for Test { - type Event = TestEvent; - type WeightInfo = (); -} - -impl nomination::Config for Test { - type Event = TestEvent; - type WeightInfo = (); -} - -impl Config for Test { - type Event = TestEvent; - type WeightInfo = (); -} - -pub type TestEvent = Event; -pub type TestError = Error; -pub type RedeemError = redeem::Error; - -pub const ALICE: AccountId = 1; -pub const BOB: VaultId = VaultId { - account_id: 2, - currencies: VaultCurrencyPair { - collateral: DEFAULT_COLLATERAL_CURRENCY, - wrapped: DEFAULT_WRAPPED_CURRENCY, - }, -}; - -pub const CAROL: VaultId = VaultId { - account_id: 3, - currencies: VaultCurrencyPair { - collateral: DEFAULT_COLLATERAL_CURRENCY, - wrapped: DEFAULT_WRAPPED_CURRENCY, - }, -}; -pub const DAVE: AccountId = 4; -pub const EVE: AccountId = 5; - -pub const ALICE_BALANCE: u128 = 1_000_000; -pub const BOB_BALANCE: u128 = 1_000_000; -pub const CAROL_BALANCE: u128 = 1_000_000; -pub const DAVE_BALANCE: u128 = 1_000_000; -pub const EVE_BALANCE: u128 = 1_000_000; - -pub struct ExtBuilder; - -impl ExtBuilder { - pub fn build_with(conf: F) -> sp_io::TestExternalities - where - F: FnOnce(&mut sp_core::storage::Storage), - { - let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); - - fee::GenesisConfig:: { - issue_fee: UnsignedFixedPoint::checked_from_rational(5, 1000).unwrap(), // 0.5% - issue_griefing_collateral: UnsignedFixedPoint::checked_from_rational(5, 100000).unwrap(), // 0.005% - refund_fee: UnsignedFixedPoint::checked_from_rational(5, 1000).unwrap(), // 0.5% - redeem_fee: UnsignedFixedPoint::checked_from_rational(5, 1000).unwrap(), // 0.5% - premium_redeem_fee: UnsignedFixedPoint::checked_from_rational(5, 100).unwrap(), // 5% - punishment_fee: UnsignedFixedPoint::checked_from_rational(1, 10).unwrap(), // 10% - replace_griefing_collateral: UnsignedFixedPoint::checked_from_rational(1, 10).unwrap(), // 10% - theft_fee: UnsignedFixedPoint::checked_from_rational(5, 100).unwrap(), // 5% - theft_fee_max: 10000000, // 0.1 BTC - } - .assimilate_storage(&mut storage) - .unwrap(); - - vault_registry::GenesisConfig:: { - minimum_collateral_vault: vec![(DEFAULT_COLLATERAL_CURRENCY, 0)], - punishment_delay: 0, - system_collateral_ceiling: vec![(DEFAULT_CURRENCY_PAIR, 1_000_000_000_000)], - secure_collateral_threshold: vec![( - DEFAULT_CURRENCY_PAIR, - UnsignedFixedPoint::checked_from_rational(200, 100).unwrap(), - )], - premium_redeem_threshold: vec![( - DEFAULT_CURRENCY_PAIR, - UnsignedFixedPoint::checked_from_rational(120, 100).unwrap(), - )], - liquidation_collateral_threshold: vec![( - DEFAULT_CURRENCY_PAIR, - UnsignedFixedPoint::checked_from_rational(110, 100).unwrap(), - )], - } - .assimilate_storage(&mut storage) - .unwrap(); - - conf(&mut storage); - - storage.into() - } - - pub fn build() -> sp_io::TestExternalities { - ExtBuilder::build_with(|storage| { - orml_tokens::GenesisConfig:: { - balances: vec![ - (ALICE, Token(DOT), ALICE_BALANCE), - (BOB.account_id, Token(DOT), BOB_BALANCE), - (CAROL.account_id, Token(DOT), CAROL_BALANCE), - (DAVE, Token(DOT), DAVE_BALANCE), - (EVE, Token(DOT), EVE_BALANCE), - ], - } - .assimilate_storage(storage) - .unwrap(); - }) - } -} - -pub fn run_test(test: T) -where - T: FnOnce(), -{ - clear_mocks(); - ExtBuilder::build().execute_with(|| { - System::set_block_number(1); - Security::set_active_block_number(1); - test(); - }); -} diff --git a/crates/relay/src/tests.rs b/crates/relay/src/tests.rs deleted file mode 100644 index 13bf3b5535..0000000000 --- a/crates/relay/src/tests.rs +++ /dev/null @@ -1,538 +0,0 @@ -extern crate hex; -use crate::{ext, mock::*}; -use bitcoin::{ - formatter::Formattable, - types::{ - H256Le, MerkleProof, Transaction, TransactionBuilder, TransactionInputBuilder, TransactionInputSource, - TransactionOutput, - }, -}; -use btc_relay::{BtcAddress, BtcPublicKey, OpReturnPaymentData}; -use frame_support::{assert_err, assert_ok}; -use mocktopus::mocking::*; -use redeem::types::{RedeemRequest, RedeemRequestStatus}; -use replace::types::{ReplaceRequest, ReplaceRequestStatus}; -use sp_core::{H160, H256}; -use sp_std::convert::TryFrom; -use std::{convert::TryInto, str::FromStr}; -use vault_registry::{types::DefaultVault, DefaultVaultId, Vault, Wallet}; - -type Event = crate::Event; - -fn dummy_merkle_proof() -> MerkleProof { - MerkleProof { - block_header: Default::default(), - transactions_count: 0, - flag_bits: vec![], - hashes: vec![], - } -} - -/// Mocking functions -fn init_zero_vault(id: DefaultVaultId, btc_addresses: Vec) -> DefaultVault { - let mut vault = Vault { - wallet: Wallet::new(), - ..Vault::new(id) - }; - - for btc_address in btc_addresses.iter() { - vault.wallet.add_btc_address(*btc_address) - } - vault -} - -#[test] -fn test_report_vault_passes_with_vault_transaction() { - run_test(|| { - let raw_tx = "0100000001c15041a06deb6b3818b022fac558da4ce2097f0860c8f642105bbad9d29be02a010000006c493046022100cfd2a2d332b29adce119c55a9fadd3c073332024b7e272513e51623ca15993480221009b482d7f7b4d479aff62bdcdaea54667737d56f8d4d63dd03ec3ef651ed9a25401210325f8b039a11861659c9bf03f43fc4ea055f3a71cd60c7b1fd474ab578f9977faffffffff0290d94000000000001976a9148ed243a7be26080a1a8cf96b53270665f1b8dd2388ac4083086b000000001976a9147e7d94d0ddc21d83bfbcfc7798e4547edf0832aa88ac00000000"; - - let vault = CAROL; - - let btc_address = BtcAddress::P2PKH(H160::from_slice(&[ - 126, 125, 148, 208, 221, 194, 29, 131, 191, 188, 252, 119, 152, 228, 84, 126, 223, 8, 50, 170, - ])); - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(vault.clone(), vec![btc_address])))); - ext::btc_relay::parse_merkle_proof::.mock_safe(|_| MockResult::Return(Ok(dummy_merkle_proof()))); - ext::btc_relay::verify_transaction_inclusion::.mock_safe(move |_, _| MockResult::Return(Ok(()))); - ext::vault_registry::liquidate_theft_vault::.mock_safe(|_, _| MockResult::Return(Ok(()))); - - assert_ok!(Relay::report_vault_theft( - Origin::signed(ALICE), - CAROL, - vec![0u8; 32], - hex::decode(&raw_tx).unwrap() - ),); - }) -} - -#[test] -fn test_report_vault_fails_with_non_vault_transaction() { - run_test(|| { - let raw_tx = "0100000001c15041a06deb6b3818b022fac558da4ce2097f0860c8f642105bbad9d29be02a010000006c493046022100cfd2a2d332b29adce119c55a9fadd3c073332024b7e272513e51623ca15993480221009b482d7f7b4d479aff62bdcdaea54667737d56f8d4d63dd03ec3ef651ed9a25401210325f8b039a11861659c9bf03f43fc4ea055f3a71cd60c7b1fd474ab578f9977faffffffff0290d94000000000001976a9148ed243a7be26080a1a8cf96b53270665f1b8dd2388ac4083086b000000001976a9147e7d94d0ddc21d83bfbcfc7798e4547edf0832aa88ac00000000"; - - let vault = CAROL; - - let btc_address = BtcAddress::P2PKH(H160::from_slice(&[ - 125, 125, 148, 208, 221, 194, 29, 131, 191, 188, 252, 119, 152, 228, 84, 126, 223, 8, 50, 170, - ])); - - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(vault.clone(), vec![btc_address])))); - ext::btc_relay::parse_merkle_proof::.mock_safe(|_| MockResult::Return(Ok(dummy_merkle_proof()))); - ext::btc_relay::verify_transaction_inclusion::.mock_safe(move |_, _| MockResult::Return(Ok(()))); - - assert_err!( - Relay::report_vault_theft( - Origin::signed(ALICE), - CAROL, - vec![0u8; 32], - hex::decode(&raw_tx).unwrap() - ), - TestError::VaultNoInputToTransaction - ); - }) -} - -#[test] -fn test_report_vault_succeeds_with_segwit_transaction() { - run_test(|| { - let raw_tx = "0200000000010140d43a99926d43eb0e619bf0b3d83b4a31f60c176beecfb9d35bf45e54d0f7420100000017160014a4b4ca48de0b3fffc15404a1acdc8dbaae226955ffffffff0100e1f5050000000017a9144a1154d50b03292b3024370901711946cb7cccc387024830450221008604ef8f6d8afa892dee0f31259b6ce02dd70c545cfcfed8148179971876c54a022076d771d6e91bed212783c9b06e0de600fab2d518fad6f15a2b191d7fbd262a3e0121039d25ab79f41f75ceaf882411fd41fa670a4c672c23ffaf0e361a969cde0692e800000000"; - - let vault = CAROL; - - let btc_address = BtcAddress::P2SH(H160::from_str(&"2928f43af18d2d60e8a843540d8086b305341339").unwrap()); - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(vault.clone(), vec![btc_address])))); - ext::btc_relay::parse_merkle_proof::.mock_safe(|_| MockResult::Return(Ok(dummy_merkle_proof()))); - ext::btc_relay::verify_transaction_inclusion::.mock_safe(move |_, _| MockResult::Return(Ok(()))); - ext::vault_registry::liquidate_theft_vault::.mock_safe(|_, _| MockResult::Return(Ok(()))); - - assert_ok!(Relay::report_vault_theft( - Origin::signed(ALICE), - CAROL, - vec![0u8; 32], - hex::decode(&raw_tx).unwrap() - )); - }) -} - -#[test] -fn test_report_vault_succeeds_with_p2sh_segwit_transaction() { - run_test(|| { - // source: https://blockstream.info/tx/0a0d7b9ab879fbd7a096e856fa5461dbae959ac86d51451c211a65fb8e95f54b?expand - let raw_tx = "02000000000101a1dcf3ca033463e346339642dd7305e33de4ce5ab179d1e19b1eb146534421660000000017160014a97a9058829417d4c581ad5004b6e46cc680063dfdffffff01b9010000000000001600143b05c08e224ddec538ac7aa2e3b6583b983807a302473044022051480b10ef40d12bce982d1d08176a403f176dd3e51189c07a0a9584ddb8e91602204a02134b2b892904a3519da0044e97da9ae78232f8f7678fea0b6531bf3104130121039dcac4d315739516bf5cea98bc6a9cfb49cb6269beb67c520bc5ecacc3c7d47206c70900"; - - let vault = CAROL; - // 35PLQyoXs2sk9QDqMv7bBGowxP1pjwXAMe - let btc_address = BtcAddress::P2SH(H160::from_str(&"288873634ae24a3c9b6792cc7e2a084ec79ef68b").unwrap()); - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(vault.clone(), vec![btc_address])))); - ext::btc_relay::parse_merkle_proof::.mock_safe(|_| MockResult::Return(Ok(dummy_merkle_proof()))); - ext::btc_relay::verify_transaction_inclusion::.mock_safe(move |_, _| MockResult::Return(Ok(()))); - ext::vault_registry::liquidate_theft_vault::.mock_safe(|_, _| MockResult::Return(Ok(()))); - - assert_ok!(Relay::report_vault_theft( - Origin::signed(ALICE), - CAROL, - vec![0u8; 32], - hex::decode(&raw_tx).unwrap() - )); - }) -} - -#[test] -fn test_report_vault_theft_succeeds() { - run_test(|| { - let relayer = Origin::signed(ALICE); - - ext::btc_relay::verify_transaction_inclusion::.mock_safe(move |_, _| MockResult::Return(Ok(()))); - Relay::_is_parsed_transaction_invalid.mock_safe(move |_, _| MockResult::Return(Ok(()))); - ext::vault_registry::liquidate_theft_vault::.mock_safe(move |_, _| MockResult::Return(Ok(()))); - - let raw_proof = hex::decode("00000020ecf348128755dbeea5deb8eddf64566d9d4e59bc65d485000000000000000000901f0d92a66ee7dcefd02fa282ca63ce85288bab628253da31ef259b24abe8a0470a385a45960018e8d672f8a90a00000d0bdabada1fb6e3cef7f5c6e234621e3230a2f54efc1cba0b16375d9980ecbc023cbef3ba8d8632ea220927ec8f95190b30769eb35d87618f210382c9445f192504074f56951b772efa43b89320d9c430b0d156b93b7a1ff316471e715151a0619a39392657f25289eb713168818bd5b37476f1bc59b166deaa736d8a58756f9d7ce2aef46d8004c5fe3293d883838f87b5f1da03839878895b71530e9ff89338bb6d4578b3c3135ff3e8671f9a64d43b22e14c2893e8271cecd420f11d2359307403bb1f3128885b3912336045269ef909d64576b93e816fa522c8c027fe408700dd4bdee0254c069ccb728d3516fe1e27578b31d70695e3e35483da448f3a951273e018de7f2a8f657064b013c6ede75c74bbd7f98fdae1c2ac6789ee7b21a791aa29d60e89fff2d1d2b1ada50aa9f59f403823c8c58bb092dc58dc09b28158ca15447da9c3bedb0b160f3fe1668d5a27716e27661bcb75ddbf3468f5c76b7bed1004c6b4df4da2ce80b831a7c260b515e6355e1c306373d2233e8de6fda3674ed95d17a01a1f64b27ba88c3676024fbf8d5dd962ffc4d5e9f3b1700763ab88047f7d0000").unwrap(); - let tx_bytes = hex::decode("0100000001c8cc2b56525e734ff63a13bc6ad06a9e5664df8c67632253a8e36017aee3ee40000000009000483045022100ad0851c69dd756b45190b5a8e97cb4ac3c2b0fa2f2aae23aed6ca97ab33bf88302200b248593abc1259512793e7dea61036c601775ebb23640a0120b0dba2c34b79001455141042f90074d7a5bf30c72cf3a8dfd1381bdbd30407010e878f3a11269d5f74a58788505cdca22ea6eab7cfb40dc0e07aba200424ab0d79122a653ad0c7ec9896bdf51aefeffffff0120f40e00000000001976a9141d30342095961d951d306845ef98ac08474b36a088aca7270400").unwrap(); - - assert_ok!(Relay::report_vault_theft(relayer, BOB, raw_proof, tx_bytes,)); - // check that the event has been emitted - assert!(System::events() - .iter() - .any(|a| matches!(a.event, TestEvent::Relay(Event::VaultTheft{ref vault_id,..}) if vault_id == &BOB))); - }) -} - -fn build_dummy_transaction_from_input_with_output_and_op_return( - prev_hash: H256Le, - public_key: &BtcPublicKey, - output: BtcAddress, - op_return: &[u8], -) -> Transaction { - let mut builder = TransactionBuilder::new(); - builder.with_version(1).add_input( - TransactionInputBuilder::new() - .with_source(TransactionInputSource::FromOutput(prev_hash, 1)) - .with_sequence(4294967295) - .with_p2pkh(public_key, vec![1u8; 32]) - .build(), - ); - builder.add_output(TransactionOutput::payment(100, &output)); - builder.add_output(TransactionOutput::op_return(0, &op_return)); - builder.build() -} - -fn build_dummy2_transaction_with(output_addresses: Vec<(i64, BtcAddress)>, op_return: H256) -> Transaction { - let mut builder = TransactionBuilder::new(); - builder.with_version(1).add_input( - TransactionInputBuilder::new() - .with_sequence(4294967295) - .with_source(TransactionInputSource::FromOutput( - H256Le::from_bytes_le(&[ - 193, 80, 65, 160, 109, 235, 107, 56, 24, 176, 34, 250, 197, 88, 218, 76, 226, 9, 127, 8, 96, 200, - 246, 66, 16, 91, 186, 217, 210, 155, 224, 42, - ]), - 1, - )) - .with_script(&[ - 73, 48, 70, 2, 33, 0, 207, 210, 162, 211, 50, 178, 154, 220, 225, 25, 197, 90, 159, 173, 211, 192, 115, - 51, 32, 36, 183, 226, 114, 81, 62, 81, 98, 60, 161, 89, 147, 72, 2, 33, 0, 155, 72, 45, 127, 123, 77, - 71, 154, 255, 98, 189, 205, 174, 165, 70, 103, 115, 125, 86, 248, 212, 214, 61, 208, 62, 195, 239, 101, - 30, 217, 162, 84, 1, 33, 3, 37, 248, 176, 57, 161, 24, 97, 101, 156, 155, 240, 63, 67, 252, 78, 160, - 85, 243, 167, 28, 214, 12, 123, 31, 212, 116, 171, 87, 143, 153, 119, 250, - ]) - .build(), - ); - for (amount, address) in output_addresses { - builder.add_output(TransactionOutput::payment(amount, &address)); - } - builder.add_output(TransactionOutput::op_return(0, op_return.as_bytes())); - builder.build() -} - -#[test] -fn test_is_valid_request_transaction_overpayment_fails() { - run_test(|| { - let vault = BOB; - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(vault.clone(), vec![])))); - - let address1 = BtcAddress::P2PKH(H160::from_str(&"66c7060feb882664ae62ffad0051fe843e318e85").unwrap()); - - let address2 = BtcAddress::P2PKH(H160::from_str(&"5f69790b72c98041330644bbd50f2ebb5d073c36").unwrap()); - - let mut wallet = Wallet::new(); - wallet.add_btc_address(address2); - - let actual_value = 101; - - let request_value = 100; - let request_address = address1; - - let transaction = build_dummy2_transaction_with(vec![(actual_value, address1)], H256::zero()); - let payment_data = OpReturnPaymentData::try_from(transaction).unwrap(); - - assert_eq!( - Relay::is_valid_request_transaction(request_value, request_address, &payment_data, &wallet), - false - ); - }) -} -#[test] -fn test_is_valid_request_transaction_underpayment_fails() { - run_test(|| { - let vault = BOB; - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(vault.clone(), vec![])))); - - let address1 = BtcAddress::P2PKH(H160::from_str(&"66c7060feb882664ae62ffad0051fe843e318e85").unwrap()); - - let address2 = BtcAddress::P2PKH(H160::from_str(&"5f69790b72c98041330644bbd50f2ebb5d073c36").unwrap()); - - let mut wallet = Wallet::new(); - wallet.add_btc_address(address2); - - let actual_value = 99; - - let request_value = 100; - let request_address = address1; - - let transaction = build_dummy2_transaction_with(vec![(actual_value, address1)], H256::zero()); - let payment_data = OpReturnPaymentData::try_from(transaction).unwrap(); - - assert_eq!( - Relay::is_valid_request_transaction(request_value, request_address, &payment_data, &wallet), - false - ); - }) -} - -#[test] -fn test_is_valid_request_transaction_succeeds() { - run_test(|| { - let recipient_address = BtcAddress::P2PKH(H160::from_str(&"66c7060feb882664ae62ffad0051fe843e318e85").unwrap()); - - let vault_address = BtcAddress::P2PKH(H160::from_str(&"5f69790b72c98041330644bbd50f2ebb5d073c36").unwrap()); - - let request_value = 100; - let change_value = 50; - - let mut wallet = Wallet::new(); - wallet.add_btc_address(vault_address); - - let transaction = build_dummy2_transaction_with( - vec![(request_value, recipient_address), (change_value, vault_address)], - H256::zero(), - ); - let payment_data = OpReturnPaymentData::try_from(transaction).unwrap(); - - assert_eq!( - Relay::is_valid_request_transaction( - request_value.try_into().unwrap(), - recipient_address, - &payment_data, - &wallet - ), - true - ); - }) -} - -#[test] -fn test_is_transaction_invalid_fails_with_valid_request_or_redeem() { - run_test(|| { - let vault_address = BtcAddress::P2SH(H160::from_slice(&[ - 41, 40, 244, 58, 241, 141, 45, 96, 232, 168, 67, 84, 13, 128, 134, 179, 5, 52, 19, 57, - ])); - - let mut wallet = Wallet::new(); - wallet.add_btc_address(vault_address); - - let recipient_address = BtcAddress::P2PKH(H160::from_str(&"5f69790b72c98041330644bbd50f2ebb5d073c36").unwrap()); - - ext::vault_registry::get_active_vault_from_id::.mock_safe(move |_| { - MockResult::Return(Ok(Vault { - wallet: wallet.clone(), - ..Vault::new(BOB) - })) - }); - - ext::redeem::get_open_or_completed_redeem_request_from_id::.mock_safe(move |_| { - MockResult::Return(Ok(RedeemRequest { - period: 0, - vault: BOB, - opentime: 0, - fee: 0, - amount_btc: 100, - premium: 0, - redeemer: ALICE, - btc_address: recipient_address, - btc_height: 0, - status: RedeemRequestStatus::Pending, - transfer_fee_btc: 0, - })) - }); - - let transaction = TransactionBuilder::new() - .with_version(1) - .add_input( - TransactionInputBuilder::new() - .with_source(TransactionInputSource::FromOutput( - H256Le::from_hex_le("40d43a99926d43eb0e619bf0b3d83b4a31f60c176beecfb9d35bf45e54d0f742"), - 1, - )) - .with_sequence(4294967295) - .with_script(&[ - 22, 0, 20, 164, 180, 202, 72, 222, 11, 63, 255, 193, 84, 4, 161, 172, 220, 141, 186, 174, 34, - 105, 85, - ]) - .add_witness(&[ - 48, 69, 2, 33, 0, 134, 4, 239, 143, 109, 138, 250, 137, 45, 238, 15, 49, 37, 155, 108, 224, 45, - 215, 12, 84, 92, 252, 254, 216, 20, 129, 121, 151, 24, 118, 197, 74, 2, 32, 118, 215, 113, 214, - 233, 27, 237, 33, 39, 131, 201, 176, 110, 13, 230, 0, 250, 178, 213, 24, 250, 214, 241, 90, 43, - 25, 29, 127, 189, 38, 42, 62, 1, - ]) - .add_witness(&[ - 3, 157, 37, 171, 121, 244, 31, 117, 206, 175, 136, 36, 17, 253, 65, 250, 103, 10, 76, 103, 44, - 35, 255, 175, 14, 54, 26, 150, 156, 222, 6, 146, 232, - ]) - .build(), - ) - .add_output(TransactionOutput::payment(100, &recipient_address)) - .add_output(TransactionOutput::op_return(0, &H256::from_slice(&[0; 32]).as_bytes())) - .build(); - - assert_err!( - Relay::is_transaction_invalid(&BOB, transaction.format()), - TestError::ValidRedeemTransaction - ); - - ext::redeem::get_open_or_completed_redeem_request_from_id:: - .mock_safe(move |_| MockResult::Return(Err(RedeemError::RedeemIdNotFound.into()))); - - ext::replace::get_open_or_completed_replace_request::.mock_safe(move |_| { - MockResult::Return(Ok(ReplaceRequest { - period: 0, - old_vault: BOB, - amount: 100, - griefing_collateral: 0, - new_vault: CAROL, - collateral: 0, - accept_time: 1, - btc_address: recipient_address, - btc_height: 0, - status: ReplaceRequestStatus::Pending, - })) - }); - - assert_err!( - Relay::is_transaction_invalid(&BOB, transaction.format()), - TestError::ValidReplaceTransaction - ); - }) -} - -#[test] -fn test_is_transaction_invalid_succeeds() { - run_test(|| { - let vault_address = BtcAddress::P2PKH(H160::from_slice(&[ - 126, 125, 148, 208, 221, 194, 29, 131, 191, 188, 252, 119, 152, 228, 84, 126, 223, 8, 50, 170, - ])); - - let recipient_address = BtcAddress::P2PKH(H160::from_str(&"66c7060feb882664ae62ffad0051fe843e318e85").unwrap()); - - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(BOB.clone(), vec![vault_address])))); - - let transaction = TransactionBuilder::new() - .with_version(1) - .add_input( - TransactionInputBuilder::new() - .with_sequence(4294967295) - .with_source(TransactionInputSource::FromOutput( - H256Le::from_bytes_le(&[ - 193, 80, 65, 160, 109, 235, 107, 56, 24, 176, 34, 250, 197, 88, 218, 76, 226, 9, 127, 8, - 96, 200, 246, 66, 16, 91, 186, 217, 210, 155, 224, 42, - ]), - 1, - )) - .with_script(&[ - 73, 48, 70, 2, 33, 0, 207, 210, 162, 211, 50, 178, 154, 220, 225, 25, 197, 90, 159, 173, 211, - 192, 115, 51, 32, 36, 183, 226, 114, 81, 62, 81, 98, 60, 161, 89, 147, 72, 2, 33, 0, 155, 72, - 45, 127, 123, 77, 71, 154, 255, 98, 189, 205, 174, 165, 70, 103, 115, 125, 86, 248, 212, 214, - 61, 208, 62, 195, 239, 101, 30, 217, 162, 84, 1, 33, 3, 37, 248, 176, 57, 161, 24, 97, 101, - 156, 155, 240, 63, 67, 252, 78, 160, 85, 243, 167, 28, 214, 12, 123, 31, 212, 116, 171, 87, - 143, 153, 119, 250, - ]) - .build(), - ) - .add_output(TransactionOutput::payment(100, &recipient_address)) - .build(); - - assert_ok!(Relay::is_transaction_invalid(&BOB, transaction.format())); - }) -} - -#[test] -fn test_is_transaction_invalid_succeeds_with_testnet_transaction() { - run_test(|| { - // bitcoin-cli -testnet getrawtransaction "3453e52ebab8ac96159d6b19114b492a05cce05a8fdfdaf5dea266ac10601ce4" 0 - // "00000000000000398849cc9d67261ec2d5fea07db87ab66a8ea47bc05acfb194" - let raw_tx_hex = "0200000000010108ce8e8943edbbf09d070bb893e09c0de12c0cf3704fe8a9b0f8b8d1a4a7a4760000000017160014473ca3f4d726ce9c21af7cdc3fcc13264f681b04feffffff02b377413f0000000017a914fe5183ccb89d98beaa6908c7cf1bd109029482cf87142e1a00000000001976a914d0a46d39dafa3012c2a7ed4d82d644b428e4586b88ac02473044022069484377c6627ccca566d4c4ac2cb84d1b0662f5ffbd384815c5e98b072759fc022061de3b77b4543ef43bb969d3f97fbbbdcddc008438720e7026181d99c455b2410121034172c29d3da8279f71adda48db8281d65b794e73cf04ea91fac4293030f0fe91a3ee1c00"; - let raw_tx = hex::decode(&raw_tx_hex).unwrap(); - - // 2MsqorfMrsvXiVM8pD9bPWxGnccSWsj16XE (P2WPKH-P2SH) - let btc_address = BtcAddress::P2SH(H160::from_slice( - &hex::decode("068a6a2ec6be7d6e7aac1657445154c52db0cef8").unwrap(), - )); - - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(BOB.clone(), vec![btc_address])))); - - assert_ok!(Relay::is_transaction_invalid(&BOB, raw_tx)); - }) -} - -#[test] -fn should_not_report_double_payment_with_identical_tx() { - run_test(|| { - assert_err!( - Relay::report_vault_double_payment( - Origin::signed(ALICE), - CAROL, - (vec![0u8; 32], vec![0u8; 32]), - (vec![0u8; 32], vec![0u8; 32]), - ), - TestError::DuplicateTransaction - ); - }) -} - -#[test] -fn should_report_double_payment() { - run_test(|| { - let public_key = BtcPublicKey::dummy(); - let input_address = BtcAddress::P2PKH(public_key.to_hash()); - let output_address = BtcAddress::random(); - let left_tx = build_dummy_transaction_from_input_with_output_and_op_return( - H256Le::from_bytes_le(&vec![1u8; 32]), - &public_key, - output_address, - &[1; 32], - ); - let right_tx = build_dummy_transaction_from_input_with_output_and_op_return( - H256Le::from_bytes_le(&vec![2u8; 32]), - &public_key, - output_address, - &[1; 32], - ); - - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(CAROL.clone(), vec![input_address])))); - ext::btc_relay::parse_merkle_proof::.mock_safe(|_| MockResult::Return(Ok(dummy_merkle_proof()))); - ext::btc_relay::verify_transaction_inclusion::.mock_safe(move |_, _| MockResult::Return(Ok(()))); - ext::vault_registry::liquidate_theft_vault::.mock_safe(|_, _| MockResult::Return(Ok(()))); - - assert_ok!(Relay::report_vault_double_payment( - Origin::signed(ALICE), - CAROL, - (vec![0u8; 32], vec![1u8; 32]), - (left_tx.format(), right_tx.format()), - )); - }) -} - -#[test] -fn should_not_report_double_payment_with_vault_no_input() { - run_test(|| { - let public_key = BtcPublicKey::dummy(); - let input_address = BtcAddress::random(); - let output_address = BtcAddress::random(); - let left_tx = build_dummy_transaction_from_input_with_output_and_op_return( - H256Le::from_bytes_le(&vec![1u8; 32]), - &public_key, - output_address, - &[1; 32], - ); - let right_tx = build_dummy_transaction_from_input_with_output_and_op_return( - H256Le::from_bytes_le(&vec![2u8; 32]), - &public_key, - output_address, - &[1; 32], - ); - - ext::vault_registry::get_active_vault_from_id:: - .mock_safe(move |_| MockResult::Return(Ok(init_zero_vault(CAROL.clone(), vec![input_address])))); - ext::btc_relay::parse_merkle_proof::.mock_safe(|_| MockResult::Return(Ok(dummy_merkle_proof()))); - ext::btc_relay::verify_transaction_inclusion::.mock_safe(move |_, _| MockResult::Return(Ok(()))); - ext::vault_registry::liquidate_theft_vault::.mock_safe(|_, _| MockResult::Return(Ok(()))); - - assert_err!( - Relay::report_vault_double_payment( - Origin::signed(ALICE), - CAROL, - (vec![0u8; 32], vec![1u8; 32]), - (left_tx.format(), right_tx.format()), - ), - TestError::VaultNoInputToTransaction - ); - }) -} diff --git a/crates/relay/src/types.rs b/crates/relay/src/types.rs deleted file mode 100644 index 8a65ab161d..0000000000 --- a/crates/relay/src/types.rs +++ /dev/null @@ -1,6 +0,0 @@ -use primitives::VaultId; -use vault_registry::types::CurrencyId; - -pub(crate) type BalanceOf = ::Balance; - -pub(crate) type DefaultVaultId = VaultId<::AccountId, CurrencyId>; diff --git a/crates/replace/src/benchmarking.rs b/crates/replace/src/benchmarking.rs index 0194608ef8..b647b4522a 100644 --- a/crates/replace/src/benchmarking.rs +++ b/crates/replace/src/benchmarking.rs @@ -69,7 +69,7 @@ fn mine_blocks(end_height: u32) { let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); Security::::set_active_block_number(1u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); + BtcRelay::::_initialize(relayer_id.clone(), block_header, height).unwrap(); let transaction = TransactionBuilder::new() .with_version(2) @@ -104,7 +104,7 @@ fn mine_blocks(end_height: u32) { let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); + BtcRelay::::_store_block_header(&relayer_id, block_header).unwrap(); } } @@ -271,7 +271,7 @@ benchmarks! { Security::::set_active_block_number(1u32.into()); VaultRegistry::::_set_system_collateral_ceiling(get_currency_pair::(), 1_000_000_000u32.into()); - BtcRelay::::initialize(relayer_id.clone(), block_header, height).unwrap(); + BtcRelay::::_initialize(relayer_id.clone(), block_header, height).unwrap(); let value = 0; let transaction = TransactionBuilder::new() @@ -311,7 +311,7 @@ benchmarks! { let raw_block_header = RawBlockHeader::from_bytes(&block.header.try_format().unwrap()).unwrap(); let block_header = BtcRelay::::parse_raw_block_header(&raw_block_header).unwrap(); - BtcRelay::::store_block_header(&relayer_id, block_header).unwrap(); + BtcRelay::::_store_block_header(&relayer_id, block_header).unwrap(); Security::::set_active_block_number(Security::::active_block_number() + BtcRelay::::parachain_confirmations() + 1u32.into()); }: _(RawOrigin::Signed(old_vault_id.account_id), replace_id, proof, raw_tx) diff --git a/crates/vault-registry/src/types.rs b/crates/vault-registry/src/types.rs index 6af4037b35..bbbeb59eb7 100644 --- a/crates/vault-registry/src/types.rs +++ b/crates/vault-registry/src/types.rs @@ -372,6 +372,7 @@ pub enum VaultStatus { Liquidated, /// Vault theft has been reported + // TODO: remove this, requires migration CommittedTheft, } diff --git a/parachain/Cargo.toml b/parachain/Cargo.toml index 89d828c193..eb8ae3fe1c 100644 --- a/parachain/Cargo.toml +++ b/parachain/Cargo.toml @@ -35,7 +35,6 @@ primitives = { package = "interbtc-primitives", path = "../primitives" } module-btc-relay-rpc-runtime-api = { path = "../crates/btc-relay/rpc/runtime-api" } module-oracle-rpc-runtime-api = { path = "../crates/oracle/rpc/runtime-api" } -module-relay-rpc-runtime-api = { path = "../crates/relay/rpc/runtime-api" } module-vault-registry-rpc-runtime-api = { path = "../crates/vault-registry/rpc/runtime-api" } module-issue-rpc-runtime-api = { path = "../crates/issue/rpc/runtime-api" } module-redeem-rpc-runtime-api = { path = "../crates/redeem/rpc/runtime-api" } diff --git a/parachain/runtime/interlay/Cargo.toml b/parachain/runtime/interlay/Cargo.toml index b85727e0b3..78e3907576 100644 --- a/parachain/runtime/interlay/Cargo.toml +++ b/parachain/runtime/interlay/Cargo.toml @@ -79,7 +79,6 @@ pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release btc-relay = { path = "../../../crates/btc-relay", default-features = false } currency = { path = "../../../crates/currency", default-features = false } security = { path = "../../../crates/security", default-features = false } -relay = { path = "../../../crates/relay", default-features = false } vault-registry = { path = "../../../crates/vault-registry", default-features = false } oracle = { path = "../../../crates/oracle", default-features = false } fee = { path = "../../../crates/fee", default-features = false } @@ -99,7 +98,6 @@ primitives = { package = "interbtc-primitives", path = "../../../primitives", de module-btc-relay-rpc-runtime-api = { path = "../../../crates/btc-relay/rpc/runtime-api", default-features = false } module-oracle-rpc-runtime-api = { path = "../../../crates/oracle/rpc/runtime-api", default-features = false } -module-relay-rpc-runtime-api = { path = "../../../crates/relay/rpc/runtime-api", default-features = false } module-vault-registry-rpc-runtime-api = { path = "../../../crates/vault-registry/rpc/runtime-api", default-features = false } module-issue-rpc-runtime-api = { path = "../../../crates/issue/rpc/runtime-api", default-features = false } module-redeem-rpc-runtime-api = { path = "../../../crates/redeem/rpc/runtime-api", default-features = false } @@ -191,7 +189,6 @@ std = [ "btc-relay/std", "currency/std", "security/std", - "relay/std", "vault-registry/std", "oracle/std", "fee/std", @@ -213,7 +210,6 @@ std = [ "module-btc-relay-rpc-runtime-api/std", "module-oracle-rpc-runtime-api/std", - "module-relay-rpc-runtime-api/std", "module-vault-registry-rpc-runtime-api/std", "module-issue-rpc-runtime-api/std", "module-redeem-rpc-runtime-api/std", @@ -247,7 +243,6 @@ runtime-benchmarks = [ "oracle/runtime-benchmarks", "redeem/runtime-benchmarks", "refund/runtime-benchmarks", - "relay/runtime-benchmarks", "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", ] diff --git a/parachain/runtime/interlay/src/lib.rs b/parachain/runtime/interlay/src/lib.rs index ac706f5caa..0556cf4dbc 100644 --- a/parachain/runtime/interlay/src/lib.rs +++ b/parachain/runtime/interlay/src/lib.rs @@ -57,7 +57,7 @@ pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; // interBTC exports -pub use btc_relay::{bitcoin, Call as RelayCall, TARGET_SPACING}; +pub use btc_relay::{bitcoin, Call as BtcRelayCall, TARGET_SPACING}; pub use constants::{currency::*, time::*}; pub use module_oracle_rpc_runtime_api::BalanceWrapper; pub use security::StatusCode; @@ -887,8 +887,6 @@ impl security::Config for Runtime { type Event = Event; } -pub use relay::Event as RelayEvent; - pub struct CurrencyConvert; impl currency::CurrencyConversion, CurrencyId> for CurrencyConvert { fn convert(amount: ¤cy::Amount, to: CurrencyId) -> Result, DispatchError> { @@ -907,11 +905,6 @@ impl currency::Config for Runtime { type CurrencyConversion = CurrencyConvert; } -impl relay::Config for Runtime { - type Event = Event; - type WeightInfo = (); -} - impl staking::Config for Runtime { type Event = Event; type SignedFixedPoint = SignedFixedPoint; @@ -1057,7 +1050,7 @@ construct_runtime! { Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 7, Identity: pallet_identity::{Pallet, Call, Storage, Event} = 8, - // Tokens & Balances + // # Tokens & Balances Currency: currency::{Pallet} = 20, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event} = 21, Supply: supply::{Pallet, Storage, Call, Event, Config} = 22, @@ -1073,11 +1066,11 @@ construct_runtime! { VaultStaking: staking::{Pallet, Storage, Event} = 42, - // Bitcoin SPV + // # Bitcoin SPV BTCRelay: btc_relay::{Pallet, Call, Config, Storage, Event} = 50, - Relay: relay::{Pallet, Call, Storage, Event} = 51, + // Relay: 51 - // Operational + // # Operational Security: security::{Pallet, Call, Config, Storage, Event} = 60, VaultRegistry: vault_registry::{Pallet, Call, Config, Storage, Event, ValidateUnsigned} = 61, Oracle: oracle::{Pallet, Call, Config, Storage, Event} = 62, @@ -1088,7 +1081,7 @@ construct_runtime! { Refund: refund::{Pallet, Call, Config, Storage, Event} = 67, Nomination: nomination::{Pallet, Call, Config, Storage, Event} = 68, - // Governance + // # Governance Democracy: democracy::{Pallet, Call, Storage, Config, Event} = 70, TechnicalCommittee: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 71, TechnicalMembership: pallet_membership::{Pallet, Call, Storage, Event, Config} = 72, @@ -1102,7 +1095,7 @@ construct_runtime! { ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event} = 85, ParachainInfo: parachain_info::{Pallet, Storage, Config} = 86, - // XCM Helpers + // # XCM Helpers XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 90, PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 91, CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin} = 92, @@ -1274,7 +1267,6 @@ impl_runtime_apis! { list_benchmark!(list, extra, oracle, Oracle); list_benchmark!(list, extra, redeem, Redeem); list_benchmark!(list, extra, refund, Refund); - list_benchmark!(list, extra, relay, Relay); list_benchmark!(list, extra, replace, Replace); list_benchmark!(list, extra, vault_registry, VaultRegistry); @@ -1311,7 +1303,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, oracle, Oracle); add_benchmark!(params, batches, redeem, Redeem); add_benchmark!(params, batches, refund, Refund); - add_benchmark!(params, batches, relay, Relay); add_benchmark!(params, batches, replace, Replace); add_benchmark!(params, batches, vault_registry, VaultRegistry); @@ -1345,15 +1336,6 @@ impl_runtime_apis! { } } - impl module_relay_rpc_runtime_api::RelayApi< - Block, - VaultId, - > for Runtime { - fn is_transaction_invalid(vault_id: VaultId, raw_tx: Vec) -> DispatchResult { - Relay::is_transaction_invalid(&vault_id, raw_tx) - } - } - impl module_vault_registry_rpc_runtime_api::VaultRegistryApi< Block, VaultId, diff --git a/parachain/runtime/kintsugi/Cargo.toml b/parachain/runtime/kintsugi/Cargo.toml index d8bcefe5f7..9eeaf97a7a 100644 --- a/parachain/runtime/kintsugi/Cargo.toml +++ b/parachain/runtime/kintsugi/Cargo.toml @@ -79,7 +79,6 @@ pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release btc-relay = { path = "../../../crates/btc-relay", default-features = false } currency = { path = "../../../crates/currency", default-features = false } security = { path = "../../../crates/security", default-features = false } -relay = { path = "../../../crates/relay", default-features = false } vault-registry = { path = "../../../crates/vault-registry", default-features = false } oracle = { path = "../../../crates/oracle", default-features = false } fee = { path = "../../../crates/fee", default-features = false } @@ -99,7 +98,6 @@ primitives = { package = "interbtc-primitives", path = "../../../primitives", de module-btc-relay-rpc-runtime-api = { path = "../../../crates/btc-relay/rpc/runtime-api", default-features = false } module-oracle-rpc-runtime-api = { path = "../../../crates/oracle/rpc/runtime-api", default-features = false } -module-relay-rpc-runtime-api = { path = "../../../crates/relay/rpc/runtime-api", default-features = false } module-vault-registry-rpc-runtime-api = { path = "../../../crates/vault-registry/rpc/runtime-api", default-features = false } module-issue-rpc-runtime-api = { path = "../../../crates/issue/rpc/runtime-api", default-features = false } module-redeem-rpc-runtime-api = { path = "../../../crates/redeem/rpc/runtime-api", default-features = false } @@ -195,7 +193,6 @@ std = [ "btc-relay/std", "currency/std", "security/std", - "relay/std", "vault-registry/std", "oracle/std", "fee/std", @@ -217,7 +214,6 @@ std = [ "module-btc-relay-rpc-runtime-api/std", "module-oracle-rpc-runtime-api/std", - "module-relay-rpc-runtime-api/std", "module-vault-registry-rpc-runtime-api/std", "module-issue-rpc-runtime-api/std", "module-redeem-rpc-runtime-api/std", @@ -251,7 +247,6 @@ runtime-benchmarks = [ "oracle/runtime-benchmarks", "redeem/runtime-benchmarks", "refund/runtime-benchmarks", - "relay/runtime-benchmarks", "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", ] diff --git a/parachain/runtime/kintsugi/src/lib.rs b/parachain/runtime/kintsugi/src/lib.rs index 1418961b7e..bdcca5d066 100644 --- a/parachain/runtime/kintsugi/src/lib.rs +++ b/parachain/runtime/kintsugi/src/lib.rs @@ -56,7 +56,7 @@ pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; // interBTC exports -pub use btc_relay::{bitcoin, Call as RelayCall, TARGET_SPACING}; +pub use btc_relay::{bitcoin, Call as BtcRelayCall, TARGET_SPACING}; pub use constants::{currency::*, time::*}; pub use module_oracle_rpc_runtime_api::BalanceWrapper; pub use orml_asset_registry::AssetMetadata; @@ -986,8 +986,6 @@ impl security::Config for Runtime { type Event = Event; } -pub use relay::Event as RelayEvent; - pub struct CurrencyConvert; impl currency::CurrencyConversion, CurrencyId> for CurrencyConvert { fn convert(amount: ¤cy::Amount, to: CurrencyId) -> Result, DispatchError> { @@ -1006,11 +1004,6 @@ impl currency::Config for Runtime { type CurrencyConversion = CurrencyConvert; } -impl relay::Config for Runtime { - type Event = Event; - type WeightInfo = (); -} - impl staking::Config for Runtime { type Event = Event; type SignedFixedPoint = SignedFixedPoint; @@ -1156,7 +1149,7 @@ construct_runtime! { Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 6, Identity: pallet_identity::{Pallet, Call, Storage, Event} = 7, - // Tokens & Balances + // # Tokens & Balances Currency: currency::{Pallet} = 20, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event} = 21, Supply: supply::{Pallet, Storage, Call, Event, Config} = 22, @@ -1171,11 +1164,11 @@ construct_runtime! { VaultRewards: reward::::{Pallet, Storage, Event} = 41, VaultStaking: staking::{Pallet, Storage, Event} = 42, - // Bitcoin SPV + // # Bitcoin SPV BTCRelay: btc_relay::{Pallet, Call, Config, Storage, Event} = 50, - Relay: relay::{Pallet, Call, Storage, Event} = 51, + // Relay: 51 - // Operational + // # Operational Security: security::{Pallet, Call, Config, Storage, Event} = 60, VaultRegistry: vault_registry::{Pallet, Call, Config, Storage, Event, ValidateUnsigned} = 61, Oracle: oracle::{Pallet, Call, Config, Storage, Event} = 62, @@ -1186,7 +1179,7 @@ construct_runtime! { Refund: refund::{Pallet, Call, Config, Storage, Event} = 67, Nomination: nomination::{Pallet, Call, Config, Storage, Event} = 68, - // Governance + // # Governance Democracy: democracy::{Pallet, Call, Storage, Config, Event} = 70, TechnicalCommittee: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 71, TechnicalMembership: pallet_membership::{Pallet, Call, Storage, Event, Config} = 72, @@ -1200,7 +1193,7 @@ construct_runtime! { ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event} = 85, ParachainInfo: parachain_info::{Pallet, Storage, Config} = 86, - // XCM helpers. + // # XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 90, PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 91, CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin} = 92, @@ -1372,7 +1365,6 @@ impl_runtime_apis! { list_benchmark!(list, extra, oracle, Oracle); list_benchmark!(list, extra, redeem, Redeem); list_benchmark!(list, extra, refund, Refund); - list_benchmark!(list, extra, relay, Relay); list_benchmark!(list, extra, replace, Replace); list_benchmark!(list, extra, vault_registry, VaultRegistry); @@ -1409,7 +1401,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, oracle, Oracle); add_benchmark!(params, batches, redeem, Redeem); add_benchmark!(params, batches, refund, Refund); - add_benchmark!(params, batches, relay, Relay); add_benchmark!(params, batches, replace, Replace); add_benchmark!(params, batches, vault_registry, VaultRegistry); @@ -1443,15 +1434,6 @@ impl_runtime_apis! { } } - impl module_relay_rpc_runtime_api::RelayApi< - Block, - VaultId, - > for Runtime { - fn is_transaction_invalid(vault_id: VaultId, raw_tx: Vec) -> DispatchResult { - Relay::is_transaction_invalid(&vault_id, raw_tx) - } - } - impl module_vault_registry_rpc_runtime_api::VaultRegistryApi< Block, VaultId, diff --git a/parachain/runtime/runtime-tests/Cargo.toml b/parachain/runtime/runtime-tests/Cargo.toml index 8d7ea549c1..45b86d2bed 100644 --- a/parachain/runtime/runtime-tests/Cargo.toml +++ b/parachain/runtime/runtime-tests/Cargo.toml @@ -83,7 +83,6 @@ pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release btc-relay = { path = "../../../crates/btc-relay", default-features = false } currency = { path = "../../../crates/currency", default-features = false } security = { path = "../../../crates/security", default-features = false } -relay = { path = "../../../crates/relay", default-features = false } vault-registry = { path = "../../../crates/vault-registry", default-features = false } oracle = { path = "../../../crates/oracle", default-features = false } fee = { path = "../../../crates/fee", default-features = false } @@ -108,7 +107,6 @@ primitives = { package = "interbtc-primitives", path = "../../../primitives", de module-btc-relay-rpc-runtime-api = { path = "../../../crates/btc-relay/rpc/runtime-api", default-features = false } module-oracle-rpc-runtime-api = { path = "../../../crates/oracle/rpc/runtime-api", default-features = false } -module-relay-rpc-runtime-api = { path = "../../../crates/relay/rpc/runtime-api", default-features = false } module-vault-registry-rpc-runtime-api = { path = "../../../crates/vault-registry/rpc/runtime-api", default-features = false } module-issue-rpc-runtime-api = { path = "../../../crates/issue/rpc/runtime-api", default-features = false } module-redeem-rpc-runtime-api = { path = "../../../crates/redeem/rpc/runtime-api", default-features = false } @@ -204,11 +202,9 @@ std = [ "testnet-kintsugi-runtime-parachain/std", "testnet-interlay-runtime-parachain/std", - "btc-relay/std", "btc-relay/std", "currency/std", "security/std", - "relay/std", "vault-registry/std", "oracle/std", "fee/std", @@ -230,7 +226,6 @@ std = [ "module-btc-relay-rpc-runtime-api/std", "module-oracle-rpc-runtime-api/std", - "module-relay-rpc-runtime-api/std", "module-vault-registry-rpc-runtime-api/std", "module-issue-rpc-runtime-api/std", "module-redeem-rpc-runtime-api/std", @@ -261,7 +256,6 @@ runtime-benchmarks = [ "issue/runtime-benchmarks", "redeem/runtime-benchmarks", "replace/runtime-benchmarks", - "relay/runtime-benchmarks", "vault-registry/runtime-benchmarks", "fee/runtime-benchmarks", ] diff --git a/parachain/runtime/testnet-interlay/Cargo.toml b/parachain/runtime/testnet-interlay/Cargo.toml index 778d9d943b..16e1416a0d 100644 --- a/parachain/runtime/testnet-interlay/Cargo.toml +++ b/parachain/runtime/testnet-interlay/Cargo.toml @@ -80,7 +80,6 @@ pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release btc-relay = { path = "../../../crates/btc-relay", default-features = false } currency = { path = "../../../crates/currency", default-features = false } security = { path = "../../../crates/security", default-features = false } -relay = { path = "../../../crates/relay", default-features = false } vault-registry = { path = "../../../crates/vault-registry", default-features = false } oracle = { path = "../../../crates/oracle", default-features = false } fee = { path = "../../../crates/fee", default-features = false } @@ -100,7 +99,6 @@ primitives = { package = "interbtc-primitives", path = "../../../primitives", de module-btc-relay-rpc-runtime-api = { path = "../../../crates/btc-relay/rpc/runtime-api", default-features = false } module-oracle-rpc-runtime-api = { path = "../../../crates/oracle/rpc/runtime-api", default-features = false } -module-relay-rpc-runtime-api = { path = "../../../crates/relay/rpc/runtime-api", default-features = false } module-vault-registry-rpc-runtime-api = { path = "../../../crates/vault-registry/rpc/runtime-api", default-features = false } module-issue-rpc-runtime-api = { path = "../../../crates/issue/rpc/runtime-api", default-features = false } module-redeem-rpc-runtime-api = { path = "../../../crates/redeem/rpc/runtime-api", default-features = false } @@ -196,7 +194,6 @@ std = [ "btc-relay/std", "currency/std", "security/std", - "relay/std", "vault-registry/std", "oracle/std", "fee/std", @@ -218,7 +215,6 @@ std = [ "module-btc-relay-rpc-runtime-api/std", "module-oracle-rpc-runtime-api/std", - "module-relay-rpc-runtime-api/std", "module-vault-registry-rpc-runtime-api/std", "module-issue-rpc-runtime-api/std", "module-redeem-rpc-runtime-api/std", @@ -253,7 +249,6 @@ runtime-benchmarks = [ "oracle/runtime-benchmarks", "redeem/runtime-benchmarks", "refund/runtime-benchmarks", - "relay/runtime-benchmarks", "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", ] diff --git a/parachain/runtime/testnet-interlay/src/lib.rs b/parachain/runtime/testnet-interlay/src/lib.rs index e21aca0fce..612677e930 100644 --- a/parachain/runtime/testnet-interlay/src/lib.rs +++ b/parachain/runtime/testnet-interlay/src/lib.rs @@ -58,7 +58,7 @@ pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; // interBTC exports -pub use btc_relay::{bitcoin, Call as RelayCall, TARGET_SPACING}; +pub use btc_relay::{bitcoin, Call as BtcRelayCall, TARGET_SPACING}; pub use constants::{currency::*, time::*}; pub use module_oracle_rpc_runtime_api::BalanceWrapper; pub use security::StatusCode; @@ -859,8 +859,6 @@ impl security::Config for Runtime { type Event = Event; } -pub use relay::Event as RelayEvent; - pub struct CurrencyConvert; impl currency::CurrencyConversion, CurrencyId> for CurrencyConvert { fn convert(amount: ¤cy::Amount, to: CurrencyId) -> Result, DispatchError> { @@ -879,11 +877,6 @@ impl currency::Config for Runtime { type CurrencyConversion = CurrencyConvert; } -impl relay::Config for Runtime { - type Event = Event; - type WeightInfo = (); -} - impl staking::Config for Runtime { type Event = Event; type SignedFixedPoint = SignedFixedPoint; @@ -1030,7 +1023,7 @@ construct_runtime! { Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 7, Identity: pallet_identity::{Pallet, Call, Storage, Event} = 8, - // Tokens & Balances + // # Tokens & Balances Currency: currency::{Pallet} = 20, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event} = 21, Supply: supply::{Pallet, Storage, Call, Event, Config} = 22, @@ -1045,11 +1038,11 @@ construct_runtime! { VaultRewards: reward::::{Pallet, Storage, Event} = 41, VaultStaking: staking::{Pallet, Storage, Event} = 42, - // Bitcoin SPV + // # Bitcoin SPV BTCRelay: btc_relay::{Pallet, Call, Config, Storage, Event} = 50, - Relay: relay::{Pallet, Call, Storage, Event} = 51, + // Relay: 51 - // Operational + // # Operational Security: security::{Pallet, Call, Config, Storage, Event} = 60, VaultRegistry: vault_registry::{Pallet, Call, Config, Storage, Event, ValidateUnsigned} = 61, Oracle: oracle::{Pallet, Call, Config, Storage, Event} = 62, @@ -1060,7 +1053,7 @@ construct_runtime! { Refund: refund::{Pallet, Call, Config, Storage, Event} = 67, Nomination: nomination::{Pallet, Call, Config, Storage, Event} = 68, - // Governance + // # Governance Democracy: democracy::{Pallet, Call, Storage, Config, Event} = 70, TechnicalCommittee: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 71, TechnicalMembership: pallet_membership::{Pallet, Call, Storage, Event, Config} = 72, @@ -1074,7 +1067,7 @@ construct_runtime! { ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event} = 85, ParachainInfo: parachain_info::{Pallet, Storage, Config} = 86, - // XCM Helpers + // # XCM Helpers XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 90, PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 91, CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin} = 92, @@ -1246,7 +1239,6 @@ impl_runtime_apis! { list_benchmark!(list, extra, oracle, Oracle); list_benchmark!(list, extra, redeem, Redeem); list_benchmark!(list, extra, refund, Refund); - list_benchmark!(list, extra, relay, Relay); list_benchmark!(list, extra, replace, Replace); list_benchmark!(list, extra, vault_registry, VaultRegistry); @@ -1283,7 +1275,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, oracle, Oracle); add_benchmark!(params, batches, redeem, Redeem); add_benchmark!(params, batches, refund, Refund); - add_benchmark!(params, batches, relay, Relay); add_benchmark!(params, batches, replace, Replace); add_benchmark!(params, batches, vault_registry, VaultRegistry); @@ -1317,15 +1308,6 @@ impl_runtime_apis! { } } - impl module_relay_rpc_runtime_api::RelayApi< - Block, - VaultId, - > for Runtime { - fn is_transaction_invalid(vault_id: VaultId, raw_tx: Vec) -> DispatchResult { - Relay::is_transaction_invalid(&vault_id, raw_tx) - } - } - impl module_vault_registry_rpc_runtime_api::VaultRegistryApi< Block, VaultId, diff --git a/parachain/runtime/testnet-kintsugi/Cargo.toml b/parachain/runtime/testnet-kintsugi/Cargo.toml index 5f30c5e995..fb6341bc67 100644 --- a/parachain/runtime/testnet-kintsugi/Cargo.toml +++ b/parachain/runtime/testnet-kintsugi/Cargo.toml @@ -80,7 +80,6 @@ pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release btc-relay = { path = "../../../crates/btc-relay", default-features = false } currency = { path = "../../../crates/currency", default-features = false } security = { path = "../../../crates/security", default-features = false } -relay = { path = "../../../crates/relay", default-features = false } vault-registry = { path = "../../../crates/vault-registry", default-features = false } oracle = { path = "../../../crates/oracle", default-features = false } fee = { path = "../../../crates/fee", default-features = false } @@ -100,7 +99,6 @@ primitives = { package = "interbtc-primitives", path = "../../../primitives", de module-btc-relay-rpc-runtime-api = { path = "../../../crates/btc-relay/rpc/runtime-api", default-features = false } module-oracle-rpc-runtime-api = { path = "../../../crates/oracle/rpc/runtime-api", default-features = false } -module-relay-rpc-runtime-api = { path = "../../../crates/relay/rpc/runtime-api", default-features = false } module-vault-registry-rpc-runtime-api = { path = "../../../crates/vault-registry/rpc/runtime-api", default-features = false } module-issue-rpc-runtime-api = { path = "../../../crates/issue/rpc/runtime-api", default-features = false } module-redeem-rpc-runtime-api = { path = "../../../crates/redeem/rpc/runtime-api", default-features = false } @@ -196,7 +194,6 @@ std = [ "btc-relay/std", "currency/std", "security/std", - "relay/std", "vault-registry/std", "oracle/std", "fee/std", @@ -218,7 +215,6 @@ std = [ "module-btc-relay-rpc-runtime-api/std", "module-oracle-rpc-runtime-api/std", - "module-relay-rpc-runtime-api/std", "module-vault-registry-rpc-runtime-api/std", "module-issue-rpc-runtime-api/std", "module-redeem-rpc-runtime-api/std", @@ -253,7 +249,6 @@ runtime-benchmarks = [ "oracle/runtime-benchmarks", "redeem/runtime-benchmarks", "refund/runtime-benchmarks", - "relay/runtime-benchmarks", "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", ] diff --git a/parachain/runtime/testnet-kintsugi/src/lib.rs b/parachain/runtime/testnet-kintsugi/src/lib.rs index d45fa0ae38..a3ad1e45cd 100644 --- a/parachain/runtime/testnet-kintsugi/src/lib.rs +++ b/parachain/runtime/testnet-kintsugi/src/lib.rs @@ -58,7 +58,7 @@ pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; // interBTC exports -pub use btc_relay::{bitcoin, Call as RelayCall, TARGET_SPACING}; +pub use btc_relay::{bitcoin, Call as BtcRelayCall, TARGET_SPACING}; pub use constants::{currency::*, time::*}; pub use module_oracle_rpc_runtime_api::BalanceWrapper; pub use security::StatusCode; @@ -859,8 +859,6 @@ impl security::Config for Runtime { type Event = Event; } -pub use relay::Event as RelayEvent; - pub struct CurrencyConvert; impl currency::CurrencyConversion, CurrencyId> for CurrencyConvert { fn convert(amount: ¤cy::Amount, to: CurrencyId) -> Result, DispatchError> { @@ -879,11 +877,6 @@ impl currency::Config for Runtime { type CurrencyConversion = CurrencyConvert; } -impl relay::Config for Runtime { - type Event = Event; - type WeightInfo = (); -} - impl staking::Config for Runtime { type Event = Event; type SignedFixedPoint = SignedFixedPoint; @@ -1030,7 +1023,7 @@ construct_runtime! { Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 7, Identity: pallet_identity::{Pallet, Call, Storage, Event} = 8, - // Tokens & Balances + // # Tokens & Balances Currency: currency::{Pallet} = 20, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event} = 21, Supply: supply::{Pallet, Storage, Call, Event, Config} = 22, @@ -1045,11 +1038,11 @@ construct_runtime! { VaultRewards: reward::::{Pallet, Storage, Event} = 41, VaultStaking: staking::{Pallet, Storage, Event} = 42, - // Bitcoin SPV + // # Bitcoin SPV BTCRelay: btc_relay::{Pallet, Call, Config, Storage, Event} = 50, - Relay: relay::{Pallet, Call, Storage, Event} = 51, + // Relay: 51 - // Operational + // # Operational Security: security::{Pallet, Call, Config, Storage, Event} = 60, VaultRegistry: vault_registry::{Pallet, Call, Config, Storage, Event, ValidateUnsigned} = 61, Oracle: oracle::{Pallet, Call, Config, Storage, Event} = 62, @@ -1060,7 +1053,7 @@ construct_runtime! { Refund: refund::{Pallet, Call, Config, Storage, Event} = 67, Nomination: nomination::{Pallet, Call, Config, Storage, Event} = 68, - // Governance + // # Governance Democracy: democracy::{Pallet, Call, Storage, Config, Event} = 70, TechnicalCommittee: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 71, TechnicalMembership: pallet_membership::{Pallet, Call, Storage, Event, Config} = 72, @@ -1074,7 +1067,7 @@ construct_runtime! { ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event} = 85, ParachainInfo: parachain_info::{Pallet, Storage, Config} = 86, - // XCM Helpers + // # XCM Helpers XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 90, PolkadotXcm: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 91, CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event, Origin} = 92, @@ -1246,7 +1239,6 @@ impl_runtime_apis! { list_benchmark!(list, extra, oracle, Oracle); list_benchmark!(list, extra, redeem, Redeem); list_benchmark!(list, extra, refund, Refund); - list_benchmark!(list, extra, relay, Relay); list_benchmark!(list, extra, replace, Replace); list_benchmark!(list, extra, vault_registry, VaultRegistry); @@ -1283,7 +1275,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, oracle, Oracle); add_benchmark!(params, batches, redeem, Redeem); add_benchmark!(params, batches, refund, Refund); - add_benchmark!(params, batches, relay, Relay); add_benchmark!(params, batches, replace, Replace); add_benchmark!(params, batches, vault_registry, VaultRegistry); @@ -1317,15 +1308,6 @@ impl_runtime_apis! { } } - impl module_relay_rpc_runtime_api::RelayApi< - Block, - VaultId, - > for Runtime { - fn is_transaction_invalid(vault_id: VaultId, raw_tx: Vec) -> DispatchResult { - Relay::is_transaction_invalid(&vault_id, raw_tx) - } - } - impl module_vault_registry_rpc_runtime_api::VaultRegistryApi< Block, VaultId, diff --git a/parachain/src/service.rs b/parachain/src/service.rs index 9d7a257385..9fbdf2bdb1 100644 --- a/parachain/src/service.rs +++ b/parachain/src/service.rs @@ -70,7 +70,6 @@ pub trait RuntimeApiCollection: + cumulus_primitives_core::CollectCollationInfo + module_btc_relay_rpc_runtime_api::BtcRelayApi + module_oracle_rpc_runtime_api::OracleApi - + module_relay_rpc_runtime_api::RelayApi> + module_vault_registry_rpc_runtime_api::VaultRegistryApi< Block, VaultId, @@ -117,7 +116,6 @@ where + cumulus_primitives_core::CollectCollationInfo + module_btc_relay_rpc_runtime_api::BtcRelayApi + module_oracle_rpc_runtime_api::OracleApi - + module_relay_rpc_runtime_api::RelayApi> + module_vault_registry_rpc_runtime_api::VaultRegistryApi< Block, VaultId, diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 5211beab97..e62aa4175a 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -11,7 +11,6 @@ jsonrpsee = { version = "0.13.0", features = ["server", "macros"] } # Parachain dependencies module-btc-relay-rpc = { path = "../crates/btc-relay/rpc" } module-oracle-rpc = { path = "../crates/oracle/rpc" } -module-relay-rpc = { path = "../crates/relay/rpc" } module-vault-registry-rpc = { path = "../crates/vault-registry/rpc" } module-issue-rpc = { path = "../crates/issue/rpc" } module-redeem-rpc = { path = "../crates/redeem/rpc" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index cc9751d2f9..5a1204505a 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -46,7 +46,6 @@ where C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, C::Api: module_btc_relay_rpc::BtcRelayRuntimeApi, C::Api: module_oracle_rpc::OracleRuntimeApi, - C::Api: module_relay_rpc::RelayRuntimeApi>, C::Api: module_vault_registry_rpc::VaultRegistryRuntimeApi< Block, VaultId, @@ -82,7 +81,6 @@ where use module_oracle_rpc::{Oracle, OracleApiServer}; use module_redeem_rpc::{Redeem, RedeemApiServer}; use module_refund_rpc::{Refund, RefundApiServer}; - use module_relay_rpc::{Relay, RelayApiServer}; use module_replace_rpc::{Replace, ReplaceApiServer}; use module_vault_registry_rpc::{VaultRegistry, VaultRegistryApiServer}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; @@ -112,8 +110,6 @@ where module.merge(Oracle::new(client.clone()).into_rpc())?; - module.merge(Relay::new(client.clone()).into_rpc())?; - module.merge(VaultRegistry::new(client.clone()).into_rpc())?; module.merge(Issue::new(client.clone()).into_rpc())?; diff --git a/standalone/runtime/Cargo.toml b/standalone/runtime/Cargo.toml index 757a6d9f75..f945f53a40 100644 --- a/standalone/runtime/Cargo.toml +++ b/standalone/runtime/Cargo.toml @@ -60,7 +60,6 @@ pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = btc-relay = { path = "../../crates/btc-relay", default-features = false } currency = { path = "../../crates/currency", default-features = false } security = { path = "../../crates/security", default-features = false } -relay = { path = "../../crates/relay", default-features = false } vault-registry = { path = "../../crates/vault-registry", default-features = false } oracle = { path = "../../crates/oracle", default-features = false } fee = { path = "../../crates/fee", default-features = false } @@ -80,7 +79,6 @@ primitives = { package = "interbtc-primitives", path = "../../primitives", defau module-btc-relay-rpc-runtime-api = { path = "../../crates/btc-relay/rpc/runtime-api", default-features = false } module-oracle-rpc-runtime-api = { path = "../../crates/oracle/rpc/runtime-api", default-features = false } -module-relay-rpc-runtime-api = { path = "../../crates/relay/rpc/runtime-api", default-features = false } module-vault-registry-rpc-runtime-api = { path = "../../crates/vault-registry/rpc/runtime-api", default-features = false } module-issue-rpc-runtime-api = { path = "../../crates/issue/rpc/runtime-api", default-features = false } module-redeem-rpc-runtime-api = { path = "../../crates/redeem/rpc/runtime-api", default-features = false } @@ -159,7 +157,6 @@ std = [ "btc-relay/std", "currency/std", "security/std", - "relay/std", "vault-registry/std", "oracle/std", "fee/std", @@ -179,7 +176,6 @@ std = [ "module-btc-relay-rpc-runtime-api/std", "module-oracle-rpc-runtime-api/std", - "module-relay-rpc-runtime-api/std", "module-vault-registry-rpc-runtime-api/std", "module-issue-rpc-runtime-api/std", "module-redeem-rpc-runtime-api/std", @@ -214,7 +210,6 @@ runtime-benchmarks = [ "oracle/runtime-benchmarks", "redeem/runtime-benchmarks", "refund/runtime-benchmarks", - "relay/runtime-benchmarks", "replace/runtime-benchmarks", "vault-registry/runtime-benchmarks", diff --git a/standalone/runtime/src/lib.rs b/standalone/runtime/src/lib.rs index 27a36b97bf..7b2002d26f 100644 --- a/standalone/runtime/src/lib.rs +++ b/standalone/runtime/src/lib.rs @@ -59,7 +59,7 @@ pub use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; // interBTC exports -pub use btc_relay::{bitcoin, Call as RelayCall, TARGET_SPACING}; +pub use btc_relay::{bitcoin, Call as BtcRelayCall, TARGET_SPACING}; pub use module_oracle_rpc_runtime_api::BalanceWrapper; pub use security::StatusCode; @@ -795,8 +795,6 @@ impl security::Config for Runtime { type Event = Event; } -pub use relay::Event as RelayEvent; - pub struct CurrencyConvert; impl currency::CurrencyConversion, CurrencyId> for CurrencyConvert { fn convert(amount: ¤cy::Amount, to: CurrencyId) -> Result, DispatchError> { @@ -815,11 +813,6 @@ impl currency::Config for Runtime { type CurrencyConversion = CurrencyConvert; } -impl relay::Config for Runtime { - type Event = Event; - type WeightInfo = (); -} - impl staking::Config for Runtime { type Event = Event; type SignedFixedPoint = SignedFixedPoint; @@ -987,7 +980,7 @@ construct_runtime! { Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 6, Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 7, - // Tokens & Balances + // # Tokens & Balances Currency: currency::{Pallet} = 8, Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event} = 9, Escrow: escrow::{Pallet, Call, Storage, Event} = 10, @@ -1003,12 +996,12 @@ construct_runtime! { Supply: supply::{Pallet, Storage, Call, Event, Config} = 17, - // Bitcoin SPV + // # Bitcoin SPV BTCRelay: btc_relay::{Pallet, Call, Config, Storage, Event} = 18, - // Operational + // # Operational Security: security::{Pallet, Call, Config, Storage, Event} = 19, - Relay: relay::{Pallet, Call, Storage, Event} = 20, + // Relay: 20 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, @@ -1020,7 +1013,7 @@ construct_runtime! { Identity: pallet_identity::{Pallet, Call, Storage, Event} = 36, - // Governance + // # Governance Democracy: democracy::{Pallet, Call, Storage, Config, Event} = 29, TechnicalCommittee: pallet_collective::::{Pallet, Call, Storage, Origin, Event, Config} = 30, TechnicalMembership: pallet_membership::{Pallet, Call, Storage, Event, Config} = 31, @@ -1213,7 +1206,6 @@ impl_runtime_apis! { list_benchmark!(list, extra, oracle, Oracle); list_benchmark!(list, extra, redeem, Redeem); list_benchmark!(list, extra, refund, Refund); - list_benchmark!(list, extra, relay, Relay); list_benchmark!(list, extra, replace, Replace); list_benchmark!(list, extra, vault_registry, VaultRegistry); @@ -1252,7 +1244,6 @@ impl_runtime_apis! { add_benchmark!(params, batches, oracle, Oracle); add_benchmark!(params, batches, redeem, Redeem); add_benchmark!(params, batches, refund, Refund); - add_benchmark!(params, batches, relay, Relay); add_benchmark!(params, batches, replace, Replace); add_benchmark!(params, batches, vault_registry, VaultRegistry); @@ -1286,15 +1277,6 @@ impl_runtime_apis! { } } - impl module_relay_rpc_runtime_api::RelayApi< - Block, - VaultId, - > for Runtime { - fn is_transaction_invalid(vault_id: VaultId, raw_tx: Vec) -> DispatchResult { - Relay::is_transaction_invalid(&vault_id, raw_tx) - } - } - impl module_vault_registry_rpc_runtime_api::VaultRegistryApi< Block, VaultId, diff --git a/standalone/runtime/tests/mock/mod.rs b/standalone/runtime/tests/mock/mod.rs index 3fe3e50493..34bf3aad4c 100644 --- a/standalone/runtime/tests/mock/mod.rs +++ b/standalone/runtime/tests/mock/mod.rs @@ -160,10 +160,6 @@ pub type SecurityCall = security::Call; pub type SudoCall = pallet_sudo::Call; -pub type RelayCall = relay::Call; -pub type RelayPallet = relay::Pallet; -pub type RelayError = relay::Error; - pub type SystemPallet = frame_system::Pallet; pub type SystemError = frame_system::Error; @@ -1187,7 +1183,7 @@ impl TransactionGenerator { .expect("could not serialize block header"); let init_block_header = BTCRelayPallet::parse_raw_block_header(&raw_init_block_header).unwrap(); - match BTCRelayPallet::initialize(account_of(ALICE), init_block_header, height) { + match BTCRelayPallet::_initialize(account_of(ALICE), init_block_header, height) { Ok(_) => {} Err(e) if e == BTCRelayError::AlreadyInitialized.into() => {} _ => panic!("Failed to initialize btc relay"), @@ -1282,7 +1278,7 @@ impl TransactionGenerator { fn relay(&self, height: u32, block: &Block, raw_block_header: RawBlockHeader) { if let Some(relayer) = self.relayer { - assert_ok!(Call::Relay(RelayCall::store_block_header { + assert_ok!(Call::BTCRelay(BTCRelayCall::store_block_header { raw_block_header: raw_block_header }) .dispatch(origin_of(account_of(relayer)))); @@ -1290,7 +1286,7 @@ impl TransactionGenerator { } else { // bypass staked relayer module let block_header = BTCRelayPallet::parse_raw_block_header(&raw_block_header).unwrap(); - assert_ok!(BTCRelayPallet::store_block_header(&account_of(ALICE), block_header)); + assert_ok!(BTCRelayPallet::_store_block_header(&account_of(ALICE), block_header)); assert_store_main_chain_header_event(height, block.header.hash, account_of(ALICE)); } } diff --git a/standalone/runtime/tests/test_btc_relay.rs b/standalone/runtime/tests/test_btc_relay.rs index ebf2c1ba6a..a345a7d85e 100644 --- a/standalone/runtime/tests/test_btc_relay.rs +++ b/standalone/runtime/tests/test_btc_relay.rs @@ -36,7 +36,7 @@ fn integration_test_submit_block_headers_and_verify_transaction_inclusion() { let parachain_genesis_height = test_data[skip_blocks].height; assert_eq!(parachain_genesis_height % DIFFICULTY_ADJUSTMENT_INTERVAL, 0); - assert_ok!(Call::Relay(RelayCall::initialize { + assert_ok!(Call::BTCRelay(BTCRelayCall::initialize { raw_block_header: parachain_genesis_header, block_height: parachain_genesis_height }) @@ -55,7 +55,7 @@ fn integration_test_submit_block_headers_and_verify_transaction_inclusion() { assert!(best_block_hash == prev_header_hash); // submit block hashes - assert_ok!(Call::Relay(RelayCall::store_block_header { + assert_ok!(Call::BTCRelay(BTCRelayCall::store_block_header { raw_block_header: block.get_raw_header() }) .dispatch(origin_of(account_of(ALICE)))); @@ -159,7 +159,7 @@ fn integration_test_submit_fork_headers() { // without going through the `relay` pallet, which checks for the block version when parsing let genesis_header = bitcoin::parser::parse_block_header_lenient(&raw_genesis_header).unwrap(); - assert_ok!(BTCRelayPallet::initialize( + assert_ok!(BTCRelayPallet::_initialize( account_of(ALICE), genesis_header, genesis_height @@ -171,7 +171,7 @@ fn integration_test_submit_fork_headers() { SecurityPallet::set_active_block_number(index as u32); let header = bitcoin::parser::parse_block_header_lenient(raw_header).unwrap(); - assert_ok!(BTCRelayPallet::store_block_header(&account_of(ALICE), header)); + assert_ok!(BTCRelayPallet::_store_block_header(&account_of(ALICE), header)); assert_store_main_chain_header_event(index as u32, header.hash, account_of(ALICE)); } @@ -181,7 +181,7 @@ fn integration_test_submit_fork_headers() { let header = bitcoin::parser::parse_block_header_lenient(raw_header).unwrap(); let height: u32 = index as u32 - NUM_FORK_HEADERS; - assert_ok!(BTCRelayPallet::store_block_header(&account_of(ALICE), header)); + assert_ok!(BTCRelayPallet::_store_block_header(&account_of(ALICE), header)); // depending on the height and header, we expect different events and chain state match height { diff --git a/standalone/runtime/tests/test_relayers.rs b/standalone/runtime/tests/test_relayers.rs deleted file mode 100644 index 676083cbe0..0000000000 --- a/standalone/runtime/tests/test_relayers.rs +++ /dev/null @@ -1,553 +0,0 @@ -mod mock; - -use crate::redeem_testing_utils::{setup_redeem, USER}; -use currency::Amount; -use mock::{assert_eq, replace_testing_utils::*, *}; -use refund::types::RefundRequestExt; -use sp_core::H256; - -pub const RELAYER: [u8; 32] = ALICE; -pub const VAULT: [u8; 32] = BOB; - -fn test_with(execute: impl Fn(CurrencyId) -> R) { - let test_with = |currency_id| { - ExtBuilder::build().execute_with(|| { - assert_ok!(OraclePallet::_set_exchange_rate(currency_id, FixedU128::one())); - UserData::force_to(USER, default_user_state()); - execute(currency_id) - }) - }; - test_with(Token(DOT)); - test_with(Token(KSM)); - test_with(ForeignAsset(1)); -} - -fn setup_vault_for_potential_double_spend( - issued_tokens: Amount, - stealing_vault: [u8; 32], - issue_tokens: bool, -) -> (BtcPublicKey, BtcPublicKey) { - let vault_public_key_one = BtcPublicKey([ - 2, 168, 49, 109, 0, 14, 227, 106, 112, 84, 59, 37, 153, 238, 121, 44, 66, 8, 181, 64, 248, 19, 137, 27, 47, - 222, 50, 95, 187, 221, 152, 165, 69, - ]); - - let vault_public_key_two = BtcPublicKey([ - 2, 139, 220, 235, 13, 249, 164, 152, 179, 4, 175, 217, 170, 84, 218, 179, 182, 247, 109, 48, 57, 152, 241, 165, - 225, 26, 242, 187, 160, 225, 248, 195, 250, - ]); - - let vault_id = VaultId::new( - account_of(stealing_vault), - DEFAULT_COLLATERAL_CURRENCY, - DEFAULT_WRAPPED_CURRENCY, - ); - register_vault_with_public_key( - &vault_id, - Amount::new(INITIAL_BALANCE, vault_id.collateral_currency()), - vault_public_key_one.clone(), - ); - - if issue_tokens { - assert_ok!(VaultRegistryPallet::try_increase_to_be_issued_tokens( - &default_vault_id_of(stealing_vault), - &issued_tokens, - )); - assert_ok!(VaultRegistryPallet::issue_tokens( - &default_vault_id_of(stealing_vault), - &issued_tokens - )); - } - (vault_public_key_one, vault_public_key_two) -} - -#[test] -fn integration_test_report_vault_theft() { - test_with(|currency_id| { - let user = ALICE; - let vault = BOB; - let theft_amount = wrapped(100); - let collateral_vault = Amount::new(1000000, currency_id); - let issued_tokens = wrapped(100); - let vault_id = vault_id_of(vault, currency_id); - - let vault_btc_address = BtcAddress::P2SH(H160([ - 215, 255, 109, 96, 235, 244, 10, 155, 24, 134, 172, 206, 6, 101, 59, 162, 34, 77, 143, 234, - ])); - let other_btc_address = BtcAddress::P2SH(H160([1; 20])); - - SecurityPallet::set_active_block_number(1); - - register_vault(&vault_id, collateral_vault); - - assert_ok!(VaultRegistryPallet::insert_vault_deposit_address( - vault_id.clone(), - vault_btc_address - )); - - assert_ok!(VaultRegistryPallet::try_increase_to_be_issued_tokens( - &vault_id, - &issued_tokens, - )); - assert_ok!(VaultRegistryPallet::issue_tokens(&vault_id, &issued_tokens)); - - let (_tx_id, _height, proof, raw_tx, _) = TransactionGenerator::new() - .with_outputs(vec![(other_btc_address, theft_amount)]) - .with_confirmations(7) - .with_relayer(Some(ALICE)) - .mine(); - - SecurityPallet::set_active_block_number(1000); - - let pre_liquidation_state = ParachainState::get(&vault_id); - let theft_fee = FeePallet::get_theft_fee(&collateral_vault).unwrap(); - - assert_ok!(Call::Relay(RelayCall::report_vault_theft { - vault_id: vault_id.clone(), - raw_merkle_proof: proof, - raw_tx: raw_tx - }) - .dispatch(origin_of(account_of(user)))); - - let confiscated_collateral = Amount::new(110, currency_id); - assert_eq!( - ParachainState::get(&vault_id), - pre_liquidation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - - (*user.balances.get_mut(¤cy_id).unwrap()).free += theft_fee; - - vault.issued -= issued_tokens; - vault.backing_collateral -= confiscated_collateral; - vault.backing_collateral -= theft_fee; - vault.status = VaultStatus::CommittedTheft; - - liquidation_vault.issued += issued_tokens; - liquidation_vault.collateral += confiscated_collateral; - }) - ); - }); -} - -#[test] -fn prevent_double_payment_force_liquidation() { - test_with(|_currency_id| { - let issued_tokens = wrapped(10_000); - // Register _honest_ vault with hardcoded public key - let victim_vault = DAVE; - let (vault_public_key_one, _vault_public_key_two) = - setup_vault_for_potential_double_spend(issued_tokens, victim_vault, true); - - // User request redeem - let redeem_id = setup_redeem(issued_tokens, USER, &default_vault_id_of(victim_vault)); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - let user_btc_address = BtcAddress::P2PKH(H160([2; 20])); - let current_block_number = 1; - - // Send the honest redeem transaction - let (_tx_id, _tx_block_height, merkle_proof, raw_tx, _) = { - register_addresses_and_mine_transaction( - default_vault_id_of(victim_vault), - vault_public_key_one, - vec![], - vec![(user_btc_address, redeem.amount_btc())], - vec![redeem_id], - ) - }; - - // Confirmations - SecurityPallet::set_active_block_number(current_block_number + 1 + CONFIRMATIONS); - - // Redeem ok - assert_ok!(Call::Redeem(RedeemCall::execute_redeem { - redeem_id: redeem_id, - merkle_proof: merkle_proof.clone(), - raw_tx: raw_tx.clone() - }) - .dispatch(origin_of(account_of(victim_vault)))); - - let mut dup_tx = raw_tx.clone(); - dup_tx.push(0); // any extra bytes - - // Trying to report honest transaction as theft - assert_err!( - Call::Relay(RelayCall::report_vault_double_payment { - vault_id: default_vault_id_of(victim_vault), - raw_merkle_proofs: (merkle_proof.clone(), merkle_proof.clone()), - raw_txs: (raw_tx, dup_tx), - }) - .dispatch(origin_of(account_of(USER))), - RelayError::DuplicateTransaction - ); - }); -} - -#[test] -fn integration_test_double_spend_redeem() { - test_with(|_currency_id| { - let issued_tokens = wrapped(10_000); - // Register vault with hardcoded public key so it counts as theft - let stealing_vault = DAVE; - let (vault_public_key_one, vault_public_key_two) = - setup_vault_for_potential_double_spend(issued_tokens, stealing_vault, true); - - let redeem_id = setup_redeem(issued_tokens, USER, &default_vault_id_of(stealing_vault)); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - let user_btc_address = BtcAddress::P2PKH(H160([2; 20])); - let current_block_number = 1; - - // Send the honest redeem transaction - let (_tx_id, _tx_block_height, merkle_proof, raw_tx, _) = { - register_addresses_and_mine_transaction( - default_vault_id_of(stealing_vault), - vault_public_key_one, - vec![], - vec![(user_btc_address, redeem.amount_btc())], - vec![redeem_id], - ) - }; - - // Double-spend the redeem, so the redeemer gets twice the BTC - let (_theft_tx_id, _theft_tx_block_height, theft_merkle_proof, theft_raw_tx, _) = - register_addresses_and_mine_transaction( - default_vault_id_of(stealing_vault), - vault_public_key_two, - vec![], - vec![(user_btc_address, redeem.amount_btc())], - vec![redeem_id], - ); - SecurityPallet::set_active_block_number(current_block_number + 1 + CONFIRMATIONS); - - assert_ok!(Call::Redeem(RedeemCall::execute_redeem { - redeem_id: redeem_id, - merkle_proof: merkle_proof.clone(), - raw_tx: raw_tx.clone() - }) - .dispatch(origin_of(account_of(stealing_vault)))); - - // Executing the theft tx should fail - assert_err!( - Call::Redeem(RedeemCall::execute_redeem { - redeem_id: redeem_id, - merkle_proof: theft_merkle_proof.clone(), - raw_tx: theft_raw_tx.clone() - }) - .dispatch(origin_of(account_of(stealing_vault))), - RedeemError::RedeemCompleted - ); - - // Reporting the double-spend transaction as theft should work - assert_ok!(Call::Relay(RelayCall::report_vault_double_payment { - vault_id: default_vault_id_of(stealing_vault), - raw_merkle_proofs: (merkle_proof, theft_merkle_proof), - raw_txs: (raw_tx, theft_raw_tx), - }) - .dispatch(origin_of(account_of(USER)))); - }); -} - -fn redeem_with_extra_utxo(use_unregistered_btc_address: bool) -> DispatchResultWithPostInfo { - let issued_tokens = wrapped(10_000); - let vault = DAVE; - let (vault_public_key_one, vault_public_key_two) = - setup_vault_for_potential_double_spend(issued_tokens, vault, true); - let second_vault_btc_address = if use_unregistered_btc_address { - BtcAddress::P2PKH(H160([8; 20])) - } else { - let btc_address = BtcAddress::P2PKH(vault_public_key_two.to_hash()); - assert_ok!(VaultRegistryPallet::insert_vault_deposit_address( - default_vault_id_of(vault), - btc_address - )); - btc_address - }; - - let redeem_id = setup_redeem(issued_tokens, USER, &default_vault_id_of(vault)); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - let user_btc_address = BtcAddress::P2PKH(H160([2; 20])); - let current_block_number = 1; - - let (_tx_id, _tx_block_height, merkle_proof, raw_tx, _) = { - register_addresses_and_mine_transaction( - default_vault_id_of(vault), - vault_public_key_one, - vec![], - vec![ - (user_btc_address, redeem.amount_btc()), - (second_vault_btc_address, redeem.amount_btc()), - ], - vec![redeem_id], - ) - }; - - SecurityPallet::set_active_block_number(current_block_number + 1 + CONFIRMATIONS); - - assert_ok!(Call::Redeem(RedeemCall::execute_redeem { - redeem_id: redeem_id, - merkle_proof: merkle_proof.clone(), - raw_tx: raw_tx.clone() - }) - .dispatch(origin_of(account_of(vault)))); - - Call::Relay(RelayCall::report_vault_theft { - vault_id: default_vault_id_of(vault), - raw_merkle_proof: merkle_proof, - raw_tx: raw_tx, - }) - .dispatch(origin_of(account_of(USER))) -} - -#[test] -fn integration_test_redeem_valid_change_utxo() { - test_with(|_currency_id| { - // Reporting as theft should fail, because the additional UTXO was a change (leftover) tx - assert_err!(redeem_with_extra_utxo(false), RelayError::ValidRedeemTransaction); - }); -} - -#[test] -fn integration_test_redeem_utxo_to_foreign_address() { - test_with(|_currency_id| { - // Reporting as theft should work, because the additional UTXO was sent to an - // address that wasn't the redeemer not the vault's - assert_ok!(redeem_with_extra_utxo(true)); - }); -} - -#[test] -/// we used to allow merge transactions, but not anymore. Specifically test that we disallow it -fn integration_test_merge_tx_is_disallowed() { - test_with(|_currency_id| { - let vault = BOB; - let transfer_amount_raw = 100; - let transfer_amount = wrapped(transfer_amount_raw); - - let (vault_public_key_one, vault_public_key_two) = - setup_vault_for_potential_double_spend(transfer_amount, vault, false); - - let vault_public_key_three = BtcPublicKey([1u8; 33]); - let vault_public_key_four = BtcPublicKey([2u8; 33]); - - let vault_first_address = BtcAddress::P2PKH(vault_public_key_one.to_hash()); - let vault_second_address = BtcAddress::P2PKH(vault_public_key_two.to_hash()); - let vault_third_address = BtcAddress::P2PKH(vault_public_key_three.to_hash()); - let vault_fourth_address = BtcAddress::P2PKH(vault_public_key_four.to_hash()); - - // The first public key isn't added to the wallet automatically as a P2PKH address. - // Need to explicitly add it, otherwise the tx won't be considered a "merge" - register_vault_address(default_vault_id_of(vault), vault_public_key_one.clone()); - register_vault_address(default_vault_id_of(vault), vault_public_key_two.clone()); - register_vault_address(default_vault_id_of(vault), vault_public_key_three.clone()); - register_vault_address(default_vault_id_of(vault), vault_public_key_four.clone()); - - let (_, _, _, _, tx) = generate_transaction_and_mine( - vault_public_key_one.clone(), - vec![], - vec![ - (vault_first_address, transfer_amount), - (vault_second_address, transfer_amount), - (vault_third_address, transfer_amount), - (vault_fourth_address, transfer_amount), - ], - vec![], - ); - - let (_tx_id, _tx_block_height, merkle_proof, raw_tx, _) = generate_transaction_and_mine( - vault_public_key_one.clone(), - vec![ - (tx.clone(), 0, Some(vault_public_key_one)), - (tx.clone(), 1, Some(vault_public_key_two)), - (tx.clone(), 2, Some(vault_public_key_three)), - (tx, 3, Some(vault_public_key_four)), - ], - vec![(vault_first_address, wrapped(4 * transfer_amount_raw))], - vec![], - ); - - SecurityPallet::set_active_block_number(1 + CONFIRMATIONS); - - // Reporting as theft should succeed, because we no longer - // allow merge transactions - assert_ok!(Call::Relay(RelayCall::report_vault_theft { - vault_id: default_vault_id_of(vault), - raw_merkle_proof: merkle_proof, - raw_tx: raw_tx - }) - .dispatch(origin_of(account_of(USER)))); - }); -} - -#[test] -fn integration_test_double_spend_refund() { - test_with(|_currency_id| { - let issued_tokens = wrapped(10_000); - let stealing_vault = DAVE; - let (vault_public_key_one, vault_public_key_two) = - setup_vault_for_potential_double_spend(issued_tokens, stealing_vault, true); - - let user_btc_address = BtcAddress::P2PKH(H160([2; 20])); - let refund_amount = wrapped(10_000); - let refund_id = RefundPallet::request_refund( - &refund_amount, - default_vault_id_of(stealing_vault), - account_of(ALICE), - user_btc_address, - Default::default(), - ) - .unwrap() - .unwrap(); - let refund_request = RefundPallet::refund_requests(refund_id).unwrap(); - - let current_block_number = 1; - - // Send the honest refund transaction - let (_tx_id, _tx_block_height, merkle_proof, raw_tx, _) = { - register_addresses_and_mine_transaction( - default_vault_id_of(stealing_vault), - vault_public_key_one, - vec![], - vec![(user_btc_address, refund_request.amount_btc())], - vec![refund_id], - ) - }; - - // Double-spend the refund, so the payee gets twice the BTC - let (_theft_tx_id, _theft_tx_block_height, theft_merkle_proof, theft_raw_tx, _) = - register_addresses_and_mine_transaction( - default_vault_id_of(stealing_vault), - vault_public_key_two, - vec![], - vec![(user_btc_address, refund_request.amount_btc())], - vec![refund_id], - ); - SecurityPallet::set_active_block_number(current_block_number + 1 + CONFIRMATIONS); - - assert_ok!(Call::Refund(RefundCall::execute_refund { - refund_id: refund_id, - merkle_proof: merkle_proof.clone(), - raw_tx: raw_tx.clone() - }) - .dispatch(origin_of(account_of(stealing_vault)))); - - // Executing the theft tx should fail - assert_err!( - Call::Refund(RefundCall::execute_refund { - refund_id: refund_id, - merkle_proof: theft_merkle_proof.clone(), - raw_tx: theft_raw_tx.clone() - }) - .dispatch(origin_of(account_of(stealing_vault))), - RefundError::RefundCompleted - ); - - // Reporting the double-spend transaction as theft should work - assert_ok!(Call::Relay(RelayCall::report_vault_double_payment { - vault_id: default_vault_id_of(stealing_vault), - raw_merkle_proofs: (merkle_proof, theft_merkle_proof), - raw_txs: (raw_tx, theft_raw_tx), - }) - .dispatch(origin_of(account_of(USER)))); - }); -} - -#[test] -fn integration_test_double_spend_replace() { - test_with(|_currency_id| { - let issued_tokens = wrapped(1000); - let stealing_vault = BOB; - let stealing_vault_id = default_vault_id_of(stealing_vault); - let new_vault = CAROL; - let new_vault_id = default_vault_id_of(new_vault); - let replace_amount = wrapped(100); - - let (vault_public_key_one, vault_public_key_two) = - setup_vault_for_potential_double_spend(issued_tokens, stealing_vault, false); - - CoreVaultData::force_to(&stealing_vault_id, default_vault_state(&stealing_vault_id)); - CoreVaultData::force_to(&new_vault_id, default_vault_state(&new_vault_id)); - - request_replace(&stealing_vault_id, issued_tokens); - let (replace, replace_id) = setup_replace(&stealing_vault_id, &new_vault_id, replace_amount); - let current_block_number = 1; - - // Send the honest replace transaction - let (_tx_id, _tx_block_height, merkle_proof, raw_tx, _) = { - register_addresses_and_mine_transaction( - stealing_vault_id.clone(), - vault_public_key_one, - vec![], - vec![(replace.btc_address, replace_amount)], - vec![replace_id], - ) - }; - - // Double-spend the replace, so the payee gets twice the BTC - let (_theft_tx_id, _theft_tx_block_height, theft_merkle_proof, theft_raw_tx, _) = - register_addresses_and_mine_transaction( - stealing_vault_id.clone(), - vault_public_key_two, - vec![], - vec![(replace.btc_address, replace_amount)], - vec![replace_id], - ); - - SecurityPallet::set_active_block_number(current_block_number + 1 + CONFIRMATIONS); - assert_ok!(Call::Replace(ReplaceCall::execute_replace { - replace_id: replace_id, - merkle_proof: merkle_proof.clone(), - raw_tx: raw_tx.clone() - }) - .dispatch(origin_of(account_of(stealing_vault)))); - - // Executing the theft tx should fail - assert_err!( - Call::Replace(ReplaceCall::execute_replace { - replace_id: replace_id, - merkle_proof: theft_merkle_proof.clone(), - raw_tx: theft_raw_tx.clone() - }) - .dispatch(origin_of(account_of(stealing_vault))), - ReplaceError::ReplaceCompleted - ); - - // Reporting the double-spend transaction as theft should work - assert_ok!(Call::Relay(RelayCall::report_vault_double_payment { - vault_id: stealing_vault_id, - raw_merkle_proofs: (merkle_proof, theft_merkle_proof), - raw_txs: (raw_tx, theft_raw_tx), - }) - .dispatch(origin_of(account_of(USER)))); - }); -} - -#[test] -fn integration_test_relay_parachain_status_check_fails() { - ExtBuilder::build().execute_with(|| { - SecurityPallet::set_status(StatusCode::Shutdown); - - assert_noop!( - Call::Relay(RelayCall::initialize { - raw_block_header: Default::default(), - block_height: 0 - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered - ); - assert_noop!( - Call::Relay(RelayCall::store_block_header { - raw_block_header: Default::default() - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered - ); - assert_noop!( - Call::Relay(RelayCall::report_vault_theft { - vault_id: vault_id_of(ALICE, Token(DOT)), - raw_merkle_proof: Default::default(), - raw_tx: Default::default() - }) - .dispatch(origin_of(account_of(ALICE))), - SystemError::CallFiltered - ); - }) -} From 78bdebbdc2865a718b2d8ca42c2c5a8b5f65afff Mon Sep 17 00:00:00 2001 From: Gregory Hill Date: Thu, 21 Jul 2022 15:13:14 +0100 Subject: [PATCH 2/3] refactor!: remove VaultStatus::CommittedTheft and add migration Signed-off-by: Gregory Hill --- crates/vault-registry/src/lib.rs | 3 - crates/vault-registry/src/types.rs | 36 +- standalone/runtime/tests/test_redeem.rs | 466 ++++++++++++------------ 3 files changed, 256 insertions(+), 249 deletions(-) diff --git a/crates/vault-registry/src/lib.rs b/crates/vault-registry/src/lib.rs index 05659428b9..8ab62c812d 100644 --- a/crates/vault-registry/src/lib.rs +++ b/crates/vault-registry/src/lib.rs @@ -601,8 +601,6 @@ pub mod pallet { MaxNominationRatioViolation, /// The collateral ceiling would be exceeded for the vault's currency. CurrencyCeilingExceeded, - /// Vault is no longer usable as it was liquidated due to theft. - VaultCommittedTheft, /// Vault is no longer usable as it was liquidated due to undercollateralization. VaultLiquidated, /// Vault must be either liquidated or flagged for theft. @@ -846,7 +844,6 @@ impl Pallet { match vault.status { VaultStatus::Active(_) => Ok(vault), VaultStatus::Liquidated => Err(Error::::VaultLiquidated.into()), - VaultStatus::CommittedTheft => Err(Error::::VaultCommittedTheft.into()), } } diff --git a/crates/vault-registry/src/types.rs b/crates/vault-registry/src/types.rs index bbbeb59eb7..1f96a3e51a 100644 --- a/crates/vault-registry/src/types.rs +++ b/crates/vault-registry/src/types.rs @@ -190,6 +190,28 @@ pub mod liquidation_vault_fix { pub mod v4 { use super::*; + #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)] + pub enum VaultStatusV4 { + /// Vault is active - bool=true indicates that the vault accepts new issue requests + Active(bool), + + /// Vault has been liquidated + Liquidated, + + /// Vault theft has been reported + CommittedTheft, + } + + impl Into for VaultStatusV4 { + fn into(self) -> VaultStatus { + match self { + VaultStatusV4::Active(accept_issue) => VaultStatus::Active(accept_issue), + VaultStatusV4::Liquidated => VaultStatus::Liquidated, + VaultStatusV4::CommittedTheft => VaultStatus::Liquidated, + } + } + } + #[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug))] pub struct VaultV4 { @@ -198,7 +220,7 @@ pub mod v4 { /// Bitcoin address of this Vault (P2PKH, P2SH, P2WPKH, P2WSH) pub wallet: Wallet, /// Current status of the vault - pub status: VaultStatus, + pub status: VaultStatusV4, /// Block height until which this Vault is banned from being used for /// Issue, Redeem (except during automatic liquidation) and Replace. pub banned_until: Option, @@ -246,7 +268,7 @@ pub mod v4 { Some(Vault { id: vault_v4.id, wallet: vault_v4.wallet, - status: vault_v4.status, + status: vault_v4.status.into(), banned_until: vault_v4.banned_until, secure_collateral_threshold: None, to_be_issued_tokens: vault_v4.to_be_issued_tokens, @@ -293,7 +315,7 @@ pub mod v4 { .into(), }, banned_until: None, - status: VaultStatus::Active(true), + status: VaultStatusV4::Active(true), issued_tokens: Default::default(), liquidated_collateral: Default::default(), replace_collateral: Default::default(), @@ -316,7 +338,7 @@ pub mod v4 { wallet: Wallet { addresses: vault.wallet.addresses.clone(), }, - status: vault.status.clone(), + status: vault.status.into(), banned_until: vault.banned_until, secure_collateral_threshold: None, to_be_issued_tokens: vault.to_be_issued_tokens, @@ -370,10 +392,6 @@ pub enum VaultStatus { /// Vault has been liquidated Liquidated, - - /// Vault theft has been reported - // TODO: remove this, requires migration - CommittedTheft, } impl Default for VaultStatus { @@ -460,7 +478,7 @@ impl< } pub fn is_liquidated(&self) -> bool { - matches!(self.status, VaultStatus::Liquidated | VaultStatus::CommittedTheft) + matches!(self.status, VaultStatus::Liquidated) } } diff --git a/standalone/runtime/tests/test_redeem.rs b/standalone/runtime/tests/test_redeem.rs index 83f6f8a914..851e4265a7 100644 --- a/standalone/runtime/tests/test_redeem.rs +++ b/standalone/runtime/tests/test_redeem.rs @@ -1726,297 +1726,289 @@ fn integration_test_redeem_wrapped_cancel_no_reimburse() { #[test] fn integration_test_liquidation_redeem_with_cancel_redeem() { - for liquidation_status in [VaultStatus::CommittedTheft, VaultStatus::Liquidated] { - test_with(|vault_id| { - let currency_id = vault_id.collateral_currency(); - let issued_tokens = vault_id.wrapped(10_000); - let collateral_vault = Amount::new(1_000_000, currency_id); - VaultRegistryPallet::collateral_integrity_check(); - let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); - VaultRegistryPallet::collateral_integrity_check(); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); + test_with(|vault_id| { + let currency_id = vault_id.collateral_currency(); + let issued_tokens = vault_id.wrapped(10_000); + let collateral_vault = Amount::new(1_000_000, currency_id); + VaultRegistryPallet::collateral_integrity_check(); + let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); + VaultRegistryPallet::collateral_integrity_check(); + let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - // setup vault state such that 1/4th of its collateral is freed after successful redeem - let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); - CoreVaultData::force_to( - &vault_id, - CoreVaultData { - issued: consumed_issued_tokens * 2, - to_be_issued: vault_id.wrapped(0), - to_be_redeemed: consumed_issued_tokens, - backing_collateral: collateral_vault, - to_be_replaced: vault_id.wrapped(0), - replace_collateral: griefing(0), - ..default_vault_state(&vault_id) - }, - ); + // setup vault state such that 1/4th of its collateral is freed after successful redeem + let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); + CoreVaultData::force_to( + &vault_id, + CoreVaultData { + issued: consumed_issued_tokens * 2, + to_be_issued: vault_id.wrapped(0), + to_be_redeemed: consumed_issued_tokens, + backing_collateral: collateral_vault, + to_be_replaced: vault_id.wrapped(0), + replace_collateral: griefing(0), + ..default_vault_state(&vault_id) + }, + ); - // make sure user has plenty of kbtc - TokensPallet::set_balance(root(), account_of(USER), Token(KBTC), 10000000000, 10000000000).unwrap(); + // make sure user has plenty of kbtc + TokensPallet::set_balance(root(), account_of(USER), Token(KBTC), 10000000000, 10000000000).unwrap(); - liquidate_vault_with_status(&vault_id, liquidation_status); + liquidate_vault_with_status(&vault_id, VaultStatus::Liquidated); - let post_liquidation_state = ParachainState::get(&vault_id); + let post_liquidation_state = ParachainState::get(&vault_id); - assert_ok!(Call::Redeem(RedeemCall::liquidation_redeem { + assert_ok!(Call::Redeem(RedeemCall::liquidation_redeem { + currencies: vault_id.currencies.clone(), + amount_wrapped: consumed_issued_tokens.amount() + }) + .dispatch(origin_of(account_of(USER)))); + assert_noop!( + Call::Redeem(RedeemCall::liquidation_redeem { currencies: vault_id.currencies.clone(), - amount_wrapped: consumed_issued_tokens.amount() + amount_wrapped: 1 }) - .dispatch(origin_of(account_of(USER)))); - assert_noop!( - Call::Redeem(RedeemCall::liquidation_redeem { - currencies: vault_id.currencies.clone(), - amount_wrapped: 1 - }) - .dispatch(origin_of(account_of(USER))), - VaultRegistryError::InsufficientTokensCommitted - ); - - let pre_cancellation_state = ParachainState::get(&vault_id); - assert_eq!( - pre_cancellation_state, - post_liquidation_state.with_changes(|user, _vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - liquidation_vault.issued -= consumed_issued_tokens; - liquidation_vault.collateral -= collateral_vault / 2; + .dispatch(origin_of(account_of(USER))), + VaultRegistryError::InsufficientTokensCommitted + ); - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free -= consumed_issued_tokens; - (*user.balances.get_mut(&vault_id.collateral_currency()).unwrap()).free += collateral_vault / 2; - }) - ); + let pre_cancellation_state = ParachainState::get(&vault_id); + assert_eq!( + pre_cancellation_state, + post_liquidation_state.with_changes(|user, _vault, liquidation_vault, _fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + liquidation_vault.issued -= consumed_issued_tokens; + liquidation_vault.collateral -= collateral_vault / 2; - assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { - redeem_id: redeem_id, - reimburse: false + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free -= consumed_issued_tokens; + (*user.balances.get_mut(&vault_id.collateral_currency()).unwrap()).free += collateral_vault / 2; }) - .dispatch(origin_of(account_of(USER)))); + ); - let post_cancellation_state = ParachainState::get(&vault_id); - assert_eq!( - post_cancellation_state, - pre_cancellation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - liquidation_vault.to_be_redeemed -= consumed_issued_tokens; - liquidation_vault.collateral += collateral_vault / 2; + assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { + redeem_id: redeem_id, + reimburse: false + }) + .dispatch(origin_of(account_of(USER)))); - vault.to_be_redeemed -= consumed_issued_tokens; - vault.liquidated_collateral -= collateral_vault / 2; + let post_cancellation_state = ParachainState::get(&vault_id); + assert_eq!( + post_cancellation_state, + pre_cancellation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + liquidation_vault.to_be_redeemed -= consumed_issued_tokens; + liquidation_vault.collateral += collateral_vault / 2; - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free += issued_tokens; - }) - ); + vault.to_be_redeemed -= consumed_issued_tokens; + vault.liquidated_collateral -= collateral_vault / 2; - assert_ok!(Call::Redeem(RedeemCall::liquidation_redeem { - currencies: vault_id.currencies.clone(), - amount_wrapped: consumed_issued_tokens.amount() + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free += issued_tokens; }) - .dispatch(origin_of(account_of(USER)))); - - // expect same change as the previous liquidation_redeem - assert_eq!( - ParachainState::get(&vault_id), - post_cancellation_state.with_changes(|user, _vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - liquidation_vault.issued -= consumed_issued_tokens; - liquidation_vault.collateral -= collateral_vault / 2; + ); - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free -= consumed_issued_tokens; - (*user.balances.get_mut(&vault_id.collateral_currency()).unwrap()).free += collateral_vault / 2; - }) - ); + assert_ok!(Call::Redeem(RedeemCall::liquidation_redeem { + currencies: vault_id.currencies.clone(), + amount_wrapped: consumed_issued_tokens.amount() }) - } + .dispatch(origin_of(account_of(USER)))); + + // expect same change as the previous liquidation_redeem + assert_eq!( + ParachainState::get(&vault_id), + post_cancellation_state.with_changes(|user, _vault, liquidation_vault, _fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + liquidation_vault.issued -= consumed_issued_tokens; + liquidation_vault.collateral -= collateral_vault / 2; + + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free -= consumed_issued_tokens; + (*user.balances.get_mut(&vault_id.collateral_currency()).unwrap()).free += collateral_vault / 2; + }) + ); + }) } #[test] fn integration_test_redeem_wrapped_cancel_liquidated_no_reimburse() { - for liquidation_status in [VaultStatus::CommittedTheft, VaultStatus::Liquidated] { - test_with(|vault_id| { - let currency_id = vault_id.collateral_currency(); - let issued_tokens = vault_id.wrapped(10_000); - let collateral_vault = Amount::new(1_000_000, currency_id); - VaultRegistryPallet::collateral_integrity_check(); - let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); - VaultRegistryPallet::collateral_integrity_check(); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); + test_with(|vault_id| { + let currency_id = vault_id.collateral_currency(); + let issued_tokens = vault_id.wrapped(10_000); + let collateral_vault = Amount::new(1_000_000, currency_id); + VaultRegistryPallet::collateral_integrity_check(); + let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); + VaultRegistryPallet::collateral_integrity_check(); + let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - // setup vault state such that 1/4th of its collateral is freed after successful redeem - let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); - CoreVaultData::force_to( - &vault_id, - CoreVaultData { - issued: consumed_issued_tokens * 4, - to_be_issued: vault_id.wrapped(0), - to_be_redeemed: consumed_issued_tokens * 4, - backing_collateral: collateral_vault, - to_be_replaced: vault_id.wrapped(0), - replace_collateral: griefing(0), - ..default_vault_state(&vault_id) - }, - ); + // setup vault state such that 1/4th of its collateral is freed after successful redeem + let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); + CoreVaultData::force_to( + &vault_id, + CoreVaultData { + issued: consumed_issued_tokens * 4, + to_be_issued: vault_id.wrapped(0), + to_be_redeemed: consumed_issued_tokens * 4, + backing_collateral: collateral_vault, + to_be_replaced: vault_id.wrapped(0), + replace_collateral: griefing(0), + ..default_vault_state(&vault_id) + }, + ); - liquidate_vault_with_status(&vault_id, liquidation_status); + liquidate_vault_with_status(&vault_id, VaultStatus::Liquidated); - let post_liquidation_state = ParachainState::get(&vault_id); + let post_liquidation_state = ParachainState::get(&vault_id); - assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { - redeem_id: redeem_id, - reimburse: false - }) - .dispatch(origin_of(account_of(USER)))); + assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { + redeem_id: redeem_id, + reimburse: false + }) + .dispatch(origin_of(account_of(USER)))); - // NOTE: changes are relative the the post liquidation state - assert_eq!( - ParachainState::get(&vault_id), - post_liquidation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - - // to-be-redeemed decreased, forwarding to liquidation vault - vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - - // the collateral that remained with the vault to back this redeem is now transferred to the - // liquidation vault - let collateral_for_this_redeem = collateral_vault / 4; - vault.liquidated_collateral -= collateral_for_this_redeem; - liquidation_vault.collateral += collateral_for_this_redeem; - - // user's tokens get unlocked - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= - redeem.amount_btc() + redeem.fee() + redeem.transfer_fee_btc(); - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free += - redeem.amount_btc() + redeem.fee() + redeem.transfer_fee_btc(); - - // Note that no punishment is taken from vault, because it's already liquidated - }) - ); - }); - } + // NOTE: changes are relative the the post liquidation state + assert_eq!( + ParachainState::get(&vault_id), + post_liquidation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + + // to-be-redeemed decreased, forwarding to liquidation vault + vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + + // the collateral that remained with the vault to back this redeem is now transferred to the + // liquidation vault + let collateral_for_this_redeem = collateral_vault / 4; + vault.liquidated_collateral -= collateral_for_this_redeem; + liquidation_vault.collateral += collateral_for_this_redeem; + + // user's tokens get unlocked + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= + redeem.amount_btc() + redeem.fee() + redeem.transfer_fee_btc(); + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free += + redeem.amount_btc() + redeem.fee() + redeem.transfer_fee_btc(); + + // Note that no punishment is taken from vault, because it's already liquidated + }) + ); + }); } #[test] fn integration_test_redeem_wrapped_cancel_liquidated_reimburse() { - for liquidation_status in [VaultStatus::CommittedTheft, VaultStatus::Liquidated] { - test_with(|vault_id| { - let currency_id = vault_id.collateral_currency(); - let issued_tokens = vault_id.wrapped(10_000); - let collateral_vault = Amount::new(1_000_000, currency_id); - let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); + test_with(|vault_id| { + let currency_id = vault_id.collateral_currency(); + let issued_tokens = vault_id.wrapped(10_000); + let collateral_vault = Amount::new(1_000_000, currency_id); + let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); + let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - // setup vault state such that 1/4th of its collateral is freed after successful redeem - let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); - CoreVaultData::force_to( - &vault_id, - CoreVaultData { - issued: consumed_issued_tokens * 4, - to_be_issued: vault_id.wrapped(0), - to_be_redeemed: consumed_issued_tokens * 4, - backing_collateral: collateral_vault, - to_be_replaced: vault_id.wrapped(0), - replace_collateral: griefing(0), - ..default_vault_state(&vault_id) - }, - ); + // setup vault state such that 1/4th of its collateral is freed after successful redeem + let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); + CoreVaultData::force_to( + &vault_id, + CoreVaultData { + issued: consumed_issued_tokens * 4, + to_be_issued: vault_id.wrapped(0), + to_be_redeemed: consumed_issued_tokens * 4, + backing_collateral: collateral_vault, + to_be_replaced: vault_id.wrapped(0), + replace_collateral: griefing(0), + ..default_vault_state(&vault_id) + }, + ); - liquidate_vault_with_status(&vault_id, liquidation_status); + liquidate_vault_with_status(&vault_id, VaultStatus::Liquidated); - let post_liquidation_state = ParachainState::get(&vault_id); + let post_liquidation_state = ParachainState::get(&vault_id); - assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { - redeem_id: redeem_id, - reimburse: true - }) - .dispatch(origin_of(account_of(USER)))); + assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { + redeem_id: redeem_id, + reimburse: true + }) + .dispatch(origin_of(account_of(USER)))); - // NOTE: changes are relative the the post liquidation state - assert_eq!( - ParachainState::get(&vault_id), - post_liquidation_state.with_changes(|user, vault, liquidation_vault, fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + // NOTE: changes are relative the the post liquidation state + assert_eq!( + ParachainState::get(&vault_id), + post_liquidation_state.with_changes(|user, vault, liquidation_vault, fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - // to-be-redeemed decreased, forwarding to liquidation vault - vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + // to-be-redeemed decreased, forwarding to liquidation vault + vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - // tokens are given to the vault, minus a fee that is given to the fee pool - *vault.free_balance.get_mut(&vault_id.wrapped_currency()).unwrap() += - redeem.amount_btc() + redeem.transfer_fee_btc(); - *fee_pool.rewards_for(&vault_id) += redeem.fee(); + // tokens are given to the vault, minus a fee that is given to the fee pool + *vault.free_balance.get_mut(&vault_id.wrapped_currency()).unwrap() += + redeem.amount_btc() + redeem.transfer_fee_btc(); + *fee_pool.rewards_for(&vault_id) += redeem.fee(); - // the collateral that remained with the vault to back this redeem is transferred to the user - let collateral_for_this_redeem = collateral_vault / 4; - vault.liquidated_collateral -= collateral_for_this_redeem; - (*user.balances.get_mut(¤cy_id).unwrap()).free += collateral_for_this_redeem; + // the collateral that remained with the vault to back this redeem is transferred to the user + let collateral_for_this_redeem = collateral_vault / 4; + vault.liquidated_collateral -= collateral_for_this_redeem; + (*user.balances.get_mut(¤cy_id).unwrap()).free += collateral_for_this_redeem; - // user's tokens get burned - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; + // user's tokens get burned + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; - // Note that no punishment is taken from vault, because it's already liquidated - }) - ); - }); - } + // Note that no punishment is taken from vault, because it's already liquidated + }) + ); + }); } #[test] fn integration_test_redeem_wrapped_execute_liquidated() { - for liquidation_status in [VaultStatus::CommittedTheft, VaultStatus::Liquidated] { - test_with(|vault_id| { - let currency_id = vault_id.collateral_currency(); - let issued_tokens = vault_id.wrapped(10_000); - let collateral_vault = Amount::new(1_000_000, currency_id); + test_with(|vault_id| { + let currency_id = vault_id.collateral_currency(); + let issued_tokens = vault_id.wrapped(10_000); + let collateral_vault = Amount::new(1_000_000, currency_id); - let redeem_id = setup_redeem(issued_tokens, USER, &vault_id); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); + let redeem_id = setup_redeem(issued_tokens, USER, &vault_id); + let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - // setup vault state such that 1/4th of its collateral is freed after successful redeem - let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); - CoreVaultData::force_to( - &vault_id, - CoreVaultData { - issued: consumed_issued_tokens * 4, - to_be_issued: vault_id.wrapped(0), - to_be_redeemed: consumed_issued_tokens * 4, - backing_collateral: collateral_vault, - to_be_replaced: vault_id.wrapped(0), - replace_collateral: griefing(0), - ..default_vault_state(&vault_id) - }, - ); + // setup vault state such that 1/4th of its collateral is freed after successful redeem + let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); + CoreVaultData::force_to( + &vault_id, + CoreVaultData { + issued: consumed_issued_tokens * 4, + to_be_issued: vault_id.wrapped(0), + to_be_redeemed: consumed_issued_tokens * 4, + backing_collateral: collateral_vault, + to_be_replaced: vault_id.wrapped(0), + replace_collateral: griefing(0), + ..default_vault_state(&vault_id) + }, + ); - liquidate_vault_with_status(&vault_id, liquidation_status); + liquidate_vault_with_status(&vault_id, VaultStatus::Liquidated); - let post_liquidation_state = ParachainState::get(&vault_id); + let post_liquidation_state = ParachainState::get(&vault_id); - execute_redeem(redeem_id); + execute_redeem(redeem_id); - // NOTE: changes are relative the the post liquidation state - assert_eq!( - ParachainState::get(&vault_id), - post_liquidation_state.with_changes(|user, vault, liquidation_vault, fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + // NOTE: changes are relative the the post liquidation state + assert_eq!( + ParachainState::get(&vault_id), + post_liquidation_state.with_changes(|user, vault, liquidation_vault, fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - // fee given to fee pool - *fee_pool.rewards_for(&vault_id) += redeem.fee(); + // fee given to fee pool + *fee_pool.rewards_for(&vault_id) += redeem.fee(); - // wrapped burned from user - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; + // wrapped burned from user + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; - // to-be-redeemed & issued decreased, forwarding to liquidation vault - vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - liquidation_vault.issued -= redeem.amount_btc() + redeem.transfer_fee_btc(); + // to-be-redeemed & issued decreased, forwarding to liquidation vault + vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + liquidation_vault.issued -= redeem.amount_btc() + redeem.transfer_fee_btc(); - // collateral released - let released_collateral = vault.liquidated_collateral / 4; - vault.liquidated_collateral -= released_collateral; - *vault.free_balance.get_mut(¤cy_id).unwrap() += released_collateral; - }) - ); - }) - } + // collateral released + let released_collateral = vault.liquidated_collateral / 4; + vault.liquidated_collateral -= released_collateral; + *vault.free_balance.get_mut(¤cy_id).unwrap() += released_collateral; + }) + ); + }) } fn get_additional_collateral(vault_id: &VaultId) { From 0c1591158e14705ab96f4f6bcf5c13edf3a69b5d Mon Sep 17 00:00:00 2001 From: Gregory Hill Date: Fri, 22 Jul 2022 08:54:01 +0100 Subject: [PATCH 3/3] Revert "refactor!: remove VaultStatus::CommittedTheft and add migration" This reverts commit 78bdebbdc2865a718b2d8ca42c2c5a8b5f65afff. Signed-off-by: Gregory Hill --- crates/vault-registry/src/lib.rs | 3 + crates/vault-registry/src/types.rs | 36 +- standalone/runtime/tests/test_redeem.rs | 466 ++++++++++++------------ 3 files changed, 249 insertions(+), 256 deletions(-) diff --git a/crates/vault-registry/src/lib.rs b/crates/vault-registry/src/lib.rs index 8ab62c812d..05659428b9 100644 --- a/crates/vault-registry/src/lib.rs +++ b/crates/vault-registry/src/lib.rs @@ -601,6 +601,8 @@ pub mod pallet { MaxNominationRatioViolation, /// The collateral ceiling would be exceeded for the vault's currency. CurrencyCeilingExceeded, + /// Vault is no longer usable as it was liquidated due to theft. + VaultCommittedTheft, /// Vault is no longer usable as it was liquidated due to undercollateralization. VaultLiquidated, /// Vault must be either liquidated or flagged for theft. @@ -844,6 +846,7 @@ impl Pallet { match vault.status { VaultStatus::Active(_) => Ok(vault), VaultStatus::Liquidated => Err(Error::::VaultLiquidated.into()), + VaultStatus::CommittedTheft => Err(Error::::VaultCommittedTheft.into()), } } diff --git a/crates/vault-registry/src/types.rs b/crates/vault-registry/src/types.rs index 1f96a3e51a..bbbeb59eb7 100644 --- a/crates/vault-registry/src/types.rs +++ b/crates/vault-registry/src/types.rs @@ -190,28 +190,6 @@ pub mod liquidation_vault_fix { pub mod v4 { use super::*; - #[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, Debug, TypeInfo, MaxEncodedLen)] - pub enum VaultStatusV4 { - /// Vault is active - bool=true indicates that the vault accepts new issue requests - Active(bool), - - /// Vault has been liquidated - Liquidated, - - /// Vault theft has been reported - CommittedTheft, - } - - impl Into for VaultStatusV4 { - fn into(self) -> VaultStatus { - match self { - VaultStatusV4::Active(accept_issue) => VaultStatus::Active(accept_issue), - VaultStatusV4::Liquidated => VaultStatus::Liquidated, - VaultStatusV4::CommittedTheft => VaultStatus::Liquidated, - } - } - } - #[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] #[cfg_attr(feature = "std", derive(Debug))] pub struct VaultV4 { @@ -220,7 +198,7 @@ pub mod v4 { /// Bitcoin address of this Vault (P2PKH, P2SH, P2WPKH, P2WSH) pub wallet: Wallet, /// Current status of the vault - pub status: VaultStatusV4, + pub status: VaultStatus, /// Block height until which this Vault is banned from being used for /// Issue, Redeem (except during automatic liquidation) and Replace. pub banned_until: Option, @@ -268,7 +246,7 @@ pub mod v4 { Some(Vault { id: vault_v4.id, wallet: vault_v4.wallet, - status: vault_v4.status.into(), + status: vault_v4.status, banned_until: vault_v4.banned_until, secure_collateral_threshold: None, to_be_issued_tokens: vault_v4.to_be_issued_tokens, @@ -315,7 +293,7 @@ pub mod v4 { .into(), }, banned_until: None, - status: VaultStatusV4::Active(true), + status: VaultStatus::Active(true), issued_tokens: Default::default(), liquidated_collateral: Default::default(), replace_collateral: Default::default(), @@ -338,7 +316,7 @@ pub mod v4 { wallet: Wallet { addresses: vault.wallet.addresses.clone(), }, - status: vault.status.into(), + status: vault.status.clone(), banned_until: vault.banned_until, secure_collateral_threshold: None, to_be_issued_tokens: vault.to_be_issued_tokens, @@ -392,6 +370,10 @@ pub enum VaultStatus { /// Vault has been liquidated Liquidated, + + /// Vault theft has been reported + // TODO: remove this, requires migration + CommittedTheft, } impl Default for VaultStatus { @@ -478,7 +460,7 @@ impl< } pub fn is_liquidated(&self) -> bool { - matches!(self.status, VaultStatus::Liquidated) + matches!(self.status, VaultStatus::Liquidated | VaultStatus::CommittedTheft) } } diff --git a/standalone/runtime/tests/test_redeem.rs b/standalone/runtime/tests/test_redeem.rs index 851e4265a7..83f6f8a914 100644 --- a/standalone/runtime/tests/test_redeem.rs +++ b/standalone/runtime/tests/test_redeem.rs @@ -1726,289 +1726,297 @@ fn integration_test_redeem_wrapped_cancel_no_reimburse() { #[test] fn integration_test_liquidation_redeem_with_cancel_redeem() { - test_with(|vault_id| { - let currency_id = vault_id.collateral_currency(); - let issued_tokens = vault_id.wrapped(10_000); - let collateral_vault = Amount::new(1_000_000, currency_id); - VaultRegistryPallet::collateral_integrity_check(); - let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); - VaultRegistryPallet::collateral_integrity_check(); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); + for liquidation_status in [VaultStatus::CommittedTheft, VaultStatus::Liquidated] { + test_with(|vault_id| { + let currency_id = vault_id.collateral_currency(); + let issued_tokens = vault_id.wrapped(10_000); + let collateral_vault = Amount::new(1_000_000, currency_id); + VaultRegistryPallet::collateral_integrity_check(); + let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); + VaultRegistryPallet::collateral_integrity_check(); + let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - // setup vault state such that 1/4th of its collateral is freed after successful redeem - let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); - CoreVaultData::force_to( - &vault_id, - CoreVaultData { - issued: consumed_issued_tokens * 2, - to_be_issued: vault_id.wrapped(0), - to_be_redeemed: consumed_issued_tokens, - backing_collateral: collateral_vault, - to_be_replaced: vault_id.wrapped(0), - replace_collateral: griefing(0), - ..default_vault_state(&vault_id) - }, - ); + // setup vault state such that 1/4th of its collateral is freed after successful redeem + let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); + CoreVaultData::force_to( + &vault_id, + CoreVaultData { + issued: consumed_issued_tokens * 2, + to_be_issued: vault_id.wrapped(0), + to_be_redeemed: consumed_issued_tokens, + backing_collateral: collateral_vault, + to_be_replaced: vault_id.wrapped(0), + replace_collateral: griefing(0), + ..default_vault_state(&vault_id) + }, + ); - // make sure user has plenty of kbtc - TokensPallet::set_balance(root(), account_of(USER), Token(KBTC), 10000000000, 10000000000).unwrap(); + // make sure user has plenty of kbtc + TokensPallet::set_balance(root(), account_of(USER), Token(KBTC), 10000000000, 10000000000).unwrap(); - liquidate_vault_with_status(&vault_id, VaultStatus::Liquidated); + liquidate_vault_with_status(&vault_id, liquidation_status); - let post_liquidation_state = ParachainState::get(&vault_id); + let post_liquidation_state = ParachainState::get(&vault_id); - assert_ok!(Call::Redeem(RedeemCall::liquidation_redeem { - currencies: vault_id.currencies.clone(), - amount_wrapped: consumed_issued_tokens.amount() - }) - .dispatch(origin_of(account_of(USER)))); - assert_noop!( - Call::Redeem(RedeemCall::liquidation_redeem { + assert_ok!(Call::Redeem(RedeemCall::liquidation_redeem { currencies: vault_id.currencies.clone(), - amount_wrapped: 1 + amount_wrapped: consumed_issued_tokens.amount() }) - .dispatch(origin_of(account_of(USER))), - VaultRegistryError::InsufficientTokensCommitted - ); + .dispatch(origin_of(account_of(USER)))); + assert_noop!( + Call::Redeem(RedeemCall::liquidation_redeem { + currencies: vault_id.currencies.clone(), + amount_wrapped: 1 + }) + .dispatch(origin_of(account_of(USER))), + VaultRegistryError::InsufficientTokensCommitted + ); - let pre_cancellation_state = ParachainState::get(&vault_id); - assert_eq!( - pre_cancellation_state, - post_liquidation_state.with_changes(|user, _vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - liquidation_vault.issued -= consumed_issued_tokens; - liquidation_vault.collateral -= collateral_vault / 2; + let pre_cancellation_state = ParachainState::get(&vault_id); + assert_eq!( + pre_cancellation_state, + post_liquidation_state.with_changes(|user, _vault, liquidation_vault, _fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + liquidation_vault.issued -= consumed_issued_tokens; + liquidation_vault.collateral -= collateral_vault / 2; - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free -= consumed_issued_tokens; - (*user.balances.get_mut(&vault_id.collateral_currency()).unwrap()).free += collateral_vault / 2; + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free -= consumed_issued_tokens; + (*user.balances.get_mut(&vault_id.collateral_currency()).unwrap()).free += collateral_vault / 2; + }) + ); + + assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { + redeem_id: redeem_id, + reimburse: false }) - ); + .dispatch(origin_of(account_of(USER)))); - assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { - redeem_id: redeem_id, - reimburse: false - }) - .dispatch(origin_of(account_of(USER)))); + let post_cancellation_state = ParachainState::get(&vault_id); + assert_eq!( + post_cancellation_state, + pre_cancellation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + liquidation_vault.to_be_redeemed -= consumed_issued_tokens; + liquidation_vault.collateral += collateral_vault / 2; - let post_cancellation_state = ParachainState::get(&vault_id); - assert_eq!( - post_cancellation_state, - pre_cancellation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - liquidation_vault.to_be_redeemed -= consumed_issued_tokens; - liquidation_vault.collateral += collateral_vault / 2; + vault.to_be_redeemed -= consumed_issued_tokens; + vault.liquidated_collateral -= collateral_vault / 2; - vault.to_be_redeemed -= consumed_issued_tokens; - vault.liquidated_collateral -= collateral_vault / 2; + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free += issued_tokens; + }) + ); - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free += issued_tokens; + assert_ok!(Call::Redeem(RedeemCall::liquidation_redeem { + currencies: vault_id.currencies.clone(), + amount_wrapped: consumed_issued_tokens.amount() }) - ); - - assert_ok!(Call::Redeem(RedeemCall::liquidation_redeem { - currencies: vault_id.currencies.clone(), - amount_wrapped: consumed_issued_tokens.amount() - }) - .dispatch(origin_of(account_of(USER)))); + .dispatch(origin_of(account_of(USER)))); - // expect same change as the previous liquidation_redeem - assert_eq!( - ParachainState::get(&vault_id), - post_cancellation_state.with_changes(|user, _vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - liquidation_vault.issued -= consumed_issued_tokens; - liquidation_vault.collateral -= collateral_vault / 2; + // expect same change as the previous liquidation_redeem + assert_eq!( + ParachainState::get(&vault_id), + post_cancellation_state.with_changes(|user, _vault, liquidation_vault, _fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + liquidation_vault.issued -= consumed_issued_tokens; + liquidation_vault.collateral -= collateral_vault / 2; - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free -= consumed_issued_tokens; - (*user.balances.get_mut(&vault_id.collateral_currency()).unwrap()).free += collateral_vault / 2; - }) - ); - }) + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free -= consumed_issued_tokens; + (*user.balances.get_mut(&vault_id.collateral_currency()).unwrap()).free += collateral_vault / 2; + }) + ); + }) + } } #[test] fn integration_test_redeem_wrapped_cancel_liquidated_no_reimburse() { - test_with(|vault_id| { - let currency_id = vault_id.collateral_currency(); - let issued_tokens = vault_id.wrapped(10_000); - let collateral_vault = Amount::new(1_000_000, currency_id); - VaultRegistryPallet::collateral_integrity_check(); - let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); - VaultRegistryPallet::collateral_integrity_check(); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - - // setup vault state such that 1/4th of its collateral is freed after successful redeem - let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); - CoreVaultData::force_to( - &vault_id, - CoreVaultData { - issued: consumed_issued_tokens * 4, - to_be_issued: vault_id.wrapped(0), - to_be_redeemed: consumed_issued_tokens * 4, - backing_collateral: collateral_vault, - to_be_replaced: vault_id.wrapped(0), - replace_collateral: griefing(0), - ..default_vault_state(&vault_id) - }, - ); - - liquidate_vault_with_status(&vault_id, VaultStatus::Liquidated); - - let post_liquidation_state = ParachainState::get(&vault_id); - - assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { - redeem_id: redeem_id, - reimburse: false - }) - .dispatch(origin_of(account_of(USER)))); - - // NOTE: changes are relative the the post liquidation state - assert_eq!( - ParachainState::get(&vault_id), - post_liquidation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + for liquidation_status in [VaultStatus::CommittedTheft, VaultStatus::Liquidated] { + test_with(|vault_id| { + let currency_id = vault_id.collateral_currency(); + let issued_tokens = vault_id.wrapped(10_000); + let collateral_vault = Amount::new(1_000_000, currency_id); + VaultRegistryPallet::collateral_integrity_check(); + let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); + VaultRegistryPallet::collateral_integrity_check(); + let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - // to-be-redeemed decreased, forwarding to liquidation vault - vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + // setup vault state such that 1/4th of its collateral is freed after successful redeem + let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); + CoreVaultData::force_to( + &vault_id, + CoreVaultData { + issued: consumed_issued_tokens * 4, + to_be_issued: vault_id.wrapped(0), + to_be_redeemed: consumed_issued_tokens * 4, + backing_collateral: collateral_vault, + to_be_replaced: vault_id.wrapped(0), + replace_collateral: griefing(0), + ..default_vault_state(&vault_id) + }, + ); - // the collateral that remained with the vault to back this redeem is now transferred to the - // liquidation vault - let collateral_for_this_redeem = collateral_vault / 4; - vault.liquidated_collateral -= collateral_for_this_redeem; - liquidation_vault.collateral += collateral_for_this_redeem; + liquidate_vault_with_status(&vault_id, liquidation_status); - // user's tokens get unlocked - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= - redeem.amount_btc() + redeem.fee() + redeem.transfer_fee_btc(); - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free += - redeem.amount_btc() + redeem.fee() + redeem.transfer_fee_btc(); + let post_liquidation_state = ParachainState::get(&vault_id); - // Note that no punishment is taken from vault, because it's already liquidated + assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { + redeem_id: redeem_id, + reimburse: false }) - ); - }); + .dispatch(origin_of(account_of(USER)))); + + // NOTE: changes are relative the the post liquidation state + assert_eq!( + ParachainState::get(&vault_id), + post_liquidation_state.with_changes(|user, vault, liquidation_vault, _fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + + // to-be-redeemed decreased, forwarding to liquidation vault + vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + + // the collateral that remained with the vault to back this redeem is now transferred to the + // liquidation vault + let collateral_for_this_redeem = collateral_vault / 4; + vault.liquidated_collateral -= collateral_for_this_redeem; + liquidation_vault.collateral += collateral_for_this_redeem; + + // user's tokens get unlocked + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= + redeem.amount_btc() + redeem.fee() + redeem.transfer_fee_btc(); + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).free += + redeem.amount_btc() + redeem.fee() + redeem.transfer_fee_btc(); + + // Note that no punishment is taken from vault, because it's already liquidated + }) + ); + }); + } } #[test] fn integration_test_redeem_wrapped_cancel_liquidated_reimburse() { - test_with(|vault_id| { - let currency_id = vault_id.collateral_currency(); - let issued_tokens = vault_id.wrapped(10_000); - let collateral_vault = Amount::new(1_000_000, currency_id); - let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); + for liquidation_status in [VaultStatus::CommittedTheft, VaultStatus::Liquidated] { + test_with(|vault_id| { + let currency_id = vault_id.collateral_currency(); + let issued_tokens = vault_id.wrapped(10_000); + let collateral_vault = Amount::new(1_000_000, currency_id); + let redeem_id = setup_cancelable_redeem(USER, &vault_id, issued_tokens); + let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - // setup vault state such that 1/4th of its collateral is freed after successful redeem - let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); - CoreVaultData::force_to( - &vault_id, - CoreVaultData { - issued: consumed_issued_tokens * 4, - to_be_issued: vault_id.wrapped(0), - to_be_redeemed: consumed_issued_tokens * 4, - backing_collateral: collateral_vault, - to_be_replaced: vault_id.wrapped(0), - replace_collateral: griefing(0), - ..default_vault_state(&vault_id) - }, - ); + // setup vault state such that 1/4th of its collateral is freed after successful redeem + let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); + CoreVaultData::force_to( + &vault_id, + CoreVaultData { + issued: consumed_issued_tokens * 4, + to_be_issued: vault_id.wrapped(0), + to_be_redeemed: consumed_issued_tokens * 4, + backing_collateral: collateral_vault, + to_be_replaced: vault_id.wrapped(0), + replace_collateral: griefing(0), + ..default_vault_state(&vault_id) + }, + ); - liquidate_vault_with_status(&vault_id, VaultStatus::Liquidated); + liquidate_vault_with_status(&vault_id, liquidation_status); - let post_liquidation_state = ParachainState::get(&vault_id); + let post_liquidation_state = ParachainState::get(&vault_id); - assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { - redeem_id: redeem_id, - reimburse: true - }) - .dispatch(origin_of(account_of(USER)))); + assert_ok!(Call::Redeem(RedeemCall::cancel_redeem { + redeem_id: redeem_id, + reimburse: true + }) + .dispatch(origin_of(account_of(USER)))); - // NOTE: changes are relative the the post liquidation state - assert_eq!( - ParachainState::get(&vault_id), - post_liquidation_state.with_changes(|user, vault, liquidation_vault, fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + // NOTE: changes are relative the the post liquidation state + assert_eq!( + ParachainState::get(&vault_id), + post_liquidation_state.with_changes(|user, vault, liquidation_vault, fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - // to-be-redeemed decreased, forwarding to liquidation vault - vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + // to-be-redeemed decreased, forwarding to liquidation vault + vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - // tokens are given to the vault, minus a fee that is given to the fee pool - *vault.free_balance.get_mut(&vault_id.wrapped_currency()).unwrap() += - redeem.amount_btc() + redeem.transfer_fee_btc(); - *fee_pool.rewards_for(&vault_id) += redeem.fee(); + // tokens are given to the vault, minus a fee that is given to the fee pool + *vault.free_balance.get_mut(&vault_id.wrapped_currency()).unwrap() += + redeem.amount_btc() + redeem.transfer_fee_btc(); + *fee_pool.rewards_for(&vault_id) += redeem.fee(); - // the collateral that remained with the vault to back this redeem is transferred to the user - let collateral_for_this_redeem = collateral_vault / 4; - vault.liquidated_collateral -= collateral_for_this_redeem; - (*user.balances.get_mut(¤cy_id).unwrap()).free += collateral_for_this_redeem; + // the collateral that remained with the vault to back this redeem is transferred to the user + let collateral_for_this_redeem = collateral_vault / 4; + vault.liquidated_collateral -= collateral_for_this_redeem; + (*user.balances.get_mut(¤cy_id).unwrap()).free += collateral_for_this_redeem; - // user's tokens get burned - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; + // user's tokens get burned + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; - // Note that no punishment is taken from vault, because it's already liquidated - }) - ); - }); + // Note that no punishment is taken from vault, because it's already liquidated + }) + ); + }); + } } #[test] fn integration_test_redeem_wrapped_execute_liquidated() { - test_with(|vault_id| { - let currency_id = vault_id.collateral_currency(); - let issued_tokens = vault_id.wrapped(10_000); - let collateral_vault = Amount::new(1_000_000, currency_id); + for liquidation_status in [VaultStatus::CommittedTheft, VaultStatus::Liquidated] { + test_with(|vault_id| { + let currency_id = vault_id.collateral_currency(); + let issued_tokens = vault_id.wrapped(10_000); + let collateral_vault = Amount::new(1_000_000, currency_id); - let redeem_id = setup_redeem(issued_tokens, USER, &vault_id); - let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); + let redeem_id = setup_redeem(issued_tokens, USER, &vault_id); + let redeem = RedeemPallet::get_open_redeem_request_from_id(&redeem_id).unwrap(); - // setup vault state such that 1/4th of its collateral is freed after successful redeem - let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); - CoreVaultData::force_to( - &vault_id, - CoreVaultData { - issued: consumed_issued_tokens * 4, - to_be_issued: vault_id.wrapped(0), - to_be_redeemed: consumed_issued_tokens * 4, - backing_collateral: collateral_vault, - to_be_replaced: vault_id.wrapped(0), - replace_collateral: griefing(0), - ..default_vault_state(&vault_id) - }, - ); + // setup vault state such that 1/4th of its collateral is freed after successful redeem + let consumed_issued_tokens = redeem.amount_btc() + redeem.transfer_fee_btc(); + CoreVaultData::force_to( + &vault_id, + CoreVaultData { + issued: consumed_issued_tokens * 4, + to_be_issued: vault_id.wrapped(0), + to_be_redeemed: consumed_issued_tokens * 4, + backing_collateral: collateral_vault, + to_be_replaced: vault_id.wrapped(0), + replace_collateral: griefing(0), + ..default_vault_state(&vault_id) + }, + ); - liquidate_vault_with_status(&vault_id, VaultStatus::Liquidated); + liquidate_vault_with_status(&vault_id, liquidation_status); - let post_liquidation_state = ParachainState::get(&vault_id); + let post_liquidation_state = ParachainState::get(&vault_id); - execute_redeem(redeem_id); + execute_redeem(redeem_id); - // NOTE: changes are relative the the post liquidation state - assert_eq!( - ParachainState::get(&vault_id), - post_liquidation_state.with_changes(|user, vault, liquidation_vault, fee_pool| { - let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); + // NOTE: changes are relative the the post liquidation state + assert_eq!( + ParachainState::get(&vault_id), + post_liquidation_state.with_changes(|user, vault, liquidation_vault, fee_pool| { + let liquidation_vault = liquidation_vault.with_currency(&vault_id.currencies); - // fee given to fee pool - *fee_pool.rewards_for(&vault_id) += redeem.fee(); + // fee given to fee pool + *fee_pool.rewards_for(&vault_id) += redeem.fee(); - // wrapped burned from user - (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; + // wrapped burned from user + (*user.balances.get_mut(&vault_id.wrapped_currency()).unwrap()).locked -= issued_tokens; - // to-be-redeemed & issued decreased, forwarding to liquidation vault - vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); - liquidation_vault.issued -= redeem.amount_btc() + redeem.transfer_fee_btc(); + // to-be-redeemed & issued decreased, forwarding to liquidation vault + vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + liquidation_vault.to_be_redeemed -= redeem.amount_btc() + redeem.transfer_fee_btc(); + liquidation_vault.issued -= redeem.amount_btc() + redeem.transfer_fee_btc(); - // collateral released - let released_collateral = vault.liquidated_collateral / 4; - vault.liquidated_collateral -= released_collateral; - *vault.free_balance.get_mut(¤cy_id).unwrap() += released_collateral; - }) - ); - }) + // collateral released + let released_collateral = vault.liquidated_collateral / 4; + vault.liquidated_collateral -= released_collateral; + *vault.free_balance.get_mut(¤cy_id).unwrap() += released_collateral; + }) + ); + }) + } } fn get_additional_collateral(vault_id: &VaultId) {