referrerpolicy=no-referrer-when-downgrade

frame_support/storage/types/
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
18//! Storage map type. Implements StorageDoubleMap, StorageIterableDoubleMap,
19//! StoragePrefixedDoubleMap traits and their methods directly.
20
21use crate::{
22	storage::{
23		types::{OptionQuery, QueryKindTrait, StorageEntryMetadataBuilder},
24		KeyLenOf, StorageAppend, StorageDecodeLength, StoragePrefixedMap, StorageTryAppend,
25	},
26	traits::{Get, GetDefault, StorageInfo, StorageInstance},
27	StorageHasher, Twox128,
28};
29use alloc::{vec, vec::Vec};
30use codec::{Decode, Encode, EncodeLike, FullCodec, MaxEncodedLen};
31use frame_support::storage::StorageDecodeNonDedupLength;
32use sp_arithmetic::traits::SaturatedConversion;
33use sp_metadata_ir::{StorageEntryMetadataIR, StorageEntryTypeIR};
34
35/// A type representing a *double map* in storage. This structure associates a pair of keys with a
36/// value of a specified type stored on-chain.
37///
38/// A double map with keys `k1` and `k2` can be likened to a
39/// [`StorageMap`](frame_support::storage::types::StorageMap) with a key of type `(k1, k2)`.
40/// However, a double map offers functions specific to each key, enabling partial iteration and
41/// deletion based on one key alone.
42///
43/// Also, conceptually, a double map is a special case of a
44/// [`StorageNMap`](frame_support::storage::types::StorageNMap) using two keys.
45///
46/// For general information regarding the `#[pallet::storage]` attribute, refer to
47/// [`crate::pallet_macros::storage`].
48///
49/// # Examples
50///
51/// ### Kitchen-sink
52///
53/// ```
54/// #[frame_support::pallet]
55/// mod pallet {
56/// # 	use frame_support::pallet_prelude::*;
57/// # 	#[pallet::config]
58/// # 	pub trait Config: frame_system::Config {}
59/// # 	#[pallet::pallet]
60/// # 	pub struct Pallet<T>(_);
61///     /// A kitchen-sink StorageDoubleMap, with all possible additional attributes.
62///     #[pallet::storage]
63///     #[pallet::getter(fn foo)]
64///     #[pallet::storage_prefix = "OtherFoo"]
65///     #[pallet::unbounded]
66///     pub type Foo<T> = StorageDoubleMap<
67/// 		_,
68///         Blake2_128Concat,
69///         u8,
70///         Twox64Concat,
71///         u16,
72///         u32,
73///         ValueQuery
74///     >;
75///
76/// 	/// Alternative named syntax.
77///     #[pallet::storage]
78///     pub type Bar<T> = StorageDoubleMap<
79///         Hasher1 = Blake2_128Concat,
80///         Key1 = u8,
81///         Hasher2 = Twox64Concat,
82///         Key2 = u16,
83///         Value = u32,
84///         QueryKind = ValueQuery
85///     >;
86/// }
87/// ```
88///
89/// ### Partial Iteration & Removal
90///
91/// When `Hasher1` and `Hasher2` implement the
92/// [`ReversibleStorageHasher`](frame_support::ReversibleStorageHasher) trait, the first key `k1`
93/// can be used to partially iterate over keys and values of the double map, and to delete items.
94#[doc = docify::embed!("src/storage/types/double_map.rs", example_double_map_partial_operations)]
95pub struct StorageDoubleMap<
96	Prefix,
97	Hasher1,
98	Key1,
99	Hasher2,
100	Key2,
101	Value,
102	QueryKind = OptionQuery,
103	OnEmpty = GetDefault,
104	MaxValues = GetDefault,
105>(
106	core::marker::PhantomData<(
107		Prefix,
108		Hasher1,
109		Key1,
110		Hasher2,
111		Key2,
112		Value,
113		QueryKind,
114		OnEmpty,
115		MaxValues,
116	)>,
117);
118
119impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues> Get<u32>
120	for KeyLenOf<
121		StorageDoubleMap<
122			Prefix,
123			Hasher1,
124			Key1,
125			Hasher2,
126			Key2,
127			Value,
128			QueryKind,
129			OnEmpty,
130			MaxValues,
131		>,
132	>
133where
134	Prefix: StorageInstance,
135	Hasher1: crate::hash::StorageHasher,
136	Hasher2: crate::hash::StorageHasher,
137	Key1: MaxEncodedLen,
138	Key2: MaxEncodedLen,
139{
140	fn get() -> u32 {
141		// The `max_len` of both key hashes plus the pallet prefix and storage prefix (which both
142		// are hashed with `Twox128`).
143		let z =
144			Hasher1::max_len::<Key1>() + Hasher2::max_len::<Key2>() + Twox128::max_len::<()>() * 2;
145		z as u32
146	}
147}
148
149impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
150	crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>
151	for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
152where
153	Prefix: StorageInstance,
154	Hasher1: crate::hash::StorageHasher,
155	Hasher2: crate::hash::StorageHasher,
156	Key1: FullCodec,
157	Key2: FullCodec,
158	Value: FullCodec,
159	QueryKind: QueryKindTrait<Value, OnEmpty>,
160	OnEmpty: Get<QueryKind::Query> + 'static,
161	MaxValues: Get<Option<u32>>,
162{
163	type Query = QueryKind::Query;
164	type Hasher1 = Hasher1;
165	type Hasher2 = Hasher2;
166	fn pallet_prefix() -> &'static [u8] {
167		Prefix::pallet_prefix().as_bytes()
168	}
169
170	fn storage_prefix() -> &'static [u8] {
171		Prefix::STORAGE_PREFIX.as_bytes()
172	}
173	fn prefix_hash() -> [u8; 32] {
174		Prefix::prefix_hash()
175	}
176
177	fn from_optional_value_to_query(v: Option<Value>) -> Self::Query {
178		QueryKind::from_optional_value_to_query(v)
179	}
180	fn from_query_to_optional_value(v: Self::Query) -> Option<Value> {
181		QueryKind::from_query_to_optional_value(v)
182	}
183}
184
185impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
186	StoragePrefixedMap<Value>
187	for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
188where
189	Prefix: StorageInstance,
190	Hasher1: crate::hash::StorageHasher,
191	Hasher2: crate::hash::StorageHasher,
192	Key1: FullCodec,
193	Key2: FullCodec,
194	Value: FullCodec,
195	QueryKind: QueryKindTrait<Value, OnEmpty>,
196	OnEmpty: Get<QueryKind::Query> + 'static,
197	MaxValues: Get<Option<u32>>,
198{
199	fn pallet_prefix() -> &'static [u8] {
200		<Self as crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>>::pallet_prefix()
201	}
202	fn storage_prefix() -> &'static [u8] {
203		<Self as crate::storage::generator::StorageDoubleMap<Key1, Key2, Value>>::storage_prefix()
204	}
205}
206
207impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
208	StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
209where
210	Prefix: StorageInstance,
211	Hasher1: crate::hash::StorageHasher,
212	Hasher2: crate::hash::StorageHasher,
213	Key1: FullCodec,
214	Key2: FullCodec,
215	Value: FullCodec,
216	QueryKind: QueryKindTrait<Value, OnEmpty>,
217	OnEmpty: Get<QueryKind::Query> + 'static,
218	MaxValues: Get<Option<u32>>,
219{
220	/// Get the storage key used to fetch a value corresponding to a specific key.
221	pub fn hashed_key_for<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Vec<u8>
222	where
223		KArg1: EncodeLike<Key1>,
224		KArg2: EncodeLike<Key2>,
225	{
226		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::hashed_key_for(k1, k2)
227	}
228
229	/// Does the value (explicitly) exist in storage?
230	pub fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool
231	where
232		KArg1: EncodeLike<Key1>,
233		KArg2: EncodeLike<Key2>,
234	{
235		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::contains_key(k1, k2)
236	}
237
238	/// Load the value associated with the given key from the double map.
239	pub fn get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> QueryKind::Query
240	where
241		KArg1: EncodeLike<Key1>,
242		KArg2: EncodeLike<Key2>,
243	{
244		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::get(k1, k2)
245	}
246
247	/// Try to get the value for the given key from the double map.
248	///
249	/// Returns `Ok` if it exists, `Err` if not.
250	pub fn try_get<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> Result<Value, ()>
251	where
252		KArg1: EncodeLike<Key1>,
253		KArg2: EncodeLike<Key2>,
254	{
255		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::try_get(k1, k2)
256	}
257
258	/// Store or remove the value to be associated with `key` so that `get` returns the `query`.
259	pub fn set<KArg1: EncodeLike<Key1>, KArg2: EncodeLike<Key2>>(
260		k1: KArg1,
261		k2: KArg2,
262		q: QueryKind::Query,
263	) {
264		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::set(k1, k2, q)
265	}
266
267	/// Take a value from storage, removing it afterwards.
268	pub fn take<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> QueryKind::Query
269	where
270		KArg1: EncodeLike<Key1>,
271		KArg2: EncodeLike<Key2>,
272	{
273		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::take(k1, k2)
274	}
275
276	/// Swap the values of two key-pairs.
277	pub fn swap<XKArg1, XKArg2, YKArg1, YKArg2>(
278		x_k1: XKArg1,
279		x_k2: XKArg2,
280		y_k1: YKArg1,
281		y_k2: YKArg2,
282	) where
283		XKArg1: EncodeLike<Key1>,
284		XKArg2: EncodeLike<Key2>,
285		YKArg1: EncodeLike<Key1>,
286		YKArg2: EncodeLike<Key2>,
287	{
288		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::swap(x_k1, x_k2, y_k1, y_k2)
289	}
290
291	/// Store a value to be associated with the given keys from the double map.
292	pub fn insert<KArg1, KArg2, VArg>(k1: KArg1, k2: KArg2, val: VArg)
293	where
294		KArg1: EncodeLike<Key1>,
295		KArg2: EncodeLike<Key2>,
296		VArg: EncodeLike<Value>,
297	{
298		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::insert(k1, k2, val)
299	}
300
301	/// Remove the value under the given keys.
302	pub fn remove<KArg1, KArg2>(k1: KArg1, k2: KArg2)
303	where
304		KArg1: EncodeLike<Key1>,
305		KArg2: EncodeLike<Key2>,
306	{
307		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::remove(k1, k2)
308	}
309
310	/// Remove all values under `k1` in the overlay and up to `limit` in the
311	/// backend.
312	///
313	/// All values in the client overlay will be deleted, if there is some `limit` then up to
314	/// `limit` values are deleted from the client backend, if `limit` is none then all values in
315	/// the client backend are deleted.
316	///
317	/// # Note
318	///
319	/// Calling this multiple times per block with a `limit` set leads always to the same keys being
320	/// removed and the same result being returned. This happens because the keys to delete in the
321	/// overlay are not taken into account when deleting keys in the backend.
322	#[deprecated = "Use `clear_prefix` instead"]
323	pub fn remove_prefix<KArg1>(k1: KArg1, limit: Option<u32>) -> sp_io::KillStorageResult
324	where
325		KArg1: ?Sized + EncodeLike<Key1>,
326	{
327		#[allow(deprecated)]
328		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::remove_prefix(k1, limit)
329	}
330
331	/// Attempt to remove items from the map matching a `first_key` prefix.
332	///
333	/// Returns [`MultiRemovalResults`](sp_io::MultiRemovalResults) to inform about the result. Once
334	/// the resultant `maybe_cursor` field is `None`, then no further items remain to be deleted.
335	///
336	/// NOTE: After the initial call for any given map, it is important that no further items
337	/// are inserted into the map which match the `first_key`. If so, then the map may not be
338	/// empty when the resultant `maybe_cursor` is `None`.
339	///
340	/// # Limit
341	///
342	/// A `limit` must always be provided through in order to cap the maximum
343	/// amount of deletions done in a single call. This is one fewer than the
344	/// maximum number of backend iterations which may be done by this operation and as such
345	/// represents the maximum number of backend deletions which may happen. A `limit` of zero
346	/// implies that no keys will be deleted, though there may be a single iteration done.
347	///
348	/// # Cursor
349	///
350	/// A *cursor* may be passed in to this operation with `maybe_cursor`. `None` should only be
351	/// passed once (in the initial call) for any given storage map and `first_key`. Subsequent
352	/// calls operating on the same map/`first_key` should always pass `Some`, and this should be
353	/// equal to the previous call result's `maybe_cursor` field.
354	pub fn clear_prefix<KArg1>(
355		first_key: KArg1,
356		limit: u32,
357		maybe_cursor: Option<&[u8]>,
358	) -> sp_io::MultiRemovalResults
359	where
360		KArg1: ?Sized + EncodeLike<Key1>,
361	{
362		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::clear_prefix(
363			first_key,
364			limit,
365			maybe_cursor,
366		)
367	}
368
369	/// Iterate over values that share the first key.
370	pub fn iter_prefix_values<KArg1>(k1: KArg1) -> crate::storage::PrefixIterator<Value>
371	where
372		KArg1: ?Sized + EncodeLike<Key1>,
373	{
374		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::iter_prefix_values(k1)
375	}
376
377	/// Mutate the value under the given keys.
378	pub fn mutate<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
379	where
380		KArg1: EncodeLike<Key1>,
381		KArg2: EncodeLike<Key2>,
382		F: FnOnce(&mut QueryKind::Query) -> R,
383	{
384		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::mutate(k1, k2, f)
385	}
386
387	/// Mutate the value under the given keys when the closure returns `Ok`.
388	pub fn try_mutate<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E>
389	where
390		KArg1: EncodeLike<Key1>,
391		KArg2: EncodeLike<Key2>,
392		F: FnOnce(&mut QueryKind::Query) -> Result<R, E>,
393	{
394		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::try_mutate(k1, k2, f)
395	}
396
397	/// Mutate the value under the given keys. Deletes the item if mutated to a `None`.
398	pub fn mutate_exists<KArg1, KArg2, R, F>(k1: KArg1, k2: KArg2, f: F) -> R
399	where
400		KArg1: EncodeLike<Key1>,
401		KArg2: EncodeLike<Key2>,
402		F: FnOnce(&mut Option<Value>) -> R,
403	{
404		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::mutate_exists(k1, k2, f)
405	}
406
407	/// Mutate the item, only if an `Ok` value is returned. Deletes the item if mutated to a `None`.
408	/// `f` will always be called with an option representing if the storage item exists (`Some<V>`)
409	/// or if the storage item does not exist (`None`), independent of the `QueryType`.
410	pub fn try_mutate_exists<KArg1, KArg2, R, E, F>(k1: KArg1, k2: KArg2, f: F) -> Result<R, E>
411	where
412		KArg1: EncodeLike<Key1>,
413		KArg2: EncodeLike<Key2>,
414		F: FnOnce(&mut Option<Value>) -> Result<R, E>,
415	{
416		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::try_mutate_exists(k1, k2, f)
417	}
418
419	/// Append the given item to the value in the storage.
420	///
421	/// `Value` is required to implement [`StorageAppend`].
422	///
423	/// # Warning
424	///
425	/// If the storage item is not encoded properly, the storage will be overwritten
426	/// and set to `[item]`. Any default value set for the storage item will be ignored
427	/// on overwrite.
428	pub fn append<Item, EncodeLikeItem, KArg1, KArg2>(k1: KArg1, k2: KArg2, item: EncodeLikeItem)
429	where
430		KArg1: EncodeLike<Key1>,
431		KArg2: EncodeLike<Key2>,
432		Item: Encode,
433		EncodeLikeItem: EncodeLike<Item>,
434		Value: StorageAppend<Item>,
435	{
436		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::append(k1, k2, item)
437	}
438
439	/// Read the length of the storage value without decoding the entire value under the
440	/// given `key1` and `key2`.
441	///
442	/// `Value` is required to implement [`StorageDecodeLength`].
443	///
444	/// If the value does not exists or it fails to decode the length, `None` is returned.
445	/// Otherwise `Some(len)` is returned.
446	///
447	/// # Warning
448	///
449	/// `None` does not mean that `get()` does not return a value. The default value is completely
450	/// ignored by this function.
451	pub fn decode_len<KArg1, KArg2>(key1: KArg1, key2: KArg2) -> Option<usize>
452	where
453		KArg1: EncodeLike<Key1>,
454		KArg2: EncodeLike<Key2>,
455		Value: StorageDecodeLength,
456	{
457		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::decode_len(key1, key2)
458	}
459
460	/// Read the length of the storage value without decoding the entire value.
461	///
462	/// `Value` is required to implement [`StorageDecodeNonDedupLength`].
463	///
464	/// If the value does not exists or it fails to decode the length, `None` is returned.
465	/// Otherwise `Some(len)` is returned.
466	///
467	/// # Warning
468	///
469	///  - `None` does not mean that `get()` does not return a value. The default value is
470	///    completely
471	/// ignored by this function.
472	///
473	/// - The value returned is the non-deduplicated length of the underlying Vector in storage.This
474	/// means that any duplicate items are included.
475	pub fn decode_non_dedup_len<KArg1, KArg2>(key1: KArg1, key2: KArg2) -> Option<usize>
476	where
477		KArg1: EncodeLike<Key1>,
478		KArg2: EncodeLike<Key2>,
479		Value: StorageDecodeNonDedupLength,
480	{
481		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::decode_non_dedup_len(
482			key1, key2,
483		)
484	}
485
486	/// Migrate an item with the given `key1` and `key2` from defunct `OldHasher1` and
487	/// `OldHasher2` to the current hashers.
488	///
489	/// If the key doesn't exist, then it's a no-op. If it does, then it returns its value.
490	pub fn migrate_keys<
491		OldHasher1: crate::StorageHasher,
492		OldHasher2: crate::StorageHasher,
493		KeyArg1: EncodeLike<Key1>,
494		KeyArg2: EncodeLike<Key2>,
495	>(
496		key1: KeyArg1,
497		key2: KeyArg2,
498	) -> Option<Value> {
499		<Self as crate::storage::StorageDoubleMap<Key1, Key2, Value>>::migrate_keys::<
500			OldHasher1,
501			OldHasher2,
502			_,
503			_,
504		>(key1, key2)
505	}
506
507	/// Remove all values in the overlay and up to `limit` in the backend.
508	///
509	/// All values in the client overlay will be deleted, if there is some `limit` then up to
510	/// `limit` values are deleted from the client backend, if `limit` is none then all values in
511	/// the client backend are deleted.
512	///
513	/// # Note
514	///
515	/// Calling this multiple times per block with a `limit` set leads always to the same keys being
516	/// removed and the same result being returned. This happens because the keys to delete in the
517	/// overlay are not taken into account when deleting keys in the backend.
518	#[deprecated = "Use `clear` instead"]
519	pub fn remove_all(limit: Option<u32>) -> sp_io::KillStorageResult {
520		#[allow(deprecated)]
521		<Self as crate::storage::StoragePrefixedMap<Value>>::remove_all(limit)
522	}
523
524	/// Attempt to remove all items from the map.
525	///
526	/// Returns [`MultiRemovalResults`](sp_io::MultiRemovalResults) to inform about the result. Once
527	/// the resultant `maybe_cursor` field is `None`, then no further items remain to be deleted.
528	///
529	/// NOTE: After the initial call for any given map, it is important that no further items
530	/// are inserted into the map. If so, then the map may not be empty when the resultant
531	/// `maybe_cursor` is `None`.
532	///
533	/// # Limit
534	///
535	/// A `limit` must always be provided through in order to cap the maximum
536	/// amount of deletions done in a single call. This is one fewer than the
537	/// maximum number of backend iterations which may be done by this operation and as such
538	/// represents the maximum number of backend deletions which may happen.A `limit` of zero
539	/// implies that no keys will be deleted, though there may be a single iteration done.
540	///
541	/// # Cursor
542	///
543	/// A *cursor* may be passed in to this operation with `maybe_cursor`. `None` should only be
544	/// passed once (in the initial call) for any given storage map. Subsequent calls
545	/// operating on the same map should always pass `Some`, and this should be equal to the
546	/// previous call result's `maybe_cursor` field.
547	pub fn clear(limit: u32, maybe_cursor: Option<&[u8]>) -> sp_io::MultiRemovalResults {
548		<Self as crate::storage::StoragePrefixedMap<Value>>::clear(limit, maybe_cursor)
549	}
550
551	/// Iter over all value of the storage.
552	///
553	/// NOTE: If a value failed to decode because storage is corrupted then it is skipped.
554	pub fn iter_values() -> crate::storage::PrefixIterator<Value> {
555		<Self as crate::storage::StoragePrefixedMap<Value>>::iter_values()
556	}
557
558	/// Translate the values of all elements by a function `f`, in the map in no particular order.
559	/// By returning `None` from `f` for an element, you'll remove it from the map.
560	///
561	/// NOTE: If a value fail to decode because storage is corrupted then it is skipped.
562	///
563	/// # Warning
564	///
565	/// This function must be used with care, before being updated the storage still contains the
566	/// old type, thus other calls (such as `get`) will fail at decoding it.
567	///
568	/// # Usage
569	///
570	/// This would typically be called inside the module implementation of on_runtime_upgrade.
571	pub fn translate_values<OldValue: Decode, F: FnMut(OldValue) -> Option<Value>>(f: F) {
572		<Self as crate::storage::StoragePrefixedMap<Value>>::translate_values(f)
573	}
574
575	/// Try and append the given item to the value in the storage.
576	///
577	/// Is only available if `Value` of the storage implements [`StorageTryAppend`].
578	pub fn try_append<KArg1, KArg2, Item, EncodeLikeItem>(
579		key1: KArg1,
580		key2: KArg2,
581		item: EncodeLikeItem,
582	) -> Result<(), ()>
583	where
584		KArg1: EncodeLike<Key1> + Clone,
585		KArg2: EncodeLike<Key2> + Clone,
586		Item: Encode,
587		EncodeLikeItem: EncodeLike<Item>,
588		Value: StorageTryAppend<Item>,
589	{
590		<Self as crate::storage::TryAppendDoubleMap<Key1, Key2, Value, Item>>::try_append(
591			key1, key2, item,
592		)
593	}
594}
595
596impl<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
597	StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
598where
599	Prefix: StorageInstance,
600	Hasher1: crate::hash::StorageHasher + crate::ReversibleStorageHasher,
601	Hasher2: crate::hash::StorageHasher + crate::ReversibleStorageHasher,
602	Key1: FullCodec,
603	Key2: FullCodec,
604	Value: FullCodec,
605	QueryKind: QueryKindTrait<Value, OnEmpty>,
606	OnEmpty: Get<QueryKind::Query> + 'static,
607	MaxValues: Get<Option<u32>>,
608{
609	/// Enumerate all elements in the map with first key `k1` in no particular order.
610	///
611	/// If you add or remove values whose first key is `k1` to the map while doing this, you'll get
612	/// undefined results.
613	pub fn iter_prefix(k1: impl EncodeLike<Key1>) -> crate::storage::PrefixIterator<(Key2, Value)> {
614		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_prefix(k1)
615	}
616
617	/// Enumerate all elements in the map with first key `k1` after a specified `starting_raw_key`
618	/// in no particular order.
619	///
620	/// If you add or remove values whose first key is `k1` to the map while doing this, you'll get
621	/// undefined results.
622	pub fn iter_prefix_from(
623		k1: impl EncodeLike<Key1>,
624		starting_raw_key: Vec<u8>,
625	) -> crate::storage::PrefixIterator<(Key2, Value)> {
626		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_prefix_from(
627			k1,
628			starting_raw_key,
629		)
630	}
631
632	/// Enumerate all second keys `k2` in the map with the same first key `k1` in no particular
633	/// order.
634	///
635	/// If you add or remove values whose first key is `k1` to the map while doing this, you'll get
636	/// undefined results.
637	pub fn iter_key_prefix(k1: impl EncodeLike<Key1>) -> crate::storage::KeyPrefixIterator<Key2> {
638		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_key_prefix(k1)
639	}
640
641	/// Enumerate all second keys `k2` in the map with the same first key `k1` after a specified
642	/// `starting_raw_key` in no particular order.
643	///
644	/// If you add or remove values whose first key is `k1` to the map while doing this, you'll get
645	/// undefined results.
646	pub fn iter_key_prefix_from(
647		k1: impl EncodeLike<Key1>,
648		starting_raw_key: Vec<u8>,
649	) -> crate::storage::KeyPrefixIterator<Key2> {
650		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_key_prefix_from(
651			k1,
652			starting_raw_key,
653		)
654	}
655
656	/// Remove all elements from the map with first key `k1` and iterate through them in no
657	/// particular order.
658	///
659	/// If you add elements with first key `k1` to the map while doing this, you'll get undefined
660	/// results.
661	pub fn drain_prefix(
662		k1: impl EncodeLike<Key1>,
663	) -> crate::storage::PrefixIterator<(Key2, Value)> {
664		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::drain_prefix(k1)
665	}
666
667	/// Enumerate all elements in the map in no particular order.
668	///
669	/// If you add or remove values to the map while doing this, you'll get undefined results.
670	pub fn iter() -> crate::storage::PrefixIterator<(Key1, Key2, Value)> {
671		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter()
672	}
673
674	/// Enumerate all elements in the map after a specified `starting_raw_key` in no particular
675	/// order.
676	///
677	/// If you add or remove values to the map while doing this, you'll get undefined results.
678	pub fn iter_from(
679		starting_raw_key: Vec<u8>,
680	) -> crate::storage::PrefixIterator<(Key1, Key2, Value)> {
681		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_from(
682			starting_raw_key,
683		)
684	}
685
686	/// Enumerate all keys `k1` and `k2` in the map in no particular order.
687	///
688	/// If you add or remove values to the map while doing this, you'll get undefined results.
689	pub fn iter_keys() -> crate::storage::KeyPrefixIterator<(Key1, Key2)> {
690		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_keys()
691	}
692
693	/// Enumerate all keys `k1` and `k2` in the map after a specified `starting_raw_key` in no
694	/// particular order.
695	///
696	/// If you add or remove values to the map while doing this, you'll get undefined results.
697	pub fn iter_keys_from(
698		starting_raw_key: Vec<u8>,
699	) -> crate::storage::KeyPrefixIterator<(Key1, Key2)> {
700		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::iter_keys_from(
701			starting_raw_key,
702		)
703	}
704
705	/// Remove all elements from the map and iterate through them in no particular order.
706	///
707	/// If you add elements to the map while doing this, you'll get undefined results.
708	pub fn drain() -> crate::storage::PrefixIterator<(Key1, Key2, Value)> {
709		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::drain()
710	}
711
712	/// Translate the values of all elements by a function `f`, in the map in no particular order.
713	///
714	/// By returning `None` from `f` for an element, you'll remove it from the map.
715	///
716	/// NOTE: If a value fail to decode because storage is corrupted then it is skipped.
717	pub fn translate<O: Decode, F: FnMut(Key1, Key2, O) -> Option<Value>>(f: F) {
718		<Self as crate::storage::IterableStorageDoubleMap<Key1, Key2, Value>>::translate(f)
719	}
720}
721
722impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
723	StorageEntryMetadataBuilder
724	for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
725where
726	Prefix: StorageInstance,
727	Hasher1: crate::hash::StorageHasher,
728	Hasher2: crate::hash::StorageHasher,
729	Key1: FullCodec + scale_info::StaticTypeInfo,
730	Key2: FullCodec + scale_info::StaticTypeInfo,
731	Value: FullCodec + scale_info::StaticTypeInfo,
732	QueryKind: QueryKindTrait<Value, OnEmpty>,
733	OnEmpty: Get<QueryKind::Query> + 'static,
734	MaxValues: Get<Option<u32>>,
735{
736	fn build_metadata(
737		deprecation_status: sp_metadata_ir::ItemDeprecationInfoIR,
738		docs: Vec<&'static str>,
739		entries: &mut Vec<StorageEntryMetadataIR>,
740	) {
741		let docs = if cfg!(feature = "no-metadata-docs") { vec![] } else { docs };
742
743		let entry = StorageEntryMetadataIR {
744			name: Prefix::STORAGE_PREFIX,
745			modifier: QueryKind::METADATA,
746			ty: StorageEntryTypeIR::Map {
747				hashers: vec![Hasher1::METADATA, Hasher2::METADATA],
748				key: scale_info::meta_type::<(Key1, Key2)>(),
749				value: scale_info::meta_type::<Value>(),
750			},
751			default: OnEmpty::get().encode(),
752			docs,
753			deprecation_info: deprecation_status,
754		};
755
756		entries.push(entry);
757	}
758}
759
760impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
761	crate::traits::StorageInfoTrait
762	for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
763where
764	Prefix: StorageInstance,
765	Hasher1: crate::hash::StorageHasher,
766	Hasher2: crate::hash::StorageHasher,
767	Key1: FullCodec + MaxEncodedLen,
768	Key2: FullCodec + MaxEncodedLen,
769	Value: FullCodec + MaxEncodedLen,
770	QueryKind: QueryKindTrait<Value, OnEmpty>,
771	OnEmpty: Get<QueryKind::Query> + 'static,
772	MaxValues: Get<Option<u32>>,
773{
774	fn storage_info() -> Vec<StorageInfo> {
775		vec![StorageInfo {
776			pallet_name: Self::pallet_prefix().to_vec(),
777			storage_name: Self::storage_prefix().to_vec(),
778			prefix: Self::final_prefix().to_vec(),
779			max_values: MaxValues::get(),
780			max_size: Some(
781				Hasher1::max_len::<Key1>()
782					.saturating_add(Hasher2::max_len::<Key2>())
783					.saturating_add(Value::max_encoded_len())
784					.saturated_into(),
785			),
786		}]
787	}
788}
789
790/// It doesn't require to implement `MaxEncodedLen` and give no information for `max_size`.
791impl<Prefix, Hasher1, Hasher2, Key1, Key2, Value, QueryKind, OnEmpty, MaxValues>
792	crate::traits::PartialStorageInfoTrait
793	for StorageDoubleMap<Prefix, Hasher1, Key1, Hasher2, Key2, Value, QueryKind, OnEmpty, MaxValues>
794where
795	Prefix: StorageInstance,
796	Hasher1: crate::hash::StorageHasher,
797	Hasher2: crate::hash::StorageHasher,
798	Key1: FullCodec,
799	Key2: FullCodec,
800	Value: FullCodec,
801	QueryKind: QueryKindTrait<Value, OnEmpty>,
802	OnEmpty: Get<QueryKind::Query> + 'static,
803	MaxValues: Get<Option<u32>>,
804{
805	fn partial_storage_info() -> Vec<StorageInfo> {
806		vec![StorageInfo {
807			pallet_name: Self::pallet_prefix().to_vec(),
808			storage_name: Self::storage_prefix().to_vec(),
809			prefix: Self::final_prefix().to_vec(),
810			max_values: MaxValues::get(),
811			max_size: None,
812		}]
813	}
814}
815
816#[cfg(test)]
817mod test {
818	use super::*;
819	use crate::{hash::*, storage::types::ValueQuery};
820	use sp_io::{hashing::twox_128, TestExternalities};
821	use sp_metadata_ir::{StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR};
822	use std::collections::BTreeSet;
823
824	struct Prefix;
825	impl StorageInstance for Prefix {
826		fn pallet_prefix() -> &'static str {
827			"test"
828		}
829		const STORAGE_PREFIX: &'static str = "foo";
830	}
831
832	struct ADefault;
833	impl crate::traits::Get<u32> for ADefault {
834		fn get() -> u32 {
835			97
836		}
837	}
838
839	#[test]
840	fn keylenof_works() {
841		// Works with Blake2_128Concat and Twox64Concat.
842		type A = StorageDoubleMap<Prefix, Blake2_128Concat, u64, Twox64Concat, u32, u32>;
843		let size = 16 * 2 // Two Twox128
844			+ 16 + 8 // Blake2_128Concat = hash + key
845			+ 8 + 4; // Twox64Concat = hash + key
846		assert_eq!(KeyLenOf::<A>::get(), size);
847	}
848
849	#[test]
850	fn test() {
851		type A =
852			StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u32, OptionQuery>;
853		type AValueQueryWithAnOnEmpty = StorageDoubleMap<
854			Prefix,
855			Blake2_128Concat,
856			u16,
857			Twox64Concat,
858			u8,
859			u32,
860			ValueQuery,
861			ADefault,
862		>;
863		type B = StorageDoubleMap<Prefix, Blake2_256, u16, Twox128, u8, u32, ValueQuery>;
864		type C = StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, u8, ValueQuery>;
865		type WithLen = StorageDoubleMap<Prefix, Blake2_128Concat, u16, Twox64Concat, u8, Vec<u32>>;
866
867		TestExternalities::default().execute_with(|| {
868			let mut k: Vec<u8> = vec![];
869			k.extend(&twox_128(b"test"));
870			k.extend(&twox_128(b"foo"));
871			k.extend(&3u16.blake2_128_concat());
872			k.extend(&30u8.twox_64_concat());
873			assert_eq!(A::hashed_key_for(3, 30).to_vec(), k);
874
875			assert_eq!(A::contains_key(3, 30), false);
876			assert_eq!(A::get(3, 30), None);
877			assert_eq!(AValueQueryWithAnOnEmpty::get(3, 30), 97);
878
879			A::insert(3, 30, 10);
880			assert_eq!(A::contains_key(3, 30), true);
881			assert_eq!(A::get(3, 30), Some(10));
882			assert_eq!(AValueQueryWithAnOnEmpty::get(3, 30), 10);
883
884			A::swap(3, 30, 2, 20);
885			assert_eq!(A::contains_key(3, 30), false);
886			assert_eq!(A::contains_key(2, 20), true);
887			assert_eq!(A::get(3, 30), None);
888			assert_eq!(AValueQueryWithAnOnEmpty::get(3, 30), 97);
889			assert_eq!(A::get(2, 20), Some(10));
890			assert_eq!(AValueQueryWithAnOnEmpty::get(2, 20), 10);
891
892			A::remove(2, 20);
893			assert_eq!(A::contains_key(2, 20), false);
894			assert_eq!(A::get(2, 20), None);
895
896			AValueQueryWithAnOnEmpty::mutate(2, 20, |v| *v = *v * 2);
897			AValueQueryWithAnOnEmpty::mutate(2, 20, |v| *v = *v * 2);
898			assert_eq!(A::contains_key(2, 20), true);
899			assert_eq!(A::get(2, 20), Some(97 * 4));
900
901			A::remove(2, 20);
902			let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
903				*v = *v * 2;
904				Ok(())
905			});
906			let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
907				*v = *v * 2;
908				Ok(())
909			});
910			assert_eq!(A::contains_key(2, 20), true);
911			assert_eq!(A::get(2, 20), Some(97 * 4));
912
913			A::remove(2, 20);
914			let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate(2, 20, |v| {
915				*v = *v * 2;
916				Err(())
917			});
918			assert_eq!(A::contains_key(2, 20), false);
919
920			A::remove(2, 20);
921			AValueQueryWithAnOnEmpty::mutate_exists(2, 20, |v| {
922				assert!(v.is_none());
923				*v = Some(10);
924			});
925			assert_eq!(A::contains_key(2, 20), true);
926			assert_eq!(A::get(2, 20), Some(10));
927			AValueQueryWithAnOnEmpty::mutate_exists(2, 20, |v| {
928				*v = Some(v.unwrap() * 10);
929			});
930			assert_eq!(A::contains_key(2, 20), true);
931			assert_eq!(A::get(2, 20), Some(100));
932
933			A::remove(2, 20);
934			let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate_exists(2, 20, |v| {
935				assert!(v.is_none());
936				*v = Some(10);
937				Ok(())
938			});
939			assert_eq!(A::contains_key(2, 20), true);
940			assert_eq!(A::get(2, 20), Some(10));
941			let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate_exists(2, 20, |v| {
942				*v = Some(v.unwrap() * 10);
943				Ok(())
944			});
945			assert_eq!(A::contains_key(2, 20), true);
946			assert_eq!(A::get(2, 20), Some(100));
947			assert_eq!(A::try_get(2, 20), Ok(100));
948			let _: Result<(), ()> = AValueQueryWithAnOnEmpty::try_mutate_exists(2, 20, |v| {
949				*v = Some(v.unwrap() * 10);
950				Err(())
951			});
952			assert_eq!(A::contains_key(2, 20), true);
953			assert_eq!(A::get(2, 20), Some(100));
954
955			A::insert(2, 20, 10);
956			assert_eq!(A::take(2, 20), Some(10));
957			assert_eq!(A::contains_key(2, 20), false);
958			assert_eq!(AValueQueryWithAnOnEmpty::take(2, 20), 97);
959			assert_eq!(A::contains_key(2, 20), false);
960			assert_eq!(A::try_get(2, 20), Err(()));
961
962			B::insert(2, 20, 10);
963			assert_eq!(A::migrate_keys::<Blake2_256, Twox128, _, _>(2, 20), Some(10));
964			assert_eq!(A::contains_key(2, 20), true);
965			assert_eq!(A::get(2, 20), Some(10));
966
967			A::insert(3, 30, 10);
968			A::insert(4, 40, 10);
969			let _ = A::clear(u32::max_value(), None);
970			assert_eq!(A::contains_key(3, 30), false);
971			assert_eq!(A::contains_key(4, 40), false);
972
973			A::insert(3, 30, 10);
974			A::insert(4, 40, 10);
975			assert_eq!(A::iter_values().collect::<Vec<_>>(), vec![10, 10]);
976
977			C::insert(3, 30, 10);
978			C::insert(4, 40, 10);
979			A::translate_values::<u8, _>(|v| Some((v * 2).into()));
980			assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 20), (3, 30, 20)]);
981
982			A::insert(3, 30, 10);
983			A::insert(4, 40, 10);
984			assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 10), (3, 30, 10)]);
985			assert_eq!(A::drain().collect::<Vec<_>>(), vec![(4, 40, 10), (3, 30, 10)]);
986			assert_eq!(A::iter().collect::<Vec<_>>(), vec![]);
987
988			C::insert(3, 30, 10);
989			C::insert(4, 40, 10);
990			A::translate::<u8, _>(|k1, k2, v| Some((k1 * k2 as u16 * v as u16).into()));
991			assert_eq!(A::iter().collect::<Vec<_>>(), vec![(4, 40, 1600), (3, 30, 900)]);
992
993			let mut entries = vec![];
994			A::build_metadata(
995				sp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated,
996				vec![],
997				&mut entries,
998			);
999			AValueQueryWithAnOnEmpty::build_metadata(
1000				sp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated,
1001				vec![],
1002				&mut entries,
1003			);
1004			assert_eq!(
1005				entries,
1006				vec![
1007					StorageEntryMetadataIR {
1008						name: "foo",
1009						modifier: StorageEntryModifierIR::Optional,
1010						ty: StorageEntryTypeIR::Map {
1011							hashers: vec![
1012								StorageHasherIR::Blake2_128Concat,
1013								StorageHasherIR::Twox64Concat
1014							],
1015							key: scale_info::meta_type::<(u16, u8)>(),
1016							value: scale_info::meta_type::<u32>(),
1017						},
1018						default: Option::<u32>::None.encode(),
1019						docs: vec![],
1020						deprecation_info: sp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated
1021					},
1022					StorageEntryMetadataIR {
1023						name: "foo",
1024						modifier: StorageEntryModifierIR::Default,
1025						ty: StorageEntryTypeIR::Map {
1026							hashers: vec![
1027								StorageHasherIR::Blake2_128Concat,
1028								StorageHasherIR::Twox64Concat
1029							],
1030							key: scale_info::meta_type::<(u16, u8)>(),
1031							value: scale_info::meta_type::<u32>(),
1032						},
1033						default: 97u32.encode(),
1034						docs: vec![],
1035						deprecation_info: sp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated
1036					}
1037				]
1038			);
1039
1040			let _ = WithLen::clear(u32::max_value(), None);
1041			assert_eq!(WithLen::decode_len(3, 30), None);
1042			WithLen::append(0, 100, 10);
1043			assert_eq!(WithLen::decode_len(0, 100), Some(1));
1044
1045			A::insert(3, 30, 11);
1046			A::insert(3, 31, 12);
1047			A::insert(4, 40, 13);
1048			A::insert(4, 41, 14);
1049			assert_eq!(A::iter_prefix_values(3).collect::<Vec<_>>(), vec![12, 11]);
1050			assert_eq!(A::iter_prefix(3).collect::<Vec<_>>(), vec![(31, 12), (30, 11)]);
1051			assert_eq!(A::iter_prefix_values(4).collect::<Vec<_>>(), vec![13, 14]);
1052			assert_eq!(A::iter_prefix(4).collect::<Vec<_>>(), vec![(40, 13), (41, 14)]);
1053
1054			let _ = A::clear_prefix(3, u32::max_value(), None);
1055			assert_eq!(A::iter_prefix(3).collect::<Vec<_>>(), vec![]);
1056			assert_eq!(A::iter_prefix(4).collect::<Vec<_>>(), vec![(40, 13), (41, 14)]);
1057
1058			assert_eq!(A::drain_prefix(4).collect::<Vec<_>>(), vec![(40, 13), (41, 14)]);
1059			assert_eq!(A::iter_prefix(4).collect::<Vec<_>>(), vec![]);
1060			assert_eq!(A::drain_prefix(4).collect::<Vec<_>>(), vec![]);
1061		})
1062	}
1063
1064	#[docify::export]
1065	#[test]
1066	fn example_double_map_partial_operations() {
1067		type FooDoubleMap =
1068			StorageDoubleMap<Prefix, Blake2_128Concat, u32, Blake2_128Concat, u32, u32, ValueQuery>;
1069
1070		TestExternalities::default().execute_with(|| {
1071			FooDoubleMap::insert(0, 0, 42);
1072			FooDoubleMap::insert(0, 1, 43);
1073			FooDoubleMap::insert(1, 0, 314);
1074
1075			// should be equal to {0,1} (ordering is random)
1076			let collected_k2_keys: BTreeSet<_> = FooDoubleMap::iter_key_prefix(0).collect();
1077			assert_eq!(collected_k2_keys, [0, 1].iter().copied().collect::<BTreeSet<_>>());
1078
1079			// should be equal to {42,43} (ordering is random)
1080			let collected_k2_values: BTreeSet<_> = FooDoubleMap::iter_prefix_values(0).collect();
1081			assert_eq!(collected_k2_values, [42, 43].iter().copied().collect::<BTreeSet<_>>());
1082
1083			// Remove items from the map using k1 = 0
1084			let _ = FooDoubleMap::clear_prefix(0, u32::max_value(), None);
1085			// Values associated with (0, _) should have been removed
1086			assert_eq!(FooDoubleMap::iter_prefix(0).collect::<Vec<_>>(), vec![]);
1087		});
1088	}
1089}