Search code examples
substratepolkadot

How to read a hash value and get the corresponding AccountId from Substrate using RPC call?


I have a substrate node up and running with storage item as: value(Hash): Option<AccountId>. My aim is to provide the hash value (say, 0x0000000000000000000000000000000000000000000000000000000000000001 and get the corresponding account id in return).

When I do this through the UI, I get the following: enter image description here

I want to perform the same task via RPC calls. After going through this blog post, I realized that my case would be to read the StorageMaps and so I began with running a few queries. If I am not wrong, the module is Substratekitties and the storage item is value. The mapping would be value to AccountId.

I ran the first two calls:

util_crypto.xxhashAsHex("Substratekitties", 128)
"0xe4a154b5ba85d6072b187ee66e4fef05"
util_crypto.xxhashAsHex("Value", 128)
"0x6b2f21989c43cc4e06ac1ad3e2027000"

But I am confused in the third call encoding: encoding the file sha256 hash. How to do that? Running util_crypto.blake2AsHex("0000000000000000000000000000000000000000000000000000000000000001", 256) "0x16821de47d8b3b0fa4ca43e5db1028d75207cbd1c379a4738144972b105355aa" won't work and is not working either.

By not working I mean, I get the "null" values when executing this query. This is the storage struct:

use frame_support::{decl_module, decl_storage, dispatch::result::Result, ensure, StorageMap};
use frame_system::ensure_signed;
use sp_runtime::DispatchError;

// pub trait Trait: balances::Trait {}
pub trait Trait: pallet_balances::Trait {}

decl_storage! {
    trait Store for Module<T: Trait> as KittyStorage {
        // Value: map T::Hash => Option<T::AccountId>;
        // TODO: check whether this is the appropriate datatype(hash).
        Value: map hasher(blake2_256) T::Hash => Option<T::AccountId>;
        // Balances: map hasher(blake2_256) (T::AssetId, T::AccountId) => T::Balance;
    }
}

decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        fn set_value(origin, value: T::Hash) -> Result<(), DispatchError> {
            let sender = ensure_signed(origin)?;
            ensure!(!<Value<T>>::contains_key(value), "key already exists");
            <Value<T>>::insert(value, sender);
            Ok(())
        }
    }
}

Update: My literal query:

curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "state_getStorage", "params": ["0x3fd011a1ea758d2e1b46ed3cec43fc86b2f21989c43cc4e06ac1ad3e2027000d3585436436a2253c5163fa0cfe54a648fa533ef32ea10dbd966ac438af77b71"]}' http://localhost:9933/

Hex queries:

util_crypto.xxhashAsHex("KittyStorage", 128)
"0xe3fd011a1ea758d2e1b46ed3cec43fc8"
util_crypto.xxhashAsHex("Value", 128)
"0x6b2f21989c43cc4e06ac1ad3e2027000"
util_crypto.blake2AsHex("0x0000000000000000000000000000000000000000000000000000000000001234")

"0xd3585436436a2253c5163fa0cfe54a648fa533ef32ea10dbd966ac438af77b71"

Solution

  • I think the issue here is you are taking the hash of a string "0000...0001" not the bytes. Try adding 0x to the front of the string.

    EDIT: Try like this:

    util_crypto.blake2AsHex("0x0000000000000000000000000000000000000000000000000000000000000001")
    
    > "0x33e423980c9b37d048bd5fadbd4a2aeb95146922045405accc2f468d0ef96988"
    

    EDIT 2: The other issue here is that you are using the wrong key.

    Your example shows you are taking the storage key "Substratekitties" but your storage key is KittyStorage as specified in the decl_storage! macro.

    So your first hash should be: 0xe3fd011a1ea758d2e1b46ed3cec43fc8