referrerpolicy=no-referrer-when-downgrade

frame_support/storage/generator/
double_map.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use crate::{
19	hash::{ReversibleStorageHasher, StorageHasher},
20	storage::{self, storage_prefix, unhashed, KeyPrefixIterator, PrefixIterator, StorageAppend},
21	Never,
22};
23use alloc::vec::Vec;
24use codec::{Decode, Encode, EncodeLike, FullCodec, FullEncode};
25
26/// Generator for `StorageDoubleMap` used by `decl_storage`.
27///
28/// # Mapping of keys to a storage path
29///
30/// The storage key (i.e. the key under which the `Value` will be stored) is created from two parts.
31/// The first part is a hash of a concatenation of the `key1_prefix` and `Key1`. And the second part
32/// is a hash of a `Key2`.
33///
34/// Thus value for (key1, key2) is stored at:
35/// ```nocompile
36/// Twox128(pallet_prefix) ++ Twox128(storage_prefix) ++ Hasher1(encode(key1)) ++ Hasher2(encode(key2))
37/// ```
38///
39/// # Warning
40///
41/// If the key1s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
42/// `blake2_256` must be used for Hasher1. Otherwise, other values in storage can be compromised.
43/// If the key2s are not trusted (e.g. can be set by a user), a cryptographic `hasher` such as
44/// `blake2_256` must be used for Hasher2. Otherwise, other items in storage with the same first
45/// key can be compromised.
46pub trait StorageDoubleMap<K1: FullEncode, K2: FullEncode, V: FullCodec> {
47	/// The type that get/take returns.
48	type Query;
49
50	/// Hasher for the first key.
51	type Hasher1: StorageHasher;
52
53	/// Hasher for the second key.
54	type Hasher2: StorageHasher;
55
56	/// Pallet prefix. Used for generating final key.
57	fn pallet_prefix() -> &'static [u8];
58
59	/// Storage prefix. Used for generating final key.
60	fn storage_prefix() -> &'static [u8];
61
62	/// The full prefix; just the hash of `pallet_prefix` concatenated to the hash of
63	/// `storage_prefix`.
64	fn prefix_hash() -> [u8; 32];
65
66	/// Convert an optional value retrieved from storage to the type queried.
67	fn from_optional_value_to_query(v: Option<V>) -> Self::Query;
68
69	/// Convert a query to an optional value into storage.
70	fn from_query_to_optional_value(v: Self::Query) -> Option<V>;
71
72	/// Generate the first part of the key used in top storage.
73	fn storage_double_map_final_key1<KArg1>(k1: KArg1) -> Vec<u8>
74	where
75		KArg1: EncodeLike<K1>,
76	{
77		let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
78		let key_hashed = k1.using_encoded(Self::Hasher1::hash);
79
80		let mut final_key = Vec::with_capacity(storage_prefix.len() + key_hashed.as_ref().len());
81
82		final_key.extend_from_slice(&storage_prefix);
83		final_key.extend_from_slice(key_hashed.as_ref());
84
85		final_key
86	}
87
88	/// Generate the full key used in top storage.
89	fn storage_double_map_final_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
90	where
91		KArg1: EncodeLike<K1>,
92		KArg2: EncodeLike<K2>,
93	{
94		let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
95		let key1_hashed = k1.using_encoded(Self::Hasher1::hash);
96		let key2_hashed = k2.using_encoded(Self::Hasher2::hash);
97
98		let mut final_key = Vec::with_capacity(
99			storage_prefix.len() + key1_hashed.as_ref().len() + key2_hashed.as_ref().len(),
100		);
101
102		final_key.extend_from_slice(&storage_prefix);
103		final_key.extend_from_slice(key1_hashed.as_ref());
104		final_key.extend_from_slice(key2_hashed.as_ref());
105
106		final_key
107	}
108}
109
110impl<K1, K2, V, G> storage::StorageDoubleMap<K1, K2, V> for G
111where
112	K1: FullEncode,
113	K2: FullEncode,
114	V: FullCodec,
115	G: StorageDoubleMap<K1, K2, V>,
116{
117	type Query = G::Query;
118
119	fn hashed_key_for<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
120	where
121		KArg1: EncodeLike<K1>,
122		KArg2: EncodeLike<K2>,
123	{
124		Self::storage_double_map_final_key(k1, k2)
125	}
126
127	fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool
128	where
129		KArg1: EncodeLike<K1>,
130		KArg2: EncodeLike<K2>,
131	{
132		unhashed::exists(&Self::storage_double_map_final_key(k1, k2))
133	}
134
135	fn get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
136	where
137		KArg1: EncodeLike<K1>,
138		KArg2: EncodeLike<K2>,
139	{
140		G::from_optional_value_to_query(unhashed::get(&Self::storage_double_map_final_key(k1, k2)))
141	}
142
143	fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<V, ()>
144	where
145		KArg1: EncodeLike<K1>,
146		KArg2: EncodeLike<K2>,
147	{
148		unhashed::get(&Self::storage_double_map_final_key(k1, k2)).ok_or(())
149	}
150
151	fn set<KArg1: EncodeLike<K1>, KArg2: EncodeLike<K2>>(k1: KArg1, k2: KArg2, q: Self::Query) {
152		match G::from_query_to_optional_value(q) {
153			Some(v) => Self::insert(k1, k2, v),
154			None => Self::remove(k1, k2),
155		}
156	}
157
158	fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Self::Query
159	where
160		KArg1: EncodeLike<K1>,
161		KArg2: EncodeLike<K2>,
162	{
163		let final_key = Self::storage_double_map_final_key(k1, k2);
164
165		let value = unhashed::take(&final_key);
166		G::from_optional_value_to_query(value)
167	}
168
169	fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(x_k1: XKArg1, x_k2: XKArg2, y_k1: YKArg1, y_k2: YKArg2)
170	where
171		XKArg1: EncodeLike<K1>,
172		XKArg2: EncodeLike<K2>,
173		YKArg1: EncodeLike<K1>,
174		YKArg2: EncodeLike<K2>,
175	{
176		let final_x_key = Self::storage_double_map_final_key(x_k1, x_k2);
177		let final_y_key = Self::storage_double_map_final_key(y_k1, y_k2);
178
179		let v1 = unhashed::get_raw(&final_x_key);
180		if let Some(val) = unhashed::get_raw(&final_y_key) {
181			unhashed::put_raw(&final_x_key, &val);
182		} else {
183			unhashed::kill(&final_x_key)
184		}
185		if let Some(val) = v1 {
186			unhashed::put_raw(&final_y_key, &val);
187		} else {
188			unhashed::kill(&final_y_key)
189		}
190	}
191
192	fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg)
193	where
194		KArg1: EncodeLike<K1>,
195		KArg2: EncodeLike<K2>,
196		VArg: EncodeLike<V>,
197	{
198		unhashed::put(&Self::storage_double_map_final_key(k1, k2), &val)
199	}
200
201	fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2)
202	where
203		KArg1: EncodeLike<K1>,
204		KArg2: EncodeLike<K2>,
205	{
206		unhashed::kill(&Self::storage_double_map_final_key(k1, k2))
207	}
208
209	fn remove_prefix<KArg1>(k1: KArg1, maybe_limit: Option<u32>) -> sp_io::KillStorageResult
210	where
211		KArg1: EncodeLike<K1>,
212	{
213		unhashed::clear_prefix(Self::storage_double_map_final_key1(k1).as_ref(), maybe_limit, None)
214			.into()
215	}
216
217	fn clear_prefix<KArg1>(
218		k1: KArg1,
219		limit: u32,
220		maybe_cursor: Option<&[u8]>,
221	) -> sp_io::MultiRemovalResults
222	where
223		KArg1: EncodeLike<K1>,
224	{
225		unhashed::clear_prefix(
226			Self::storage_double_map_final_key1(k1).as_ref(),
227			Some(limit),
228			maybe_cursor,
229		)
230		.into()
231	}
232
233	fn contains_prefix<KArg1>(k1: KArg1) -> bool
234	where
235		KArg1: EncodeLike<K1>,
236	{
237		unhashed::contains_prefixed_key(Self::storage_double_map_final_key1(k1).as_ref())
238	}
239
240	fn iter_prefix_values<KArg1>(k1: KArg1) -> storage::PrefixIterator<V>
241	where
242		KArg1: ?Sized + EncodeLike<K1>,
243	{
244		let prefix = Self::storage_double_map_final_key1(k1);
245		storage::PrefixIterator {
246			prefix: prefix.clone(),
247			previous_key: prefix,
248			drain: false,
249			closure: |_raw_key, mut raw_value| V::decode(&mut raw_value),
250			phantom: Default::default(),
251		}
252	}
253
254	fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
255	where
256		KArg1: EncodeLike<K1>,
257		KArg2: EncodeLike<K2>,
258		F: FnOnce(&mut Self::Query) -> R,
259	{
260		Self::try_mutate(k1, k2, |v| Ok::<R, Never>(f(v)))
261			.expect("`Never` can not be constructed; qed")
262	}
263
264	fn mutate_exists<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
265	where
266		KArg1: EncodeLike<K1>,
267		KArg2: EncodeLike<K2>,
268		F: FnOnce(&mut Option<V>) -> R,
269	{
270		Self::try_mutate_exists(k1, k2, |v| Ok::<R, Never>(f(v)))
271			.expect("`Never` can not be constructed; qed")
272	}
273
274	fn try_mutate<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E>
275	where
276		KArg1: EncodeLike<K1>,
277		KArg2: EncodeLike<K2>,
278		F: FnOnce(&mut Self::Query) -> Result<R, E>,
279	{
280		let final_key = Self::storage_double_map_final_key(k1, k2);
281		let mut val = G::from_optional_value_to_query(unhashed::get(final_key.as_ref()));
282
283		let ret = f(&mut val);
284		if ret.is_ok() {
285			match G::from_query_to_optional_value(val) {
286				Some(ref val) => unhashed::put(final_key.as_ref(), val),
287				None => unhashed::kill(final_key.as_ref()),
288			}
289		}
290		ret
291	}
292
293	fn try_mutate_exists<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E>
294	where
295		KArg1: EncodeLike<K1>,
296		KArg2: EncodeLike<K2>,
297		F: FnOnce(&mut Option<V>) -> Result<R, E>,
298	{
299		let final_key = Self::storage_double_map_final_key(k1, k2);
300		let mut val = unhashed::get(final_key.as_ref());
301
302		let ret = f(&mut val);
303		if ret.is_ok() {
304			match val {
305				Some(ref val) => unhashed::put(final_key.as_ref(), val),
306				None => unhashed::kill(final_key.as_ref()),
307			}
308		}
309		ret
310	}
311
312	fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
313	where
314		KArg1: EncodeLike<K1>,
315		KArg2: EncodeLike<K2>,
316		Item: Encode,
317		EncodeLikeItem: EncodeLike<Item>,
318		V: StorageAppend<Item>,
319	{
320		let final_key = Self::storage_double_map_final_key(k1, k2);
321		sp_io::storage::append(&final_key, item.encode());
322	}
323
324	fn migrate_keys<
325		OldHasher1: StorageHasher,
326		OldHasher2: StorageHasher,
327		KeyArg1: EncodeLike<K1>,
328		KeyArg2: EncodeLike<K2>,
329	>(
330		key1: KeyArg1,
331		key2: KeyArg2,
332	) -> Option<V> {
333		let old_key = {
334			let storage_prefix = storage_prefix(Self::pallet_prefix(), Self::storage_prefix());
335
336			let key1_hashed = key1.using_encoded(OldHasher1::hash);
337			let key2_hashed = key2.using_encoded(OldHasher2::hash);
338
339			let mut final_key = Vec::with_capacity(
340				storage_prefix.len() + key1_hashed.as_ref().len() + key2_hashed.as_ref().len(),
341			);
342
343			final_key.extend_from_slice(&storage_prefix);
344			final_key.extend_from_slice(key1_hashed.as_ref());
345			final_key.extend_from_slice(key2_hashed.as_ref());
346
347			final_key
348		};
349		unhashed::take(old_key.as_ref()).inspect(|value| {
350			unhashed::put(Self::storage_double_map_final_key(key1, key2).as_ref(), &value);
351		})
352	}
353}
354
355impl<K1: FullCodec, K2: FullCodec, V: FullCodec, G: StorageDoubleMap<K1, K2, V>>
356	storage::IterableStorageDoubleMap<K1, K2, V> for G
357where
358	G::Hasher1: ReversibleStorageHasher,
359	G::Hasher2: ReversibleStorageHasher,
360{
361	type PartialKeyIterator = KeyPrefixIterator<K2>;
362	type PrefixIterator = PrefixIterator<(K2, V)>;
363	type FullKeyIterator = KeyPrefixIterator<(K1, K2)>;
364	type Iterator = PrefixIterator<(K1, K2, V)>;
365
366	fn iter_prefix(k1: impl EncodeLike<K1>) -> Self::PrefixIterator {
367		let prefix = G::storage_double_map_final_key1(k1);
368		Self::PrefixIterator {
369			prefix: prefix.clone(),
370			previous_key: prefix,
371			drain: false,
372			closure: |raw_key_without_prefix, mut raw_value| {
373				let mut key_material = G::Hasher2::reverse(raw_key_without_prefix);
374				Ok((K2::decode(&mut key_material)?, V::decode(&mut raw_value)?))
375			},
376			phantom: Default::default(),
377		}
378	}
379
380	fn iter_prefix_from(
381		k1: impl EncodeLike<K1>,
382		starting_raw_key: Vec<u8>,
383	) -> Self::PrefixIterator {
384		let mut iter = Self::iter_prefix(k1);
385		iter.set_last_raw_key(starting_raw_key);
386		iter
387	}
388
389	fn iter_key_prefix(k1: impl EncodeLike<K1>) -> Self::PartialKeyIterator {
390		let prefix = G::storage_double_map_final_key1(k1);
391		Self::PartialKeyIterator {
392			prefix: prefix.clone(),
393			previous_key: prefix,
394			drain: false,
395			closure: |raw_key_without_prefix| {
396				let mut key_material = G::Hasher2::reverse(raw_key_without_prefix);
397				K2::decode(&mut key_material)
398			},
399		}
400	}
401
402	fn iter_key_prefix_from(
403		k1: impl EncodeLike<K1>,
404		starting_raw_key: Vec<u8>,
405	) -> Self::PartialKeyIterator {
406		let mut iter = Self::iter_key_prefix(k1);
407		iter.set_last_raw_key(starting_raw_key);
408		iter
409	}
410
411	fn drain_prefix(k1: impl EncodeLike<K1>) -> Self::PrefixIterator {
412		let mut iterator = Self::iter_prefix(k1);
413		iterator.drain = true;
414		iterator
415	}
416
417	fn iter() -> Self::Iterator {
418		let prefix = G::prefix_hash().to_vec();
419		Self::Iterator {
420			prefix: prefix.clone(),
421			previous_key: prefix,
422			drain: false,
423			closure: |raw_key_without_prefix, mut raw_value| {
424				let mut k1_k2_material = G::Hasher1::reverse(raw_key_without_prefix);
425				let k1 = K1::decode(&mut k1_k2_material)?;
426				let mut k2_material = G::Hasher2::reverse(k1_k2_material);
427				let k2 = K2::decode(&mut k2_material)?;
428				Ok((k1, k2, V::decode(&mut raw_value)?))
429			},
430			phantom: Default::default(),
431		}
432	}
433
434	fn iter_from(starting_raw_key: Vec<u8>) -> Self::Iterator {
435		let mut iter = Self::iter();
436		iter.set_last_raw_key(starting_raw_key);
437		iter
438	}
439
440	fn iter_keys() -> Self::FullKeyIterator {
441		let prefix = G::prefix_hash().to_vec();
442		Self::FullKeyIterator {
443			prefix: prefix.clone(),
444			previous_key: prefix,
445			drain: false,
446			closure: |raw_key_without_prefix| {
447				let mut k1_k2_material = G::Hasher1::reverse(raw_key_without_prefix);
448				let k1 = K1::decode(&mut k1_k2_material)?;
449				let mut k2_material = G::Hasher2::reverse(k1_k2_material);
450				let k2 = K2::decode(&mut k2_material)?;
451				Ok((k1, k2))
452			},
453		}
454	}
455
456	fn iter_keys_from(starting_raw_key: Vec<u8>) -> Self::FullKeyIterator {
457		let mut iter = Self::iter_keys();
458		iter.set_last_raw_key(starting_raw_key);
459		iter
460	}
461
462	fn drain() -> Self::Iterator {
463		let mut iterator = Self::iter();
464		iterator.drain = true;
465		iterator
466	}
467
468	fn translate<O: Decode, F: FnMut(K1, K2, O) -> Option<V>>(mut f: F) {
469		let prefix = G::prefix_hash().to_vec();
470		let mut previous_key = prefix.clone();
471		while let Some(next) =
472			sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
473		{
474			previous_key = next;
475			let value = match unhashed::get::<O>(&previous_key) {
476				Some(value) => value,
477				None => {
478					log::error!("Invalid translate: fail to decode old value");
479					continue
480				},
481			};
482			let mut key_material = G::Hasher1::reverse(&previous_key[prefix.len()..]);
483			let key1 = match K1::decode(&mut key_material) {
484				Ok(key1) => key1,
485				Err(_) => {
486					log::error!("Invalid translate: fail to decode key1");
487					continue
488				},
489			};
490
491			let mut key2_material = G::Hasher2::reverse(key_material);
492			let key2 = match K2::decode(&mut key2_material) {
493				Ok(key2) => key2,
494				Err(_) => {
495					log::error!("Invalid translate: fail to decode key2");
496					continue
497				},
498			};
499
500			match f(key1, key2, value) {
501				Some(new) => unhashed::put::<V>(&previous_key, &new),
502				None => unhashed::kill(&previous_key),
503			}
504		}
505	}
506}
507
508/// Test iterators for StorageDoubleMap
509#[cfg(test)]
510mod test_iterators {
511	use crate::{
512		hash::StorageHasher,
513		storage::{
514			generator::{tests::*, StorageDoubleMap},
515			unhashed,
516		},
517	};
518	use alloc::vec;
519	use codec::Encode;
520
521	#[test]
522	fn double_map_iter_from() {
523		sp_io::TestExternalities::default().execute_with(|| {
524			use crate::hash::Identity;
525			#[crate::storage_alias]
526			type MyDoubleMap = StorageDoubleMap<MyModule, Identity, u64, Identity, u64, u64>;
527
528			MyDoubleMap::insert(1, 10, 100);
529			MyDoubleMap::insert(1, 21, 201);
530			MyDoubleMap::insert(1, 31, 301);
531			MyDoubleMap::insert(1, 41, 401);
532			MyDoubleMap::insert(2, 20, 200);
533			MyDoubleMap::insert(3, 30, 300);
534			MyDoubleMap::insert(4, 40, 400);
535			MyDoubleMap::insert(5, 50, 500);
536
537			let starting_raw_key = MyDoubleMap::storage_double_map_final_key(1, 21);
538			let iter = MyDoubleMap::iter_key_prefix_from(1, starting_raw_key);
539			assert_eq!(iter.collect::<Vec<_>>(), vec![31, 41]);
540
541			let starting_raw_key = MyDoubleMap::storage_double_map_final_key(1, 31);
542			let iter = MyDoubleMap::iter_prefix_from(1, starting_raw_key);
543			assert_eq!(iter.collect::<Vec<_>>(), vec![(41, 401)]);
544
545			let starting_raw_key = MyDoubleMap::storage_double_map_final_key(2, 20);
546			let iter = MyDoubleMap::iter_keys_from(starting_raw_key);
547			assert_eq!(iter.collect::<Vec<_>>(), vec![(3, 30), (4, 40), (5, 50)]);
548
549			let starting_raw_key = MyDoubleMap::storage_double_map_final_key(3, 30);
550			let iter = MyDoubleMap::iter_from(starting_raw_key);
551			assert_eq!(iter.collect::<Vec<_>>(), vec![(4, 40, 400), (5, 50, 500)]);
552		});
553	}
554
555	#[test]
556	fn double_map_reversible_reversible_iteration() {
557		sp_io::TestExternalities::default().execute_with(|| {
558			type DoubleMap = self::frame_system::DoubleMap<Runtime>;
559
560			// All map iterator
561			let prefix = DoubleMap::prefix_hash().to_vec();
562
563			unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
564			unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
565
566			for i in 0..4 {
567				DoubleMap::insert(i as u16, i as u32, i as u64);
568			}
569
570			assert_eq!(
571				DoubleMap::iter().collect::<Vec<_>>(),
572				vec![(3, 3, 3), (0, 0, 0), (2, 2, 2), (1, 1, 1)],
573			);
574
575			assert_eq!(
576				DoubleMap::iter_keys().collect::<Vec<_>>(),
577				vec![(3, 3), (0, 0), (2, 2), (1, 1)],
578			);
579
580			assert_eq!(DoubleMap::iter_values().collect::<Vec<_>>(), vec![3, 0, 2, 1]);
581
582			assert_eq!(
583				DoubleMap::drain().collect::<Vec<_>>(),
584				vec![(3, 3, 3), (0, 0, 0), (2, 2, 2), (1, 1, 1)],
585			);
586
587			assert_eq!(DoubleMap::iter().collect::<Vec<_>>(), vec![]);
588			assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
589			assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
590
591			// Prefix iterator
592			let k1 = 3 << 8;
593			let prefix = DoubleMap::storage_double_map_final_key1(k1);
594
595			unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
596			unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
597
598			for i in 0..4 {
599				DoubleMap::insert(k1, i as u32, i as u64);
600			}
601
602			assert_eq!(
603				DoubleMap::iter_prefix(k1).collect::<Vec<_>>(),
604				vec![(1, 1), (2, 2), (0, 0), (3, 3)],
605			);
606
607			assert_eq!(DoubleMap::iter_key_prefix(k1).collect::<Vec<_>>(), vec![1, 2, 0, 3]);
608
609			assert_eq!(DoubleMap::iter_prefix_values(k1).collect::<Vec<_>>(), vec![1, 2, 0, 3]);
610
611			assert_eq!(
612				DoubleMap::drain_prefix(k1).collect::<Vec<_>>(),
613				vec![(1, 1), (2, 2), (0, 0), (3, 3)],
614			);
615
616			assert_eq!(DoubleMap::iter_prefix(k1).collect::<Vec<_>>(), vec![]);
617			assert_eq!(unhashed::get(&key_before_prefix(prefix.clone())), Some(1u64));
618			assert_eq!(unhashed::get(&key_after_prefix(prefix.clone())), Some(1u64));
619
620			// Translate
621			let prefix = DoubleMap::prefix_hash().to_vec();
622
623			unhashed::put(&key_before_prefix(prefix.clone()), &1u64);
624			unhashed::put(&key_after_prefix(prefix.clone()), &1u64);
625			for i in 0..4 {
626				DoubleMap::insert(i as u16, i as u32, i as u64);
627			}
628
629			// Wrong key1
630			unhashed::put(&[prefix.clone(), vec![1, 2, 3]].concat(), &3u64.encode());
631
632			// Wrong key2
633			unhashed::put(
634				&[prefix.clone(), crate::Blake2_128Concat::hash(&1u16.encode())].concat(),
635				&3u64.encode(),
636			);
637
638			// Wrong value
639			unhashed::put(
640				&[
641					prefix.clone(),
642					crate::Blake2_128Concat::hash(&1u16.encode()),
643					crate::Twox64Concat::hash(&2u32.encode()),
644				]
645				.concat(),
646				&vec![1],
647			);
648
649			DoubleMap::translate(|_k1, _k2, v: u64| Some(v * 2));
650			assert_eq!(
651				DoubleMap::iter().collect::<Vec<_>>(),
652				vec![(3, 3, 6), (0, 0, 0), (2, 2, 4), (1, 1, 2)],
653			);
654		})
655	}
656}