@@ -76,7 +76,8 @@ use frame_support::{
76
76
} ;
77
77
use frame_system:: RawOrigin ;
78
78
use impl_trait_for_tuples:: impl_for_tuples;
79
- use sp_core:: { Hasher , H160 , H256 , U256 } ;
79
+ use scale_info:: TypeInfo ;
80
+ use sp_core:: { Decode , Encode , Hasher , H160 , H256 , U256 } ;
80
81
use sp_runtime:: {
81
82
traits:: { BadOrigin , Saturating , UniqueSaturatedInto , Zero } ,
82
83
AccountId32 , DispatchErrorWithPostInfo ,
@@ -512,6 +513,10 @@ pub mod pallet {
512
513
#[ pallet:: storage]
513
514
pub type AccountCodes < T : Config > = StorageMap < _ , Blake2_128Concat , H160 , Vec < u8 > , ValueQuery > ;
514
515
516
+ #[ pallet:: storage]
517
+ pub type AccountCodesMetadata < T : Config > =
518
+ StorageMap < _ , Blake2_128Concat , H160 , CodeMetadata , OptionQuery > ;
519
+
515
520
#[ pallet:: storage]
516
521
pub type AccountStorages < T : Config > =
517
522
StorageDoubleMap < _ , Blake2_128Concat , H160 , Blake2_128Concat , H256 , H256 , ValueQuery > ;
@@ -525,6 +530,21 @@ pub type BalanceOf<T> =
525
530
type NegativeImbalanceOf < C , T > =
526
531
<C as Currency < <T as frame_system:: Config >:: AccountId > >:: NegativeImbalance ;
527
532
533
+ #[ derive( Debug , Clone , Copy , Eq , PartialEq , Encode , Decode , TypeInfo ) ]
534
+ pub struct CodeMetadata {
535
+ pub size : u64 ,
536
+ pub hash : H256 ,
537
+ }
538
+
539
+ impl CodeMetadata {
540
+ fn from_code ( code : & [ u8 ] ) -> Self {
541
+ let size = code. len ( ) as u64 ;
542
+ let hash = H256 :: from ( sp_io:: hashing:: keccak_256 ( code) ) ;
543
+
544
+ Self { size, hash }
545
+ }
546
+ }
547
+
528
548
pub trait EnsureAddressOrigin < OuterOrigin > {
529
549
/// Success return type.
530
550
type Success ;
@@ -720,6 +740,7 @@ impl<T: Config> Pallet<T> {
720
740
}
721
741
722
742
<AccountCodes < T > >:: remove ( address) ;
743
+ <AccountCodesMetadata < T > >:: remove ( address) ;
723
744
#[ allow( deprecated) ]
724
745
let _ = <AccountStorages < T > >:: remove_prefix ( address, None ) ;
725
746
}
@@ -735,9 +756,40 @@ impl<T: Config> Pallet<T> {
735
756
let _ = frame_system:: Pallet :: < T > :: inc_sufficients ( & account_id) ;
736
757
}
737
758
759
+ // Update metadata.
760
+ let meta = CodeMetadata :: from_code ( & code) ;
761
+ <AccountCodesMetadata < T > >:: insert ( address, meta) ;
762
+
738
763
<AccountCodes < T > >:: insert ( address, code) ;
739
764
}
740
765
766
+ /// Get the account metadata (hash and size) from storage if it exists,
767
+ /// or compute it from code and store it if it doesn't exist.
768
+ pub fn account_code_metadata ( address : H160 ) -> CodeMetadata {
769
+ if let Some ( meta) = <AccountCodesMetadata < T > >:: get ( address) {
770
+ return meta;
771
+ }
772
+
773
+ let code = <AccountCodes < T > >:: get ( address) ;
774
+
775
+ // If code is empty we return precomputed hash for empty code.
776
+ // We don't store it as this address could get code deployed in the future.
777
+ if code. is_empty ( ) {
778
+ const EMPTY_CODE_HASH : [ u8 ; 32 ] = hex_literal:: hex!(
779
+ "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
780
+ ) ;
781
+ return CodeMetadata {
782
+ size : 0 ,
783
+ hash : EMPTY_CODE_HASH . into ( ) ,
784
+ } ;
785
+ }
786
+
787
+ let meta = CodeMetadata :: from_code ( & code) ;
788
+
789
+ <AccountCodesMetadata < T > >:: insert ( address, meta) ;
790
+ meta
791
+ }
792
+
741
793
/// Get the account basic in EVM format.
742
794
pub fn account_basic ( address : & H160 ) -> ( Account , frame_support:: weights:: Weight ) {
743
795
let account_id = T :: AddressMapping :: into_account_id ( * address) ;
0 commit comments