Skip to content

Commit

Permalink
Added Identity and blake2_128_concat storage hasher
Browse files Browse the repository at this point in the history
Fixed two_x64_concat hasher
  • Loading branch information
Arjan Zijderveld committed Mar 17, 2020
1 parent 79c9066 commit 8e6f39c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 51 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ urllib3==1.25.3
xxhash==1.3.0
pytest==4.4.0

scalecodec>=0.9.25
scalecodec>=0.9.26
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
'requests==2.22.0',
'urllib3==1.25.3',
'xxhash==1.3.0',
'scalecodec>=0.9.25'
'scalecodec>=0.9.26'
],

# List additional groups of dependencies here (e.g. development
Expand Down
77 changes: 29 additions & 48 deletions substrateinterface/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from scalecodec.metadata import MetadataDecoder
from scalecodec.type_registry import load_type_registry_preset

from .utils.hasher import blake2_256, two_x64_concat, xxh64
from .utils.hasher import blake2_256, two_x64_concat, xxh64, xxh128, blake2_128, blake2_128_concat, identity
from .exceptions import SubstrateRequestException
from .constants import *
from .utils.ss58 import ss58_decode
Expand Down Expand Up @@ -440,75 +440,53 @@ def generate_storage_hash(self, storage_module, storage_function, params=None, h
"""

if metadata_version and metadata_version >= 9:
storage_hash = two_x64_concat(storage_module.encode()) + two_x64_concat(storage_function.encode())
storage_hash = xxh128(storage_module.encode()) + xxh128(storage_function.encode())

if params:

if type(params) is not list:
params = [params]

if len(params) == 1:
for idx, param in enumerate(params):
if idx == 0:
param_hasher = hasher
elif idx == 1:
param_hasher = key2_hasher
else:
raise ValueError('Unexpected third parameter for storage call')

params_key = bytes()

param = params[0]

if type(param) is str:
params_key += binascii.unhexlify(param)
elif type(param) is ScaleBytes:
params_key += param.data
elif isinstance(param, ScaleDecoder):
params_key += param.data.data

if not hasher:
hasher = 'Twox64Concat'
if not param_hasher:
param_hasher = 'Twox128'

if hasher == 'Blake2_256':
if param_hasher == 'Blake2_256':
storage_hash += blake2_256(params_key)

elif hasher == 'Twox64Concat':
storage_hash += two_x64_concat(params_key)

elif len(params) == 2:

params_key = bytes()

param = params[0]

if type(param) is str:
params_key += binascii.unhexlify(param)
elif type(param) is ScaleBytes:
params_key += param.data
elif isinstance(param, ScaleDecoder):
params_key += param.data.data
elif param_hasher == 'Blake2_128':
storage_hash += blake2_128(params_key)

if not hasher:
hasher = 'Twox64Concat'
elif param_hasher == 'Blake2_128Concat':
storage_hash += blake2_128_concat(params_key)

if hasher == 'Blake2_256':
storage_hash += blake2_256(params_key) + params_key.hex()
elif param_hasher == 'Twox128':
storage_hash += xxh128(params_key)

elif hasher == 'Twox64Concat':
storage_hash += xxh64(params_key) + params_key.hex()

params_key = bytes()

param = params[1]

if type(param) is str:
params_key += binascii.unhexlify(param)
elif type(param) is ScaleBytes:
params_key += param.data
elif isinstance(param, ScaleDecoder):
params_key += param.data.data

if not key2_hasher:
key2_hasher = 'Twox64Concat'
elif param_hasher == 'Twox64Concat':
storage_hash += two_x64_concat(params_key)

if key2_hasher == 'Blake2_256':
storage_hash += blake2_256(params_key) + params_key.hex()
elif param_hasher == 'Identity':
storage_hash += identity(params_key)

elif key2_hasher == 'Twox64Concat':
storage_hash += xxh64(params_key) + params_key.hex()
else:
raise ValueError('Unknown storage hasher "{}"'.format(param_hasher))

return '0x{}'.format(storage_hash)

Expand All @@ -520,11 +498,14 @@ def generate_storage_hash(self, storage_module, storage_function, params=None, h

# Determine hasher function
if not hasher:
hasher = 'Twox64Concat'
hasher = 'Twox128'

if hasher == 'Blake2_256':
return "0x{}".format(blake2_256(storage_hash))

elif hasher == 'Twox128':
return "0x{}".format(xxh128(storage_hash))

elif hasher == 'Twox64Concat':
return "0x{}".format(two_x64_concat(storage_hash))

Expand Down
56 changes: 55 additions & 1 deletion substrateinterface/utils/hasher.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,38 @@ def blake2_256(data):
return blake2b(data, digest_size=32).digest().hex()


def two_x64_concat(data):
def blake2_128(data):
"""
Helper function to calculate a 16 bytes Blake2b hash for provided data, used as key for Substrate storage items
Parameters
----------
data
Returns
-------
"""
return blake2b(data, digest_size=16).digest().hex()


def blake2_128_concat(data):
"""
Helper function to calculate a 16 bytes Blake2b hash for provided data, concatenated with data, used as key
for Substrate storage items
Parameters
----------
data
Returns
-------
"""
return "{}{}".format(blake2b(data, digest_size=16).digest().hex(), data.hex())


def xxh128(data):
"""
Helper function to calculate a 2 concatenated xxh64 hash for provided data, used as key for several Substrate
Expand All @@ -59,8 +90,31 @@ def two_x64_concat(data):
return "{}{}".format(storage_key1.hex(), storage_key2.hex())


def two_x64_concat(data):
"""
Helper function to calculate a xxh64 hash with concatenated data for provided data,
used as key for several Substrate
Parameters
----------
data
Returns
-------
"""
storage_key = bytearray(xxhash.xxh64(data, seed=0).digest())
storage_key.reverse()

return "{}{}".format(storage_key.hex(), data.hex())


def xxh64(data):
storage_key = bytearray(xxhash.xxh64(data, seed=0).digest())
storage_key.reverse()

return "{}".format(storage_key.hex())


def identity(data):
return data.hex()

0 comments on commit 8e6f39c

Please sign in to comment.