From b883aa7676f1da75881fef0774f2e5a5e5ea180d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9=20=28Ubuntu=2018=2E04=20WSL=29?= Date: Thu, 3 Oct 2019 00:53:16 +0100 Subject: [PATCH 1/4] Add `swap` and `decode_len` to `DoubleMap` --- node/runtime/src/lib.rs | 4 +- .../src/storage/generator/double_map.rs | 40 ++++++++++++++++++- srml/support/src/storage/mod.rs | 19 +++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 82ffe5390fd64..9b35950e2642d 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -84,8 +84,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to equal spec_version. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 170, - impl_version: 170, + spec_version: 171, + impl_version: 171, apis: RUNTIME_API_VERSIONS, }; diff --git a/srml/support/src/storage/generator/double_map.rs b/srml/support/src/storage/generator/double_map.rs index cac8dbd034e85..032db1415a370 100644 --- a/srml/support/src/storage/generator/double_map.rs +++ b/srml/support/src/storage/generator/double_map.rs @@ -17,7 +17,7 @@ use rstd::prelude::*; use rstd::borrow::Borrow; use codec::{Ref, FullCodec, FullEncode, Encode, EncodeLike, EncodeAppend}; -use crate::{storage::{self, unhashed}, hash::StorageHasher}; +use crate::{storage::{self, unhashed}, hash::StorageHasher, traits::Len}; /// Generator for `StorageDoubleMap` used by `decl_storage`. /// @@ -116,6 +116,27 @@ where G::from_optional_value_to_query(value) } + fn swap(key11: KArg1, key12: KArg2, key21: KArg1, key22: KArg2) + where + KArg1: EncodeLike, + KArg2: EncodeLike, + { + let final_k1 = Self::storage_double_map_final_key(key11, key12); + let final_k2 = Self::storage_double_map_final_key(key21, key22); + + let v1 = unhashed::get_raw(&final_k1); + if let Some(val) = unhashed::get_raw(&final_k2) { + unhashed::put_raw(&final_k1, &val); + } else { + unhashed::kill(&final_k1) + } + if let Some(val) = v1 { + unhashed::put_raw(&final_k2, &val); + } else { + unhashed::kill(&final_k2) + } + } + fn insert(k1: KArg1, k2: KArg2, val: VArg) where KArg1: EncodeLike, @@ -204,4 +225,21 @@ where Self::append(Ref::from(&k1), Ref::from(&k2), items.clone()) .unwrap_or_else(|_| Self::insert(k1, k2, items)); } + + fn decode_len(key1: KArg1, key2: KArg2) -> Result + where KArg1: EncodeLike, + KArg2: EncodeLike, + V: codec::DecodeLength + Len, + { + let final_key = Self::storage_double_map_final_key(key1, key2); + if let Some(v) = unhashed::get_raw(&final_key) { + ::len(&v).map_err(|e| e.what()) + } else { + let len = G::from_query_to_optional_value(G::from_optional_value_to_query(None)) + .map(|v| v.len()) + .unwrap_or(0); + + Ok(len) + } + } } diff --git a/srml/support/src/storage/mod.rs b/srml/support/src/storage/mod.rs index 648009b470e42..f356adf7848aa 100644 --- a/srml/support/src/storage/mod.rs +++ b/srml/support/src/storage/mod.rs @@ -226,6 +226,12 @@ pub trait StorageDoubleMap { KArg1: EncodeLike, KArg2: EncodeLike; + /// Swap the values of two key-pairs. + fn swap(key11: KArg1, key12: KArg2, key21: KArg1, key22: KArg2) + where + KArg1: EncodeLike, + KArg2: EncodeLike; + fn insert(k1: KArg1, k2: KArg2, val: VArg) where KArg1: EncodeLike, @@ -272,4 +278,17 @@ pub trait StorageDoubleMap { V: EncodeAppend, Items: IntoIterator + Clone + EncodeLike, Items::IntoIter: ExactSizeIterator; + + /// Read the length of the value in a fast way, without decoding the entire value. + /// + /// `T` is required to implement `Codec::DecodeLength`. + /// + /// Note that `0` is returned as the default value if no encoded value exists at the given key. + /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` + /// function for this purpose. + fn decode_len(key1: KArg1, key2: KArg2) -> Result + where + KArg1: EncodeLike, + KArg2: EncodeLike, + V: codec::DecodeLength + Len; } From 6c97a1bd945c9548e9fc9c0eafcdf7e8dcc7ac56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bald=C3=A9=20=28Ubuntu=2018=2E04=20WSL=29?= Date: Sun, 6 Oct 2019 21:28:57 +0100 Subject: [PATCH 2/4] Add tests to `swap` and `decode_len` for `DoubleMap` (WIP) --- srml/support/src/lib.rs | 29 +++++++++++++++++++++++ srml/support/src/storage/mod.rs | 2 +- srml/support/src/storage/storage_items.rs | 16 +++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index b88d86761c314..763775e1f2396 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -326,6 +326,35 @@ mod tests { }); } + fn double_map_swap_works() { + with_externalities(&mut new_test_ext(), || { + type DoubleMap = DataDM; + DataDM::insert(0, 1, 0); + DataDM::insert(0, 2, 1); + DataDM::insert(0, 3, 2); + DataDM::insert(0, 4, 3); + + let collect = || DataDM::enumerate().collect::>(); + assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); + + // Two existing + DataDM::swap(0, 1, 0, 2); + assert_eq!(collect(), vec![(3, 3), (2, 1), (1, 2), (0, 0)]); + + // Back to normal + DataDM::swap(0, 2, 0, 1); + assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); + + // Left existing + DataDM::swap(0, 2, 0, 5); + assert_eq!(collect(), vec![(5, 2), (3, 3), (1, 1), (0, 0)]); + + // Right existing + DataDM::swap(0, 5, 0, 2); + assert_eq!(collect(), vec![(2, 2), (3, 3), (1, 1), (0, 0)]); + }); + } + #[test] fn linked_map_basic_insert_remove_should_work() { with_externalities(&mut new_test_ext(), || { diff --git a/srml/support/src/storage/mod.rs b/srml/support/src/storage/mod.rs index f356adf7848aa..6661eb7141fd8 100644 --- a/srml/support/src/storage/mod.rs +++ b/srml/support/src/storage/mod.rs @@ -281,7 +281,7 @@ pub trait StorageDoubleMap { /// Read the length of the value in a fast way, without decoding the entire value. /// - /// `T` is required to implement `Codec::DecodeLength`. + /// `V` is required to implement `Codec::DecodeLength`. /// /// Note that `0` is returned as the default value if no encoded value exists at the given key. /// Therefore, this function cannot be used as a sign of _existence_. use the `::exists()` diff --git a/srml/support/src/storage/storage_items.rs b/srml/support/src/storage/storage_items.rs index 24a7f3984a865..f6ebddd770183 100644 --- a/srml/support/src/storage/storage_items.rs +++ b/srml/support/src/storage/storage_items.rs @@ -786,6 +786,10 @@ mod test_append_and_len { MapVecWithDefault: map u32 => Vec = vec![6, 9]; OptionMapVec: map u32 => Option>; + DoubleMapVec: double_map u32, u32 => Vec; + DoubleMapVecWithDefault: double_map u32, u32 => Vec = vec![6, 9]; + OptionDoubleMapVec: double_map u32, u32 => Option>; + LinkedMapVec: linked_map u32 => Vec; LinkedMapVecWithDefault: linked_map u32 => Vec = vec![6, 9]; OptionLinkedMapVec: linked_map u32 => Option>; @@ -861,11 +865,13 @@ mod test_append_and_len { OptionVec::put(&vec![1, 2, 3, 4, 5]); MapVec::insert(1, &vec![1, 2, 3, 4, 5, 6]); LinkedMapVec::insert(2, &vec![1, 2, 3]); + DoubleMapVec::insert(0, 1, &vec![1, 2]); assert_eq!(JustVec::decode_len().unwrap(), 4); assert_eq!(OptionVec::decode_len().unwrap(), 5); assert_eq!(MapVec::decode_len(1).unwrap(), 6); assert_eq!(LinkedMapVec::decode_len(2).unwrap(), 3); + assert_eq!(DoubleMapVec::decode_len(0, 1).unwrap(), 2); }); } @@ -901,6 +907,16 @@ mod test_append_and_len { assert_eq!(OptionLinkedMapVec::get(0), None); assert_eq!(OptionLinkedMapVec::decode_len(0), Ok(0)); + + // Double map + assert_eq!(DoubleMapVec::get(0), vec![]); + assert_eq!(DoubleMapVec::decode_len(0, 1), Ok(0)); + + assert_eq!(DoubleMapVecWithDefault::get(0), vec![6, 9]); + assert_eq!(DoubleMapVecWithDefault::decode_len(0, 1), Ok(2)); + + assert_eq!(OptionDoubleMapVec::get(0), None); + assert_eq!(OptionDoubleMapVec::decode_len(0, 1), Ok(0)); }); } } From cb66b1e753692098614cce9c643b218a59b6b484 Mon Sep 17 00:00:00 2001 From: Alexandre Date: Sat, 2 Nov 2019 02:13:14 +0000 Subject: [PATCH 3/4] Address review comments --- srml/support/src/lib.rs | 2 +- srml/support/src/storage/generator/double_map.rs | 4 +++- srml/support/src/storage/mod.rs | 6 ++++-- srml/support/src/storage/storage_items.rs | 6 +++--- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 763775e1f2396..32a608015375f 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -334,7 +334,7 @@ mod tests { DataDM::insert(0, 3, 2); DataDM::insert(0, 4, 3); - let collect = || DataDM::enumerate().collect::>(); + let collect = || DataDM::collect::>(); assert_eq!(collect(), vec![(3, 3), (2, 2), (1, 1), (0, 0)]); // Two existing diff --git a/srml/support/src/storage/generator/double_map.rs b/srml/support/src/storage/generator/double_map.rs index 032db1415a370..95295d203d78e 100644 --- a/srml/support/src/storage/generator/double_map.rs +++ b/srml/support/src/storage/generator/double_map.rs @@ -116,10 +116,12 @@ where G::from_optional_value_to_query(value) } - fn swap(key11: KArg1, key12: KArg2, key21: KArg1, key22: KArg2) + fn swap(key11: KArg1, key12: KArg2, key21: KArg3, key22: KArg4) where KArg1: EncodeLike, KArg2: EncodeLike, + KArg3: EncodeLike, + KArg4: EncodeLike, { let final_k1 = Self::storage_double_map_final_key(key11, key12); let final_k2 = Self::storage_double_map_final_key(key21, key22); diff --git a/srml/support/src/storage/mod.rs b/srml/support/src/storage/mod.rs index 6661eb7141fd8..102ba1d5b56f9 100644 --- a/srml/support/src/storage/mod.rs +++ b/srml/support/src/storage/mod.rs @@ -227,10 +227,12 @@ pub trait StorageDoubleMap { KArg2: EncodeLike; /// Swap the values of two key-pairs. - fn swap(key11: KArg1, key12: KArg2, key21: KArg1, key22: KArg2) + fn swap(key11: KArg1, key12: KArg2, key21: KArg3, key22: KArg4) where KArg1: EncodeLike, - KArg2: EncodeLike; + KArg2: EncodeLike, + KArg3: EncodeLike, + KArg4: EncodeLike; fn insert(k1: KArg1, k2: KArg2, val: VArg) where diff --git a/srml/support/src/storage/storage_items.rs b/srml/support/src/storage/storage_items.rs index f6ebddd770183..82f6a08685d0c 100644 --- a/srml/support/src/storage/storage_items.rs +++ b/srml/support/src/storage/storage_items.rs @@ -909,13 +909,13 @@ mod test_append_and_len { assert_eq!(OptionLinkedMapVec::decode_len(0), Ok(0)); // Double map - assert_eq!(DoubleMapVec::get(0), vec![]); + assert_eq!(DoubleMapVec::get(0, 0), vec![]); assert_eq!(DoubleMapVec::decode_len(0, 1), Ok(0)); - assert_eq!(DoubleMapVecWithDefault::get(0), vec![6, 9]); + assert_eq!(DoubleMapVecWithDefault::get(0, 0), vec![6, 9]); assert_eq!(DoubleMapVecWithDefault::decode_len(0, 1), Ok(2)); - assert_eq!(OptionDoubleMapVec::get(0), None); + assert_eq!(OptionDoubleMapVec::get(0, 0), None); assert_eq!(OptionDoubleMapVec::decode_len(0, 1), Ok(0)); }); } From e5635bf9dac8fd3d724a1de34f26b758bc5c15b9 Mon Sep 17 00:00:00 2001 From: Alexandre Date: Sat, 2 Nov 2019 02:37:41 +0000 Subject: [PATCH 4/4] Remove function that is not in scope --- srml/support/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index e47c6137bb894..c3649dd6ce553 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -327,8 +327,9 @@ mod tests { }); } + #[test] fn double_map_swap_works() { - with_externalities(&mut new_test_ext(), || { + new_test_ext().execute_with(|| { type DoubleMap = DataDM; DataDM::insert(0, 1, 0); DataDM::insert(0, 2, 1);