|
17 | 17 |
|
18 | 18 | //! Stuff to do with the runtime's storage.
|
19 | 19 |
|
| 20 | +use sp_core::storage::ChildInfo; |
20 | 21 | use sp_std::prelude::*;
|
21 | 22 | use codec::{FullCodec, FullEncode, Encode, EncodeLike, Decode};
|
22 |
| -use crate::hash::{Twox128, StorageHasher}; |
| 23 | +use crate::hash::{Twox128, StorageHasher, ReversibleStorageHasher}; |
23 | 24 | use sp_runtime::generic::{Digest, DigestItem};
|
24 | 25 | pub use sp_runtime::TransactionOutcome;
|
25 | 26 |
|
@@ -519,6 +520,14 @@ pub struct PrefixIterator<T> {
|
519 | 520 | closure: fn(&[u8], &[u8]) -> Result<T, codec::Error>,
|
520 | 521 | }
|
521 | 522 |
|
| 523 | +impl<T> PrefixIterator<T> { |
| 524 | + /// Mutate this iterator into a draining iterator; items iterated are removed from storage. |
| 525 | + pub fn drain(mut self) -> Self { |
| 526 | + self.drain = true; |
| 527 | + self |
| 528 | + } |
| 529 | +} |
| 530 | + |
522 | 531 | impl<T> Iterator for PrefixIterator<T> {
|
523 | 532 | type Item = T;
|
524 | 533 |
|
@@ -563,6 +572,133 @@ impl<T> Iterator for PrefixIterator<T> {
|
563 | 572 | }
|
564 | 573 | }
|
565 | 574 |
|
| 575 | +/// Iterate over a prefix of a child trie and decode raw_key and raw_value into `T`. |
| 576 | +/// |
| 577 | +/// If any decoding fails it skips the key and continues to the next one. |
| 578 | +pub struct ChildTriePrefixIterator<T> { |
| 579 | + /// The prefix iterated on |
| 580 | + prefix: Vec<u8>, |
| 581 | + /// child info for child trie |
| 582 | + child_info: ChildInfo, |
| 583 | + /// The last key iterated on |
| 584 | + previous_key: Vec<u8>, |
| 585 | + /// If true then values are removed while iterating |
| 586 | + drain: bool, |
| 587 | + /// Whether or not we should fetch the previous key |
| 588 | + fetch_previous_key: bool, |
| 589 | + /// Function that takes `(raw_key_without_prefix, raw_value)` and decode `T`. |
| 590 | + /// `raw_key_without_prefix` is the raw storage key without the prefix iterated on. |
| 591 | + closure: fn(&[u8], &[u8]) -> Result<T, codec::Error>, |
| 592 | +} |
| 593 | + |
| 594 | +impl<T> ChildTriePrefixIterator<T> { |
| 595 | + /// Mutate this iterator into a draining iterator; items iterated are removed from storage. |
| 596 | + pub fn drain(mut self) -> Self { |
| 597 | + self.drain = true; |
| 598 | + self |
| 599 | + } |
| 600 | +} |
| 601 | + |
| 602 | +impl<T: Decode + Sized> ChildTriePrefixIterator<(Vec<u8>, T)> { |
| 603 | + /// Construct iterator to iterate over child trie items in `child_info` with the prefix `prefix`. |
| 604 | + /// |
| 605 | + /// NOTE: Iterator with [`Self::drain`] will remove any value who failed to decode |
| 606 | + pub fn with_prefix(child_info: &ChildInfo, prefix: &[u8]) -> Self { |
| 607 | + let prefix = prefix.to_vec(); |
| 608 | + let previous_key = prefix.clone(); |
| 609 | + let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| { |
| 610 | + let value = T::decode(&mut &raw_value[..])?; |
| 611 | + Ok((raw_key_without_prefix.to_vec(), value)) |
| 612 | + }; |
| 613 | + |
| 614 | + Self { |
| 615 | + prefix, |
| 616 | + child_info: child_info.clone(), |
| 617 | + previous_key, |
| 618 | + drain: false, |
| 619 | + fetch_previous_key: true, |
| 620 | + closure, |
| 621 | + } |
| 622 | + } |
| 623 | +} |
| 624 | + |
| 625 | +impl<K: Decode + Sized, T: Decode + Sized> ChildTriePrefixIterator<(K, T)> { |
| 626 | + /// Construct iterator to iterate over child trie items in `child_info` with the prefix `prefix`. |
| 627 | + /// |
| 628 | + /// NOTE: Iterator with [`Self::drain`] will remove any key or value who failed to decode |
| 629 | + pub fn with_prefix_over_key<H: ReversibleStorageHasher>(child_info: &ChildInfo, prefix: &[u8]) -> Self { |
| 630 | + let prefix = prefix.to_vec(); |
| 631 | + let previous_key = prefix.clone(); |
| 632 | + let closure = |raw_key_without_prefix: &[u8], raw_value: &[u8]| { |
| 633 | + let mut key_material = H::reverse(raw_key_without_prefix); |
| 634 | + let key = K::decode(&mut key_material)?; |
| 635 | + let value = T::decode(&mut &raw_value[..])?; |
| 636 | + Ok((key, value)) |
| 637 | + }; |
| 638 | + |
| 639 | + Self { |
| 640 | + prefix, |
| 641 | + child_info: child_info.clone(), |
| 642 | + previous_key, |
| 643 | + drain: false, |
| 644 | + fetch_previous_key: true, |
| 645 | + closure, |
| 646 | + } |
| 647 | + } |
| 648 | +} |
| 649 | + |
| 650 | +impl<T> Iterator for ChildTriePrefixIterator<T> { |
| 651 | + type Item = T; |
| 652 | + |
| 653 | + fn next(&mut self) -> Option<Self::Item> { |
| 654 | + loop { |
| 655 | + let maybe_next = if self.fetch_previous_key { |
| 656 | + self.fetch_previous_key = false; |
| 657 | + Some(self.previous_key.clone()) |
| 658 | + } else { |
| 659 | + sp_io::default_child_storage::next_key( |
| 660 | + &self.child_info.storage_key(), |
| 661 | + &self.previous_key, |
| 662 | + ) |
| 663 | + .filter(|n| n.starts_with(&self.prefix)) |
| 664 | + }; |
| 665 | + break match maybe_next { |
| 666 | + Some(next) => { |
| 667 | + self.previous_key = next; |
| 668 | + let raw_value = match child::get_raw(&self.child_info, &self.previous_key) { |
| 669 | + Some(raw_value) => raw_value, |
| 670 | + None => { |
| 671 | + log::error!( |
| 672 | + "next_key returned a key with no value at {:?}", |
| 673 | + self.previous_key, |
| 674 | + ); |
| 675 | + continue |
| 676 | + } |
| 677 | + }; |
| 678 | + if self.drain { |
| 679 | + child::kill(&self.child_info, &self.previous_key) |
| 680 | + } |
| 681 | + let raw_key_without_prefix = &self.previous_key[self.prefix.len()..]; |
| 682 | + let item = match (self.closure)(raw_key_without_prefix, &raw_value[..]) { |
| 683 | + Ok(item) => item, |
| 684 | + Err(e) => { |
| 685 | + log::error!( |
| 686 | + "(key, value) failed to decode at {:?}: {:?}", |
| 687 | + self.previous_key, |
| 688 | + e, |
| 689 | + ); |
| 690 | + continue |
| 691 | + } |
| 692 | + }; |
| 693 | + |
| 694 | + Some(item) |
| 695 | + } |
| 696 | + None => None, |
| 697 | + } |
| 698 | + } |
| 699 | + } |
| 700 | +} |
| 701 | + |
566 | 702 | /// Trait for maps that store all its value after a unique prefix.
|
567 | 703 | ///
|
568 | 704 | /// By default the final prefix is:
|
@@ -689,6 +825,7 @@ impl<Hash: Encode> StorageAppend<DigestItem<Hash>> for Digest<Hash> {}
|
689 | 825 | mod test {
|
690 | 826 | use super::*;
|
691 | 827 | use sp_core::hashing::twox_128;
|
| 828 | + use crate::hash::Identity; |
692 | 829 | use sp_io::TestExternalities;
|
693 | 830 | use generator::StorageValue as _;
|
694 | 831 |
|
@@ -825,4 +962,78 @@ mod test {
|
825 | 962 | });
|
826 | 963 | });
|
827 | 964 | }
|
| 965 | + |
| 966 | + #[test] |
| 967 | + fn child_trie_prefixed_map_works() { |
| 968 | + TestExternalities::default().execute_with(|| { |
| 969 | + let child_info_a = child::ChildInfo::new_default(b"a"); |
| 970 | + child::put(&child_info_a, &[1, 2, 3], &8u16); |
| 971 | + child::put(&child_info_a, &[2], &8u16); |
| 972 | + child::put(&child_info_a, &[2, 1, 3], &8u8); |
| 973 | + child::put(&child_info_a, &[2, 2, 3], &8u16); |
| 974 | + child::put(&child_info_a, &[3], &8u16); |
| 975 | + |
| 976 | + assert_eq!( |
| 977 | + ChildTriePrefixIterator::with_prefix(&child_info_a, &[2]) |
| 978 | + .collect::<Vec<(Vec<u8>, u16)>>(), |
| 979 | + vec![ |
| 980 | + (vec![], 8), |
| 981 | + (vec![2, 3], 8), |
| 982 | + ], |
| 983 | + ); |
| 984 | + |
| 985 | + assert_eq!( |
| 986 | + ChildTriePrefixIterator::with_prefix(&child_info_a, &[2]) |
| 987 | + .drain() |
| 988 | + .collect::<Vec<(Vec<u8>, u16)>>(), |
| 989 | + vec![ |
| 990 | + (vec![], 8), |
| 991 | + (vec![2, 3], 8), |
| 992 | + ], |
| 993 | + ); |
| 994 | + |
| 995 | + // The only remaining is the ones outside prefix |
| 996 | + assert_eq!( |
| 997 | + ChildTriePrefixIterator::with_prefix(&child_info_a, &[]) |
| 998 | + .collect::<Vec<(Vec<u8>, u8)>>(), |
| 999 | + vec![ |
| 1000 | + (vec![1, 2, 3], 8), |
| 1001 | + (vec![3], 8), |
| 1002 | + ], |
| 1003 | + ); |
| 1004 | + |
| 1005 | + child::put(&child_info_a, &[1, 2, 3], &8u16); |
| 1006 | + child::put(&child_info_a, &[2], &8u16); |
| 1007 | + child::put(&child_info_a, &[2, 1, 3], &8u8); |
| 1008 | + child::put(&child_info_a, &[2, 2, 3], &8u16); |
| 1009 | + child::put(&child_info_a, &[3], &8u16); |
| 1010 | + |
| 1011 | + assert_eq!( |
| 1012 | + ChildTriePrefixIterator::with_prefix_over_key::<Identity>(&child_info_a, &[2]) |
| 1013 | + .collect::<Vec<(u16, u16)>>(), |
| 1014 | + vec![ |
| 1015 | + (u16::decode(&mut &[2, 3][..]).unwrap(), 8), |
| 1016 | + ], |
| 1017 | + ); |
| 1018 | + |
| 1019 | + assert_eq!( |
| 1020 | + ChildTriePrefixIterator::with_prefix_over_key::<Identity>(&child_info_a, &[2]) |
| 1021 | + .drain() |
| 1022 | + .collect::<Vec<(u16, u16)>>(), |
| 1023 | + vec![ |
| 1024 | + (u16::decode(&mut &[2, 3][..]).unwrap(), 8), |
| 1025 | + ], |
| 1026 | + ); |
| 1027 | + |
| 1028 | + // The only remaining is the ones outside prefix |
| 1029 | + assert_eq!( |
| 1030 | + ChildTriePrefixIterator::with_prefix(&child_info_a, &[]) |
| 1031 | + .collect::<Vec<(Vec<u8>, u8)>>(), |
| 1032 | + vec![ |
| 1033 | + (vec![1, 2, 3], 8), |
| 1034 | + (vec![3], 8), |
| 1035 | + ], |
| 1036 | + ); |
| 1037 | + }); |
| 1038 | + } |
828 | 1039 | }
|
0 commit comments