From b0292653caed2d98472950757dc01f269813bc97 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 10:51:23 +0200 Subject: [PATCH 01/19] Init atomic swap pallet --- Cargo.lock | 15 ++++ Cargo.toml | 1 + frame/atomic-swap/Cargo.toml | 39 ++++++++++ frame/atomic-swap/src/lib.rs | 127 +++++++++++++++++++++++++++++++++ frame/atomic-swap/src/tests.rs | 90 +++++++++++++++++++++++ 5 files changed, 272 insertions(+) create mode 100644 frame/atomic-swap/Cargo.toml create mode 100644 frame/atomic-swap/src/lib.rs create mode 100644 frame/atomic-swap/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 83c98c65c6cb0..b5f274ae3ee07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3807,6 +3807,21 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-atomic-swap" +version = "2.0.0-rc3" +dependencies = [ + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-aura" version = "2.0.0-rc3" diff --git a/Cargo.toml b/Cargo.toml index d3004fcadca5a..d1c7339b993fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ members = [ "utils/wasm-builder-runner", "frame/assets", "frame/aura", + "frame/atomic-swap", "frame/authority-discovery", "frame/authorship", "frame/babe", diff --git a/frame/atomic-swap/Cargo.toml b/frame/atomic-swap/Cargo.toml new file mode 100644 index 0000000000000..be197096e7727 --- /dev/null +++ b/frame/atomic-swap/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "pallet-atomic-swap" +version = "2.0.0-rc3" +authors = ["Parity Technologies "] +edition = "2018" +license = "Apache-2.0" +homepage = "https://substrate.dev" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME atomic swap pallet" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false } +frame-support = { version = "2.0.0-rc3", default-features = false, path = "../support" } +frame-system = { version = "2.0.0-rc3", default-features = false, path = "../system" } +sp-runtime = { version = "2.0.0-rc3", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "2.0.0-rc3", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0-rc3", default-features = false, path = "../../primitives/io" } +sp-core = { version = "2.0.0-rc3", default-features = false, path = "../../primitives/core" } + +[dev-dependencies] +pallet-balances = { version = "2.0.0-rc3", default-features = false, path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-std/std", + "sp-io/std", + "sp-core/std", + "pallet-balances/std", +] diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs new file mode 100644 index 0000000000000..8207af58253c0 --- /dev/null +++ b/frame/atomic-swap/src/lib.rs @@ -0,0 +1,127 @@ +// This file is part of Substrate. + +// Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! # Atomic swap support pallet + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +mod tests; + +use sp_std::prelude::*; +use sp_core::H256; +use frame_support::{ + dispatch::DispatchResult, decl_module, decl_storage, decl_event, + traits::{Currency, ReservableCurrency}, +}; +use frame_system::{self as system, ensure_signed}; +use codec::{Encode, Decode}; +use sp_runtime::RuntimeDebug; + +/// Pending atomic swap operation. +#[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode)] +pub struct PendingSwap { + /// Source of the swap. + pub source: AccountId, + /// Balance value of the swap. + pub balance: Balance, + /// End block of the lock. + pub end_block: BlockNumber, +} + +/// Balance type from the pallet's point of view. +pub type BalanceFor = <::Currency as Currency<::AccountId>>::Balance; + +/// AccountId type from the pallet's point of view. +pub type AccountIdFor = ::AccountId; + +/// BlockNumber type from the pallet's point of view. +pub type BlockNumberFor = ::BlockNumber; + +/// PendingSwap type from the pallet's point of view. +pub type PendingSwapFor = PendingSwap, BalanceFor, BlockNumberFor>; + +/// Atomic swap's pallet configuration trait. +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + /// The currency mechanism. + type Currency: ReservableCurrency; +} + +decl_storage! { + trait Store for Module as Example { + pub PendingSwaps: double_map + hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) H256 + => Option>; + } +} + +decl_event!( + /// Event of atomic swap pallet. + pub enum Event where + Balance = BalanceFor, + AccountId = AccountIdFor, + PendingSwap = PendingSwapFor, + { + /// Swap created. + NewSwap(AccountId, H256, PendingSwap), + /// Swap claimed. + SwapClaimed(AccountId, H256, Balance), + /// Swap cancelled. + SwapCancelled(AccountId, H256, Balance), + } +); + +decl_module! { + /// Module definition of atomic swap pallet. + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + #[weight = 0] + fn create_swap( + origin, + _target: AccountIdFor, + _hashed_proof: H256, + _balance: BalanceFor, + _duration: BlockNumberFor, + ) -> DispatchResult { + ensure_signed(origin)?; + unimplemented!() + } + + #[weight = 0] + fn claim_swap( + origin, + _hashed_proof: H256, + _proof: Vec, + ) -> DispatchResult { + ensure_signed(origin)?; + unimplemented!() + } + + #[weight = 0] + fn cancel_swap( + origin, + _target: AccountIdFor, + _hashed_proof: H256, + ) -> DispatchResult { + ensure_signed(origin)?; + unimplemented!() + } + } +} diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs new file mode 100644 index 0000000000000..1d929c73e5a60 --- /dev/null +++ b/frame/atomic-swap/src/tests.rs @@ -0,0 +1,90 @@ +#![cfg(test)] + +use super::*; + +use frame_support::{ + assert_ok, impl_outer_origin, parameter_types, weights::{Weight, DispatchInfo, GetDispatchInfo}, + traits::{OnInitialize, OnFinalize} +}; +use sp_core::H256; +// The testing primitives are very useful for avoiding having to work with signatures +// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. +use sp_runtime::{ + Perbill, + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} +} + +// For testing the pallet, we construct most of a mock runtime. This means +// first constructing a configuration type (`Test`) which `impl`s each of the +// configuration traits of pallets we want to use. +#[derive(Clone, Eq, PartialEq)] +pub struct Test; +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); +} +impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type DbWeight = (); + type BlockExecutionWeight = (); + type ExtrinsicBaseWeight = (); + type MaximumExtrinsicWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + type ModuleToIndex = (); + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); +} +parameter_types! { + pub const ExistentialDeposit: u64 = 1; +} +impl pallet_balances::Trait for Test { + type Balance = u64; + type DustRemoval = (); + type Event = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; +} +impl Trait for Test { + type Event = (); + type Currency = Balances; +} +type System = frame_system::Module; +type Balances = pallet_balances::Module; +type Example = Module; + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + pallet_balances::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); + t.into() +} + +#[test] +fn two_party_swap() { + new_test_ext().execute_with(|| { + unimplemented!() + }); +} From eb0fbeff39ca2ba3a92e3c87d28dd68d4a96a257 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 11:25:57 +0200 Subject: [PATCH 02/19] Implement module swap operations --- frame/atomic-swap/src/lib.rs | 97 +++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 23 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 8207af58253c0..2cfac6c52026d 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -23,10 +23,10 @@ mod tests; use sp_std::prelude::*; -use sp_core::H256; +use sp_io::hashing::blake2_256; use frame_support::{ - dispatch::DispatchResult, decl_module, decl_storage, decl_event, - traits::{Currency, ReservableCurrency}, + dispatch::DispatchResult, decl_module, decl_storage, decl_event, decl_error, ensure, + traits::{Currency, ReservableCurrency, BalanceStatus}, }; use frame_system::{self as system, ensure_signed}; use codec::{Encode, Decode}; @@ -55,6 +55,9 @@ pub type BlockNumberFor = ::BlockNumber; /// PendingSwap type from the pallet's point of view. pub type PendingSwapFor = PendingSwap, BalanceFor, BlockNumberFor>; +/// Hashed proof type. +pub type HashedProof = [u8; 32]; + /// Atomic swap's pallet configuration trait. pub trait Trait: frame_system::Trait { /// The overarching event type. @@ -66,11 +69,24 @@ pub trait Trait: frame_system::Trait { decl_storage! { trait Store for Module as Example { pub PendingSwaps: double_map - hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) H256 + hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) HashedProof => Option>; } } +decl_error! { + pub enum Error for Module { + /// Swap already exists. + AlreadyExist, + /// Swap proof is invalid. + InvalidProof, + /// Swap does not exist. + NotExist, + /// Duration has not yet passed for the swap to be cancelled. + DurationNotPassed, + } +} + decl_event!( /// Event of atomic swap pallet. pub enum Event where @@ -79,49 +95,84 @@ decl_event!( PendingSwap = PendingSwapFor, { /// Swap created. - NewSwap(AccountId, H256, PendingSwap), + NewSwap(AccountId, HashedProof, PendingSwap), /// Swap claimed. - SwapClaimed(AccountId, H256, Balance), + SwapClaimed(AccountId, HashedProof, Balance), /// Swap cancelled. - SwapCancelled(AccountId, H256, Balance), + SwapCancelled(AccountId, HashedProof, Balance), } ); decl_module! { /// Module definition of atomic swap pallet. pub struct Module for enum Call where origin: T::Origin { + type Error = Error; + fn deposit_event() = default; #[weight = 0] fn create_swap( origin, - _target: AccountIdFor, - _hashed_proof: H256, - _balance: BalanceFor, - _duration: BlockNumberFor, - ) -> DispatchResult { - ensure_signed(origin)?; - unimplemented!() + target: AccountIdFor, + hashed_proof: HashedProof, + balance: BalanceFor, + duration: BlockNumberFor, + ) { + let source = ensure_signed(origin)?; + ensure!( + PendingSwaps::::get(&target, hashed_proof).is_none(), + Error::::AlreadyExist + ); + + T::Currency::reserve(&source, balance)?; + + let swap = PendingSwap { + source, + balance, + end_block: frame_system::Module::::block_number() + duration, + }; + PendingSwaps::::insert(target, hashed_proof, swap); } #[weight = 0] fn claim_swap( origin, - _hashed_proof: H256, - _proof: Vec, - ) -> DispatchResult { - ensure_signed(origin)?; - unimplemented!() + proof: Vec, + ) { + let target = ensure_signed(origin)?; + let hashed_proof = blake2_256(&proof); + + let swap = PendingSwaps::::get(&target, hashed_proof) + .ok_or(Error::::InvalidProof)?; + T::Currency::repatriate_reserved( + &swap.source, + &target, + swap.balance, + BalanceStatus::Free, + )?; + PendingSwaps::::remove(target, hashed_proof); } #[weight = 0] fn cancel_swap( origin, - _target: AccountIdFor, - _hashed_proof: H256, - ) -> DispatchResult { + target: AccountIdFor, + hashed_proof: HashedProof, + ) { ensure_signed(origin)?; - unimplemented!() + + let swap = PendingSwaps::::get(&target, hashed_proof) + .ok_or(Error::::NotExist)?; + ensure!( + frame_system::Module::::block_number() >= swap.end_block, + Error::::DurationNotPassed, + ); + + T::Currency::unreserve( + &swap.source, + swap.balance, + ); + PendingSwaps::::remove(&target, hashed_proof); } } } From b08c1eaec35c85504c68e3d74d81775725fde58b Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 13:39:26 +0200 Subject: [PATCH 03/19] Add successful swap test --- frame/atomic-swap/src/lib.rs | 2 +- frame/atomic-swap/src/tests.rs | 79 +++++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 2cfac6c52026d..223af5a5720cb 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -25,7 +25,7 @@ mod tests; use sp_std::prelude::*; use sp_io::hashing::blake2_256; use frame_support::{ - dispatch::DispatchResult, decl_module, decl_storage, decl_event, decl_error, ensure, + decl_module, decl_storage, decl_event, decl_error, ensure, traits::{Currency, ReservableCurrency, BalanceStatus}, }; use frame_system::{self as system, ensure_signed}; diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs index 1d929c73e5a60..58d86c1a8e8f0 100644 --- a/frame/atomic-swap/src/tests.rs +++ b/frame/atomic-swap/src/tests.rs @@ -3,8 +3,7 @@ use super::*; use frame_support::{ - assert_ok, impl_outer_origin, parameter_types, weights::{Weight, DispatchInfo, GetDispatchInfo}, - traits::{OnInitialize, OnFinalize} + impl_outer_origin, parameter_types, weights::Weight, }; use sp_core::H256; // The testing primitives are very useful for avoiding having to work with signatures @@ -71,20 +70,80 @@ impl Trait for Test { } type System = frame_system::Module; type Balances = pallet_balances::Module; -type Example = Module; +type AtomicSwap = Module; + +const A: u64 = 1; +const B: u64 = 2; -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. - pallet_balances::GenesisConfig::::default().assimilate_storage(&mut t).unwrap(); + let genesis = pallet_balances::GenesisConfig:: { + balances: vec![ + (A, 100), + (B, 200), + ], + }; + genesis.assimilate_storage(&mut t).unwrap(); t.into() } #[test] -fn two_party_swap() { - new_test_ext().execute_with(|| { - unimplemented!() +fn two_party_successful_swap() { + let mut chain1 = new_test_ext(); + let mut chain2 = new_test_ext(); + + // A generates a random proof. Keep it secret. + let proof: [u8; 2] = [4, 2]; + // The hashed proof is the blake2_256 hash of the proof. This is public. + let hashed_proof = blake2_256(&proof); + + // A creates the swap on chain1. + chain1.execute_with(|| { + AtomicSwap::create_swap( + Origin::signed(A), + B, + hashed_proof.clone(), + 50, + 1000, + ).unwrap(); + + assert_eq!(Balances::free_balance(A), 100 - 50); + assert_eq!(Balances::free_balance(B), 200); + }); + + // B creates the swap on chain2. + chain2.execute_with(|| { + AtomicSwap::create_swap( + Origin::signed(B), + A, + hashed_proof.clone(), + 75, + 1000, + ).unwrap(); + + assert_eq!(Balances::free_balance(A), 100); + assert_eq!(Balances::free_balance(B), 200 - 75); + }); + + // A reveals the proof and claims the swap on chain2. + chain2.execute_with(|| { + AtomicSwap::claim_swap( + Origin::signed(A), + proof.to_vec(), + ).unwrap(); + + assert_eq!(Balances::free_balance(A), 100 + 75); + assert_eq!(Balances::free_balance(B), 200 - 75); + }); + + // B use the revealed proof to claim the swap on chain1. + chain1.execute_with(|| { + AtomicSwap::claim_swap( + Origin::signed(B), + proof.to_vec(), + ).unwrap(); + + assert_eq!(Balances::free_balance(A), 100 - 50); + assert_eq!(Balances::free_balance(B), 200 + 50); }); } From 0b4454f482e26a643afe0470b83beb92d235798f Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 13:43:59 +0200 Subject: [PATCH 04/19] Bump node spec_version --- bin/node/runtime/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d64f641ea9d5a..fbde01b3f571f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -96,8 +96,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 252, - impl_version: 1, + spec_version: 253, + impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, }; From c3f88f5c6decb573610759af6f9f01c4aa296029 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 13:44:28 +0200 Subject: [PATCH 05/19] Fix storage name --- frame/atomic-swap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 223af5a5720cb..88116c46014ef 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -67,7 +67,7 @@ pub trait Trait: frame_system::Trait { } decl_storage! { - trait Store for Module as Example { + trait Store for Module as AtomicSwap { pub PendingSwaps: double_map hasher(twox_64_concat) T::AccountId, hasher(blake2_128_concat) HashedProof => Option>; From f885efbd4114b47b89a073cd9397e2abcd2a70c3 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 13:53:52 +0200 Subject: [PATCH 06/19] Add ProofLimit parameter to prevent proof size being too large --- frame/atomic-swap/src/lib.rs | 4 +++- frame/atomic-swap/src/tests.rs | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 88116c46014ef..252e7cb89544e 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -26,7 +26,7 @@ use sp_std::prelude::*; use sp_io::hashing::blake2_256; use frame_support::{ decl_module, decl_storage, decl_event, decl_error, ensure, - traits::{Currency, ReservableCurrency, BalanceStatus}, + traits::{Get, Currency, ReservableCurrency, BalanceStatus}, }; use frame_system::{self as system, ensure_signed}; use codec::{Encode, Decode}; @@ -64,6 +64,8 @@ pub trait Trait: frame_system::Trait { type Event: From> + Into<::Event>; /// The currency mechanism. type Currency: ReservableCurrency; + /// Limit of proof size. + type ProofLimit: Get; } decl_storage! { diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs index 58d86c1a8e8f0..3457ad5b8980e 100644 --- a/frame/atomic-swap/src/tests.rs +++ b/frame/atomic-swap/src/tests.rs @@ -28,6 +28,7 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const ProofLimit: u32 = 1024; } impl frame_system::Trait for Test { type Origin = Origin; @@ -67,6 +68,7 @@ impl pallet_balances::Trait for Test { impl Trait for Test { type Event = (); type Currency = Balances; + type ProofLimit = ProofLimit; } type System = frame_system::Module; type Balances = pallet_balances::Module; From 8ce4cce7d49df15a4fd63f4069cf90cc86383f51 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 13:54:10 +0200 Subject: [PATCH 07/19] Add missing events --- frame/atomic-swap/src/lib.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 252e7cb89544e..966e91b063dc8 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -82,6 +82,8 @@ decl_error! { AlreadyExist, /// Swap proof is invalid. InvalidProof, + /// Proof is too large. + ProofTooLarge, /// Swap does not exist. NotExist, /// Duration has not yet passed for the swap to be cancelled. @@ -101,7 +103,7 @@ decl_event!( /// Swap claimed. SwapClaimed(AccountId, HashedProof, Balance), /// Swap cancelled. - SwapCancelled(AccountId, HashedProof, Balance), + SwapCancelled(AccountId, HashedProof), } ); @@ -133,7 +135,11 @@ decl_module! { balance, end_block: frame_system::Module::::block_number() + duration, }; - PendingSwaps::::insert(target, hashed_proof, swap); + PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap.clone()); + + Self::deposit_event( + RawEvent::NewSwap(target, hashed_proof, swap) + ); } #[weight = 0] @@ -141,6 +147,11 @@ decl_module! { origin, proof: Vec, ) { + ensure!( + proof.len() <= T::ProofLimit::get() as usize, + Error::::ProofTooLarge, + ); + let target = ensure_signed(origin)?; let hashed_proof = blake2_256(&proof); @@ -152,7 +163,11 @@ decl_module! { swap.balance, BalanceStatus::Free, )?; - PendingSwaps::::remove(target, hashed_proof); + PendingSwaps::::remove(target.clone(), hashed_proof.clone()); + + Self::deposit_event( + RawEvent::SwapClaimed(target, hashed_proof, swap.balance) + ); } #[weight = 0] @@ -174,7 +189,11 @@ decl_module! { &swap.source, swap.balance, ); - PendingSwaps::::remove(&target, hashed_proof); + PendingSwaps::::remove(&target, hashed_proof.clone()); + + Self::deposit_event( + RawEvent::SwapCancelled(target, hashed_proof) + ); } } } From 3088ff198267b02a35ae7ab036f32917d6b775f3 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 13:58:28 +0200 Subject: [PATCH 08/19] Basic weight support --- frame/atomic-swap/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 966e91b063dc8..24c8e461b68a1 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -27,6 +27,7 @@ use sp_io::hashing::blake2_256; use frame_support::{ decl_module, decl_storage, decl_event, decl_error, ensure, traits::{Get, Currency, ReservableCurrency, BalanceStatus}, + weights::Weight, }; use frame_system::{self as system, ensure_signed}; use codec::{Encode, Decode}; @@ -114,7 +115,7 @@ decl_module! { fn deposit_event() = default; - #[weight = 0] + #[weight = T::DbWeight::get().reads_writes(1, 1).saturating_add(40_000_000)] fn create_swap( origin, target: AccountIdFor, @@ -142,7 +143,10 @@ decl_module! { ); } - #[weight = 0] + #[weight = T::DbWeight::get().reads_writes(1, 1) + .saturating_add(40_000_000) + .saturating_add((proof.len() as Weight).saturating_mul(100)) + ] fn claim_swap( origin, proof: Vec, @@ -170,7 +174,7 @@ decl_module! { ); } - #[weight = 0] + #[weight = T::DbWeight::get().reads_writes(1, 1).saturating_add(40_000_000)] fn cancel_swap( origin, target: AccountIdFor, From 8e18344a1375f03b1cb4dec72cc799f55d567fc1 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 14 Jun 2020 14:04:25 +0200 Subject: [PATCH 09/19] Add basic docs --- frame/atomic-swap/src/lib.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 24c8e461b68a1..da2eb86c8e210 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -85,6 +85,8 @@ decl_error! { InvalidProof, /// Proof is too large. ProofTooLarge, + /// Source does not match. + SourceMismatch, /// Swap does not exist. NotExist, /// Duration has not yet passed for the swap to be cancelled. @@ -115,6 +117,16 @@ decl_module! { fn deposit_event() = default; + /// Register a new atomic swap, declaring an intention to send funds from origin to target + /// on the current blockchain. The target can claim the fund using the revealed proof. If + /// the fund is not claimed after `duration` blocks, then the sender can cancel the swap. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `target`: Receiver of the atomic swap. + /// - `hashed_proof`: The blake2_256 hash of the secret proof. + /// - `balance`: Funds to be sent from origin. + /// - `duration`: Locked duration of the atomic swap. #[weight = T::DbWeight::get().reads_writes(1, 1).saturating_add(40_000_000)] fn create_swap( origin, @@ -143,6 +155,11 @@ decl_module! { ); } + /// Claim an atomic swap. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `proof`: Revealed proof of the claim. #[weight = T::DbWeight::get().reads_writes(1, 1) .saturating_add(40_000_000) .saturating_add((proof.len() as Weight).saturating_mul(100)) @@ -174,13 +191,19 @@ decl_module! { ); } + /// Cancel an atomic swap. Only possible after the originally set duration has passed. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `target`: Target of the original atomic swap. + /// - `hashed_proof`: Hashed proof of the original atomic swap. #[weight = T::DbWeight::get().reads_writes(1, 1).saturating_add(40_000_000)] fn cancel_swap( origin, target: AccountIdFor, hashed_proof: HashedProof, ) { - ensure_signed(origin)?; + let source = ensure_signed(origin)?; let swap = PendingSwaps::::get(&target, hashed_proof) .ok_or(Error::::NotExist)?; @@ -188,6 +211,10 @@ decl_module! { frame_system::Module::::block_number() >= swap.end_block, Error::::DurationNotPassed, ); + ensure!( + swap.source == source, + Error::::SourceMismatch, + ); T::Currency::unreserve( &swap.source, From 47877fa9033cca07f103b36331defeb86c0e69c1 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 16 Jun 2020 17:34:05 +0200 Subject: [PATCH 10/19] Mark swap on claim This handles the additional case if `repatriate_reserved` fails. --- frame/atomic-swap/src/lib.rs | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index da2eb86c8e210..17f6b80cb1139 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -28,6 +28,7 @@ use frame_support::{ decl_module, decl_storage, decl_event, decl_error, ensure, traits::{Get, Currency, ReservableCurrency, BalanceStatus}, weights::Weight, + dispatch::DispatchResult, }; use frame_system::{self as system, ensure_signed}; use codec::{Encode, Decode}; @@ -42,6 +43,8 @@ pub struct PendingSwap { pub balance: Balance, /// End block of the lock. pub end_block: BlockNumber, + /// Whether the swap has already been claimed. + pub claimed: bool, } /// Balance type from the pallet's point of view. @@ -87,6 +90,8 @@ decl_error! { ProofTooLarge, /// Source does not match. SourceMismatch, + /// Swap has already been claimed. + AlreadyClaimed, /// Swap does not exist. NotExist, /// Duration has not yet passed for the swap to be cancelled. @@ -105,6 +110,9 @@ decl_event!( NewSwap(AccountId, HashedProof, PendingSwap), /// Swap claimed. SwapClaimed(AccountId, HashedProof, Balance), + /// Swap claim failed its execution. However, the swap is still marked as claimed, and the + /// caller can try again later if it believes that this is a temporary error. + SwapClaimFailed(AccountId, HashedProof), /// Swap cancelled. SwapCancelled(AccountId, HashedProof), } @@ -137,7 +145,7 @@ decl_module! { ) { let source = ensure_signed(origin)?; ensure!( - PendingSwaps::::get(&target, hashed_proof).is_none(), + !PendingSwaps::::contains_key(&target, hashed_proof), Error::::AlreadyExist ); @@ -147,6 +155,7 @@ decl_module! { source, balance, end_block: frame_system::Module::::block_number() + duration, + claimed: false, }; PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap.clone()); @@ -167,7 +176,7 @@ decl_module! { fn claim_swap( origin, proof: Vec, - ) { + ) -> DispatchResult { ensure!( proof.len() <= T::ProofLimit::get() as usize, Error::::ProofTooLarge, @@ -176,19 +185,35 @@ decl_module! { let target = ensure_signed(origin)?; let hashed_proof = blake2_256(&proof); - let swap = PendingSwaps::::get(&target, hashed_proof) + let mut swap = PendingSwaps::::get(&target, hashed_proof) .ok_or(Error::::InvalidProof)?; - T::Currency::repatriate_reserved( + swap.claimed = true; + + match T::Currency::repatriate_reserved( &swap.source, &target, swap.balance, BalanceStatus::Free, - )?; - PendingSwaps::::remove(target.clone(), hashed_proof.clone()); + ) { + Ok(_) => { + PendingSwaps::::remove(target.clone(), hashed_proof.clone()); - Self::deposit_event( - RawEvent::SwapClaimed(target, hashed_proof, swap.balance) - ); + Self::deposit_event( + RawEvent::SwapClaimed(target, hashed_proof, swap.balance) + ); + + Ok(()) + }, + Err(e) => { + PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap); + + Self::deposit_event( + RawEvent::SwapClaimFailed(target, hashed_proof) + ); + + Err(e.into()) + }, + } } /// Cancel an atomic swap. Only possible after the originally set duration has passed. @@ -208,13 +233,17 @@ decl_module! { let swap = PendingSwaps::::get(&target, hashed_proof) .ok_or(Error::::NotExist)?; ensure!( - frame_system::Module::::block_number() >= swap.end_block, - Error::::DurationNotPassed, + !swap.claimed, + Error::::AlreadyClaimed, ); ensure!( swap.source == source, Error::::SourceMismatch, ); + ensure!( + frame_system::Module::::block_number() >= swap.end_block, + Error::::DurationNotPassed, + ); T::Currency::unreserve( &swap.source, From d51b1ded6affc1d7a3d52fb4b489ef3c93004c9c Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 16 Jun 2020 17:44:02 +0200 Subject: [PATCH 11/19] Add additional expire handler --- frame/atomic-swap/src/lib.rs | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index 17f6b80cb1139..eeda0aef0bf4c 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -32,7 +32,7 @@ use frame_support::{ }; use frame_system::{self as system, ensure_signed}; use codec::{Encode, Decode}; -use sp_runtime::RuntimeDebug; +use sp_runtime::{RuntimeDebug, traits::Saturating}; /// Pending atomic swap operation. #[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode)] @@ -70,6 +70,8 @@ pub trait Trait: frame_system::Trait { type Currency: ReservableCurrency; /// Limit of proof size. type ProofLimit: Get; + /// Block when the swap completely expires. + type ExpireDuration: Get>; } decl_storage! { @@ -110,9 +112,8 @@ decl_event!( NewSwap(AccountId, HashedProof, PendingSwap), /// Swap claimed. SwapClaimed(AccountId, HashedProof, Balance), - /// Swap claim failed its execution. However, the swap is still marked as claimed, and the - /// caller can try again later if it believes that this is a temporary error. - SwapClaimFailed(AccountId, HashedProof), + /// Swap claim failed its execution. The last parameter indicates whether retry is possible. + SwapClaimFailed(AccountId, HashedProof, bool), /// Swap cancelled. SwapCancelled(AccountId, HashedProof), } @@ -195,6 +196,25 @@ decl_module! { swap.balance, BalanceStatus::Free, ) { + Err(e) => { + let expired = frame_system::Module::::block_number() > + swap.end_block.saturating_add(T::ExpireDuration::get()); + if expired { + PendingSwaps::::remove(target.clone(), hashed_proof.clone()); + + Self::deposit_event( + RawEvent::SwapClaimFailed(target, hashed_proof, false) + ); + } else { + PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap); + + Self::deposit_event( + RawEvent::SwapClaimFailed(target, hashed_proof, true) + ); + } + + Err(e.into()) + }, Ok(_) => { PendingSwaps::::remove(target.clone(), hashed_proof.clone()); @@ -204,15 +224,7 @@ decl_module! { Ok(()) }, - Err(e) => { - PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap); - Self::deposit_event( - RawEvent::SwapClaimFailed(target, hashed_proof) - ); - - Err(e.into()) - }, } } From fe709445f03344859546815c9903ca5d59d8f991 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 16 Jun 2020 17:44:47 +0200 Subject: [PATCH 12/19] Update frame/atomic-swap/src/lib.rs Co-authored-by: Shawn Tabrizi --- frame/atomic-swap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index eeda0aef0bf4c..82e5b501e25a9 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -170,7 +170,7 @@ decl_module! { /// The dispatch origin for this call must be _Signed_. /// /// - `proof`: Revealed proof of the claim. - #[weight = T::DbWeight::get().reads_writes(1, 1) + #[weight = T::DbWeight::get().reads_writes(2, 2) .saturating_add(40_000_000) .saturating_add((proof.len() as Weight).saturating_mul(100)) ] From fa2a85e1ee5c1c84631428d8f052ae51d07abfb9 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 16 Jun 2020 17:46:03 +0200 Subject: [PATCH 13/19] Add docs on ProofLimit --- frame/atomic-swap/src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index eeda0aef0bf4c..1cc145e33f679 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -69,6 +69,15 @@ pub trait Trait: frame_system::Trait { /// The currency mechanism. type Currency: ReservableCurrency; /// Limit of proof size. + /// + /// Atomic swap is only atomic if once the proof is revealed, both parties can submit the proofs + /// on-chain. If A is the one that generates the proof, then it requires that either: + /// - A's blockchain has the same proof length limit as B's blockchain. + /// - Or A's blockchain has shorter proof length limit as B's blockchain. + /// + /// If B sees A is on a blockchain with larger proof length limit, then it should kindly refuse + /// to accept the atomic swap request if A generates the proof, and asks that B generates the + /// proof instead. type ProofLimit: Get; /// Block when the swap completely expires. type ExpireDuration: Get>; From b71ca91bc69f615eaa3e067417392f87bc2b5c08 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 16 Jun 2020 18:44:16 +0200 Subject: [PATCH 14/19] Fix test --- frame/atomic-swap/src/tests.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs index 3457ad5b8980e..317c4337a17c2 100644 --- a/frame/atomic-swap/src/tests.rs +++ b/frame/atomic-swap/src/tests.rs @@ -28,7 +28,6 @@ parameter_types! { pub const MaximumBlockWeight: Weight = 1024; pub const MaximumBlockLength: u32 = 2 * 1024; pub const AvailableBlockRatio: Perbill = Perbill::one(); - pub const ProofLimit: u32 = 1024; } impl frame_system::Trait for Test { type Origin = Origin; @@ -65,10 +64,15 @@ impl pallet_balances::Trait for Test { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; } +parameter_types! { + pub const ProofLimit: u32 = 1024; + pub const ExpireDuration: u64 = 100; +} impl Trait for Test { type Event = (); type Currency = Balances; type ProofLimit = ProofLimit; + type ExpireDuration = ExpireDuration; } type System = frame_system::Module; type Balances = pallet_balances::Module; From 2aa173ba5e48f51f0b71d9120104042bf585f5a1 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 16 Jun 2020 19:59:20 +0200 Subject: [PATCH 15/19] Return Ok(()) even when the transfer fails Because we need to mark the swap as claimed no matter what. --- frame/atomic-swap/src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index ad980ade1e634..f574c063c6a08 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -121,7 +121,8 @@ decl_event!( NewSwap(AccountId, HashedProof, PendingSwap), /// Swap claimed. SwapClaimed(AccountId, HashedProof, Balance), - /// Swap claim failed its execution. The last parameter indicates whether retry is possible. + /// Swap claim failed its execution. + /// The third parameter indicates whether retry is possible. SwapClaimFailed(AccountId, HashedProof, bool), /// Swap cancelled. SwapCancelled(AccountId, HashedProof), @@ -205,7 +206,7 @@ decl_module! { swap.balance, BalanceStatus::Free, ) { - Err(e) => { + Err(_) => { let expired = frame_system::Module::::block_number() > swap.end_block.saturating_add(T::ExpireDuration::get()); if expired { @@ -222,7 +223,7 @@ decl_module! { ); } - Err(e.into()) + Ok(()) }, Ok(_) => { PendingSwaps::::remove(target.clone(), hashed_proof.clone()); From ad361856bf637b02b5e151e9323b36f524044c27 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 16 Jun 2020 20:37:50 +0200 Subject: [PATCH 16/19] Remove retry logic It's overkill. Swap is about something being executed, not necessarily successful. Although there should be logic (reserve and unreserve) to make it so that both parties *believes* that the execution is successful. --- frame/atomic-swap/src/lib.rs | 63 ++++++++-------------------------- frame/atomic-swap/src/tests.rs | 1 - 2 files changed, 14 insertions(+), 50 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index f574c063c6a08..a2767e543a185 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -32,7 +32,7 @@ use frame_support::{ }; use frame_system::{self as system, ensure_signed}; use codec::{Encode, Decode}; -use sp_runtime::{RuntimeDebug, traits::Saturating}; +use sp_runtime::RuntimeDebug; /// Pending atomic swap operation. #[derive(Clone, RuntimeDebug, Eq, PartialEq, Encode, Decode)] @@ -43,8 +43,6 @@ pub struct PendingSwap { pub balance: Balance, /// End block of the lock. pub end_block: BlockNumber, - /// Whether the swap has already been claimed. - pub claimed: bool, } /// Balance type from the pallet's point of view. @@ -79,8 +77,6 @@ pub trait Trait: frame_system::Trait { /// to accept the atomic swap request if A generates the proof, and asks that B generates the /// proof instead. type ProofLimit: Get; - /// Block when the swap completely expires. - type ExpireDuration: Get>; } decl_storage! { @@ -119,11 +115,8 @@ decl_event!( { /// Swap created. NewSwap(AccountId, HashedProof, PendingSwap), - /// Swap claimed. - SwapClaimed(AccountId, HashedProof, Balance), - /// Swap claim failed its execution. - /// The third parameter indicates whether retry is possible. - SwapClaimFailed(AccountId, HashedProof, bool), + /// Swap claimed. The last parameter indicates whether the execution succeeds. + SwapClaimed(AccountId, HashedProof, Balance, bool), /// Swap cancelled. SwapCancelled(AccountId, HashedProof), } @@ -166,7 +159,6 @@ decl_module! { source, balance, end_block: frame_system::Module::::block_number() + duration, - claimed: false, }; PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap.clone()); @@ -196,46 +188,23 @@ decl_module! { let target = ensure_signed(origin)?; let hashed_proof = blake2_256(&proof); - let mut swap = PendingSwaps::::get(&target, hashed_proof) + let swap = PendingSwaps::::get(&target, hashed_proof) .ok_or(Error::::InvalidProof)?; - swap.claimed = true; - match T::Currency::repatriate_reserved( + let succeed = T::Currency::repatriate_reserved( &swap.source, &target, swap.balance, BalanceStatus::Free, - ) { - Err(_) => { - let expired = frame_system::Module::::block_number() > - swap.end_block.saturating_add(T::ExpireDuration::get()); - if expired { - PendingSwaps::::remove(target.clone(), hashed_proof.clone()); - - Self::deposit_event( - RawEvent::SwapClaimFailed(target, hashed_proof, false) - ); - } else { - PendingSwaps::::insert(target.clone(), hashed_proof.clone(), swap); - - Self::deposit_event( - RawEvent::SwapClaimFailed(target, hashed_proof, true) - ); - } - - Ok(()) - }, - Ok(_) => { - PendingSwaps::::remove(target.clone(), hashed_proof.clone()); - - Self::deposit_event( - RawEvent::SwapClaimed(target, hashed_proof, swap.balance) - ); - - Ok(()) - }, - - } + ).is_ok(); + + PendingSwaps::::remove(target.clone(), hashed_proof.clone()); + + Self::deposit_event( + RawEvent::SwapClaimed(target, hashed_proof, swap.balance, succeed) + ); + + Ok(()) } /// Cancel an atomic swap. Only possible after the originally set duration has passed. @@ -254,10 +223,6 @@ decl_module! { let swap = PendingSwaps::::get(&target, hashed_proof) .ok_or(Error::::NotExist)?; - ensure!( - !swap.claimed, - Error::::AlreadyClaimed, - ); ensure!( swap.source == source, Error::::SourceMismatch, diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs index 317c4337a17c2..b7094ffa18756 100644 --- a/frame/atomic-swap/src/tests.rs +++ b/frame/atomic-swap/src/tests.rs @@ -72,7 +72,6 @@ impl Trait for Test { type Event = (); type Currency = Balances; type ProofLimit = ProofLimit; - type ExpireDuration = ExpireDuration; } type System = frame_system::Module; type Balances = pallet_balances::Module; From a46db72136d397598d2ecb39fc10f91d8f893194 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 16 Jun 2020 20:40:19 +0200 Subject: [PATCH 17/19] succeed -> succeeded --- frame/atomic-swap/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index a2767e543a185..d1a9467774b76 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -191,7 +191,7 @@ decl_module! { let swap = PendingSwaps::::get(&target, hashed_proof) .ok_or(Error::::InvalidProof)?; - let succeed = T::Currency::repatriate_reserved( + let succeeded = T::Currency::repatriate_reserved( &swap.source, &target, swap.balance, @@ -201,7 +201,7 @@ decl_module! { PendingSwaps::::remove(target.clone(), hashed_proof.clone()); Self::deposit_event( - RawEvent::SwapClaimed(target, hashed_proof, swap.balance, succeed) + RawEvent::SwapClaimed(target, hashed_proof, swap.balance, succeeded) ); Ok(()) From 96b13927e0284349cc6e2ac37cfc9d14a7803001 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 17 Jun 2020 11:38:20 +0200 Subject: [PATCH 18/19] Add docs on duration -- revealer should use duration shorter than counterparty --- frame/atomic-swap/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frame/atomic-swap/src/lib.rs b/frame/atomic-swap/src/lib.rs index d1a9467774b76..aa33c9a849fff 100644 --- a/frame/atomic-swap/src/lib.rs +++ b/frame/atomic-swap/src/lib.rs @@ -138,7 +138,9 @@ decl_module! { /// - `target`: Receiver of the atomic swap. /// - `hashed_proof`: The blake2_256 hash of the secret proof. /// - `balance`: Funds to be sent from origin. - /// - `duration`: Locked duration of the atomic swap. + /// - `duration`: Locked duration of the atomic swap. For safety reasons, it is recommended + /// that the revealer uses a shorter duration than the counterparty, to prevent the + /// situation where the revealer reveals the proof too late around the end block. #[weight = T::DbWeight::get().reads_writes(1, 1).saturating_add(40_000_000)] fn create_swap( origin, From 9cc2350df4e68c6587a20999c0c2f26127d9e5f6 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 17 Jun 2020 12:29:36 +0200 Subject: [PATCH 19/19] Missing trait type --- frame/atomic-swap/src/tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frame/atomic-swap/src/tests.rs b/frame/atomic-swap/src/tests.rs index b7094ffa18756..72db841de19df 100644 --- a/frame/atomic-swap/src/tests.rs +++ b/frame/atomic-swap/src/tests.rs @@ -30,6 +30,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64;