Skip to content

Commit

Permalink
Merge pull request #63 from xian-network/default_value_for_foreign_hash
Browse files Browse the repository at this point in the history
Make ForeighHash inherit the default value of the referenced Hash
  • Loading branch information
duelingbenjos authored Oct 2, 2024
2 parents 75707a9 + bc00242 commit c5aaf72
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/contracting/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
DELIMITER = ':'
INDEX_SEPARATOR = '.'
HDF5_GROUP_SEPARATOR = '/'

DEFAULT = '__default__'
SUBMISSION_CONTRACT_NAME = 'submission'
PRIVATE_METHOD_PREFIX = '__'
EXPORT_DECORATOR_STRING = 'export'
Expand Down
41 changes: 25 additions & 16 deletions src/contracting/storage/orm.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from contracting.storage.driver import Driver
from contracting.execution.runtime import rt
from contracting import constants
from contracting import constants as c
from contracting.stdlib.bridge.decimal import ContractingDecimal

driver = rt.env.get('__Driver') or Driver()
Expand Down Expand Up @@ -35,55 +35,61 @@ def get(self):
class Hash(Datum):
def __init__(self, contract, name, driver: Driver = driver, default_value=None):
super().__init__(contract, name, driver=driver)
self._delimiter = constants.DELIMITER
self._default_value = default_value

# Store the default_value in storage if it's not None
if default_value is not None:
self._driver.set(f'{self._key}{c.DELIMITER}{c.DEFAULT}', default_value)

def _set(self, key, value):
self._driver.set(f'{self._key}{self._delimiter}{key}', value)
self._driver.set(f'{self._key}{c.DELIMITER}{key}', value)

def _get(self, item):
value = self._driver.get(f'{self._key}{self._delimiter}{item}')
value = self._driver.get(f'{self._key}{c.DELIMITER}{item}')

# Add Python defaultdict behavior for easier smart contracting
if value is None:
# Retrieve the default_value from storage if not set
if self._default_value is None:
self._default_value = self._driver.get(f'{self._key}{c.DELIMITER}{c.DEFAULT}')
value = self._default_value

if type(value) == float or type(value) == ContractingDecimal:
if isinstance(value, (float, ContractingDecimal)):
return ContractingDecimal(str(value))

return value

def _validate_key(self, key):
if isinstance(key, tuple):
assert len(key) <= constants.MAX_HASH_DIMENSIONS, (f'Too many dimensions ({len(key)}) for hash. '
f'Max is {constants.MAX_HASH_DIMENSIONS}')
assert len(key) <= c.MAX_HASH_DIMENSIONS, (f'Too many dimensions ({len(key)}) for hash. '
f'Max is {c.MAX_HASH_DIMENSIONS}')

new_key_str = ''
for k in key:
assert not isinstance(k, slice), 'Slices prohibited in hashes.'

k = str(k)

assert constants.DELIMITER not in k, 'Illegal delimiter in key.'
assert constants.INDEX_SEPARATOR not in k, 'Illegal separator in key.'
assert c.DELIMITER not in k, 'Illegal delimiter in key.'
assert c.INDEX_SEPARATOR not in k, 'Illegal separator in key.'

new_key_str += f'{k}{self._delimiter}'
new_key_str += f'{k}{c.DELIMITER}'

key = new_key_str[:-len(self._delimiter)]
key = new_key_str[:-len(c.DELIMITER)]
else:
key = str(key)

assert constants.DELIMITER not in key, 'Illegal delimiter in key.'
assert constants.INDEX_SEPARATOR not in key, 'Illegal separator in key.'
assert c.DELIMITER not in key, 'Illegal delimiter in key.'
assert c.INDEX_SEPARATOR not in key, 'Illegal separator in key.'

assert len(key) <= constants.MAX_KEY_SIZE, f'Key is too long ({len(key)}). Max is {constants.MAX_KEY_SIZE}.'
assert len(key) <= c.MAX_KEY_SIZE, f'Key is too long ({len(key)}). Max is {c.MAX_KEY_SIZE}.'
return key

def _prefix_for_args(self, args):
multi = self._validate_key(args)
prefix = f'{self._key}{self._delimiter}'
prefix = f'{self._key}{c.DELIMITER}'
if multi != '':
prefix += f'{multi}{self._delimiter}'
prefix += f'{multi}{c.DELIMITER}'

return prefix

Expand Down Expand Up @@ -128,6 +134,9 @@ def __init__(self, contract, name, foreign_contract, foreign_name, driver: Drive
super().__init__(contract, name, driver=driver)
self._key = self._driver.make_key(foreign_contract, foreign_name)

# Retrieve the default_value from the foreign Hash's storage
self._default_value = self._driver.get(f'{self._key}{c.DELIMITER}{c.DEFAULT}')

def _set(self, key, value):
raise ReferenceError

Expand Down

0 comments on commit c5aaf72

Please sign in to comment.