From d683f7ddafed47690a27bb8248192ea804bde189 Mon Sep 17 00:00:00 2001 From: Erik van den Brink Date: Thu, 18 Feb 2021 09:11:02 +0100 Subject: [PATCH] https://github.com/neo-project/neo/pull/2265 --- neo3/contracts/applicationengine.py | 8 +- neo3/contracts/native/management.py | 12 +- neo3/contracts/native/nameservice.py | 12 +- neo3/contracts/native/nativecontract.py | 132 +++++++-------------- neo3/contracts/native/nonfungible.py | 20 ++-- tests/contracts/native/test_nameservice.py | 6 - 6 files changed, 65 insertions(+), 125 deletions(-) diff --git a/neo3/contracts/applicationengine.py b/neo3/contracts/applicationengine.py index 5023d470..3ad58eca 100644 --- a/neo3/contracts/applicationengine.py +++ b/neo3/contracts/applicationengine.py @@ -45,8 +45,12 @@ def __init__(self, self._invocation_counter: Dict[types.UInt160, int] = {} #: Notifications (Notify SYSCALLs) that occured while executing the script. self.notifications: List[Tuple[payloads.IVerifiable, types.UInt160, bytes, vm.ArrayStackItem]] = [] - self.exec_fee_factor = contracts.PolicyContract().get_exec_fee_factor(snapshot) - self.STORAGE_PRICE = contracts.PolicyContract().get_storage_price(snapshot) + if self.snapshot is None or self.snapshot.persisting_block is None or self.snapshot.persisting_block.index == 0: + self.exec_fee_factor = contracts.PolicyContract().DEFAULT_EXEC_FEE_FACTOR + self.STORAGE_PRICE = contracts.PolicyContract().DEFAULT_STORAGE_PRICE + else: + self.exec_fee_factor = contracts.PolicyContract().get_exec_fee_factor(snapshot) + self.STORAGE_PRICE = contracts.PolicyContract().get_storage_price(snapshot) self._context_state: Dict[vm.ExecutionContext, storage.ContractState] = {} diff --git a/neo3/contracts/native/management.py b/neo3/contracts/native/management.py index 266cb198..0c20a396 100644 --- a/neo3/contracts/native/management.py +++ b/neo3/contracts/native/management.py @@ -113,17 +113,13 @@ def _initialize(self, engine: contracts.ApplicationEngine) -> None: self.key_min_deploy_fee, storage.StorageItem(vm.BigInteger(10_00000000).to_array()) ) + engine.snapshot.storages.put(self.key_next_id, storage.StorageItem(b'\x00')) def get_next_available_id(self, snapshot: storage.Snapshot) -> int: key = self.create_key(self._PREFIX_NEXT_AVAILABLE_ID) - item = snapshot.storages.try_get(key, read_only=False) - if item is None: - value = vm.BigInteger(1) - item = storage.StorageItem(value.to_array()) - else: - value = vm.BigInteger(item.value) + 1 - item.value = value.to_array() - snapshot.storages.update(key, item) + item = snapshot.storages.get(key, read_only=False) + value = vm.BigInteger(item.value) + 1 + item.value = value.to_array() return int(value) def on_persist(self, engine: contracts.ApplicationEngine) -> None: diff --git a/neo3/contracts/native/nameservice.py b/neo3/contracts/native/nameservice.py index 88109902..6b2b4d23 100644 --- a/neo3/contracts/native/nameservice.py +++ b/neo3/contracts/native/nameservice.py @@ -152,6 +152,7 @@ def init(self): def _initialize(self, engine: contracts.ApplicationEngine) -> None: super(NameService, self)._initialize(engine) engine.snapshot.storages.put(self.key_domain_price, storage.StorageItem(vm.BigInteger(1000000000).to_array())) + engine.snapshot.storages.put(self.key_roots, storage.StorageItem(b'\x00')) def on_persist(self, engine: contracts.ApplicationEngine) -> None: now = vm.BigInteger((engine.snapshot.persisting_block.timestamp // 1000) + 1) @@ -171,11 +172,7 @@ def add_root(self, engine: contracts.ApplicationEngine, root: str) -> None: raise ValueError("Regex failure - root not found") if not self._check_committee(engine): raise ValueError("Check committee failed") - storage_item_roots = engine.snapshot.storages.try_get(self.key_roots, read_only=False) - if storage_item_roots is None: - storage_item_roots = storage.StorageItem(b'\x00') - engine.snapshot.storages.put(self.key_roots, storage_item_roots) - + storage_item_roots = engine.snapshot.storages.get(self.key_roots, read_only=False) roots = StringList.from_storage(storage_item_roots) if root in roots: raise ValueError("The name already exists") @@ -201,10 +198,7 @@ def is_available(self, snapshot: storage.Snapshot, name: str) -> bool: storage_item = snapshot.storages.try_get(self.key_token + name.encode(), read_only=True) if storage_item: return False - storage_item_roots = snapshot.storages.try_get(self.key_roots, read_only=True) - if storage_item_roots is None: - raise ValueError("Can't find roots in storage") - + storage_item_roots = snapshot.storages.get(self.key_roots, read_only=True) roots = StringList.from_storage(storage_item_roots) if names[1] not in roots: raise ValueError(f"'{names[1]}' is not a registered root") diff --git a/neo3/contracts/native/nativecontract.py b/neo3/contracts/native/nativecontract.py index fec6e915..61282a24 100644 --- a/neo3/contracts/native/nativecontract.py +++ b/neo3/contracts/native/nativecontract.py @@ -300,6 +300,14 @@ class PolicyContract(NativeContract): _PREFIX_EXEC_FEE_FACTOR = b'\x12' _PREFIX_STORAGE_PRICE = b'\x13' + key_max_transactions_per_block = storage.StorageKey(_id, _PREFIX_MAX_TRANSACTIONS_PER_BLOCK) + key_fee_per_byte = storage.StorageKey(_id, _PREFIX_FEE_PER_BYTE) + key_blocked_account = storage.StorageKey(_id, _PREFIX_BLOCKED_ACCOUNT) + key_max_block_size = storage.StorageKey(_id, _PREFIX_MAX_BLOCK_SIZE) + key_max_block_system_fee = storage.StorageKey(_id, _PREFIX_MAX_BLOCK_SYSTEM_FEE) + key_exec_fee_factor = storage.StorageKey(_id, _PREFIX_EXEC_FEE_FACTOR) + key_storage_price = storage.StorageKey(_id, _PREFIX_STORAGE_PRICE) + def init(self): super(PolicyContract, self).init() @@ -421,6 +429,20 @@ def init(self): call_flags=contracts.CallFlags.WRITE_STATES ) + def _int_to_bytes(self, value: int) -> bytes: + return value.to_bytes((value.bit_length() + 7 + 1) // 8, 'little', signed=True) # +1 for signed + + def _initialize(self, engine: contracts.ApplicationEngine) -> None: + def _to_si(value: int) -> storage.StorageItem: + return storage.StorageItem(self._int_to_bytes(value)) + + engine.snapshot.storages.put(self.key_max_transactions_per_block, _to_si(512)) + engine.snapshot.storages.put(self.key_fee_per_byte, _to_si(1000)) + engine.snapshot.storages.put(self.key_max_block_size, _to_si(1024 * 256)) + engine.snapshot.storages.put(self.key_max_block_system_fee, _to_si(int(GasToken().factor * 9000))) + engine.snapshot.storages.put(self.key_exec_fee_factor, _to_si(self.DEFAULT_EXEC_FEE_FACTOR)) + engine.snapshot.storages.put(self.key_storage_price, _to_si(self.DEFAULT_STORAGE_PRICE)) + def get_max_block_size(self, snapshot: storage.Snapshot) -> int: """ Retrieve the configured maximum size of a Block. @@ -428,12 +450,10 @@ def get_max_block_size(self, snapshot: storage.Snapshot) -> int: Returns: int: maximum number of bytes. """ - data = snapshot.storages.try_get( + data = snapshot.storages.get( self.create_key(self._PREFIX_MAX_BLOCK_SIZE), read_only=True ) - if data is None: - return 1024 * 256 return int.from_bytes(data.value, 'little', signed=True) def get_max_transactions_per_block(self, snapshot: storage.Snapshot) -> int: @@ -443,12 +463,7 @@ def get_max_transactions_per_block(self, snapshot: storage.Snapshot) -> int: Returns: int: maximum number of transaction. """ - data = snapshot.storages.try_get( - self.create_key(self._PREFIX_MAX_TRANSACTIONS_PER_BLOCK), - read_only=True - ) - if data is None: - return 512 + data = snapshot.storages.get(self.key_max_transactions_per_block, read_only=True) return int.from_bytes(data.value, 'little', signed=True) def get_max_block_system_fee(self, snapshot: storage.Snapshot) -> int: @@ -458,13 +473,7 @@ def get_max_block_system_fee(self, snapshot: storage.Snapshot) -> int: Returns: int: maximum system fee. """ - data = snapshot.storages.try_get( - self.create_key(self._PREFIX_MAX_BLOCK_SYSTEM_FEE), - read_only=True - ) - if data is None: - x = GasToken().factor * 9000 - return int(x) + data = snapshot.storages.get(self.key_max_block_system_fee, read_only=True) return int.from_bytes(data.value, 'little', signed=True) def get_fee_per_byte(self, snapshot: storage.Snapshot) -> int: @@ -474,12 +483,7 @@ def get_fee_per_byte(self, snapshot: storage.Snapshot) -> int: Returns: int: maximum fee. """ - data = snapshot.storages.try_get( - self.create_key(self._PREFIX_FEE_PER_BYTE), - read_only=True - ) - if data is None: - return 1000 + data = snapshot.storages.get(self.key_fee_per_byte, read_only=True) return int.from_bytes(data.value, 'little', signed=True) def is_blocked(self, snapshot: storage.Snapshot, account: types.UInt160) -> bool: @@ -489,10 +493,7 @@ def is_blocked(self, snapshot: storage.Snapshot, account: types.UInt160) -> bool Transaction from blocked accounts will be rejected by the consensus nodes. """ - si = snapshot.storages.try_get( - self.create_key(self._PREFIX_BLOCKED_ACCOUNT + account.to_array()), - read_only=True - ) + si = snapshot.storages.try_get(self.key_blocked_account + account.to_array(), read_only=True) if si is None: return False else: @@ -508,15 +509,8 @@ def _set_max_block_size(self, engine: contracts.ApplicationEngine, value: int) - if not self._check_committee(engine): raise ValueError("Check committee failed") - storage_key = self.create_key(self._PREFIX_MAX_BLOCK_SIZE) - storage_item = engine.snapshot.storages.try_get( - storage_key, - read_only=False - ) - if storage_item is None: - storage_item = storage.StorageItem(b'') - engine.snapshot.storages.update(storage_key, storage_item) - storage_item.value = value.to_bytes((value.bit_length() + 7) // 8, 'little', signed=True) + storage_item = engine.snapshot.storages.get(self.key_max_block_size, read_only=False) + storage_item.value = self._int_to_bytes(value) def _set_max_transactions_per_block(self, engine: contracts.ApplicationEngine, value: int) -> None: """ @@ -528,16 +522,8 @@ def _set_max_transactions_per_block(self, engine: contracts.ApplicationEngine, v if not self._check_committee(engine): raise ValueError("Check committee failed") - storage_key = self.create_key(self._PREFIX_MAX_TRANSACTIONS_PER_BLOCK) - storage_item = engine.snapshot.storages.try_get( - storage_key, - read_only=False - ) - if storage_item is None: - storage_item = storage.StorageItem(b'') - engine.snapshot.storages.update(storage_key, storage_item) - - storage_item.value = value.to_bytes((value.bit_length() + 7) // 8, 'little', signed=True) + storage_item = engine.snapshot.storages.get(self.key_max_transactions_per_block, read_only=False) + storage_item.value = self._int_to_bytes(value) def _set_max_block_system_fee(self, engine: contracts.ApplicationEngine, value: int) -> None: """ @@ -550,16 +536,8 @@ def _set_max_block_system_fee(self, engine: contracts.ApplicationEngine, value: if not self._check_committee(engine): raise ValueError("Check committee failed") - storage_key = self.create_key(self._PREFIX_MAX_BLOCK_SYSTEM_FEE) - storage_item = engine.snapshot.storages.try_get( - storage_key, - read_only=False - ) - if storage_item is None: - storage_item = storage.StorageItem(b'') - engine.snapshot.storages.update(storage_key, storage_item) - - storage_item.value = value.to_bytes((value.bit_length() + 7) // 8, 'little', signed=True) + storage_item = engine.snapshot.storages.get(self.key_max_block_system_fee, read_only=False) + storage_item.value = self._int_to_bytes(value) def _set_fee_per_byte(self, engine: contracts.ApplicationEngine, value: int) -> None: """ @@ -571,16 +549,8 @@ def _set_fee_per_byte(self, engine: contracts.ApplicationEngine, value: int) -> if not self._check_committee(engine): raise ValueError("Check committee failed") - storage_key = self.create_key(self._PREFIX_FEE_PER_BYTE) - storage_item = engine.snapshot.storages.try_get( - storage_key, - read_only=False - ) - if storage_item is None: - storage_item = storage.StorageItem(b'') - engine.snapshot.storages.update(storage_key, storage_item) - - storage_item.value = value.to_bytes((value.bit_length() + 7) // 8, 'little', signed=True) + storage_item = engine.snapshot.storages.get(self.key_fee_per_byte, read_only=False) + storage_item.value = self._int_to_bytes(value) def _block_account(self, engine: contracts.ApplicationEngine, account: types.UInt160) -> bool: """ @@ -588,10 +558,10 @@ def _block_account(self, engine: contracts.ApplicationEngine, account: types.UIn """ if not self._check_committee(engine): return False - storage_key = self.create_key(self._PREFIX_BLOCKED_ACCOUNT + account.to_array()) + storage_key = self.key_blocked_account + account.to_array() storage_item = engine.snapshot.storages.try_get(storage_key, read_only=False) if storage_item is None: - storage_item = storage.StorageItem(b'\x01') + storage_item = storage.StorageItem(b'\x00') engine.snapshot.storages.update(storage_key, storage_item) else: return False @@ -604,7 +574,7 @@ def _unblock_account(self, engine: contracts.ApplicationEngine, account: types.U """ if not self._check_committee(engine): return False - storage_key = self.create_key(self._PREFIX_BLOCKED_ACCOUNT + account.to_array()) + storage_key = self.key_blocked_account + account.to_array() storage_item = engine.snapshot.storages.try_get(storage_key, read_only=False) if storage_item is None: return False @@ -613,15 +583,11 @@ def _unblock_account(self, engine: contracts.ApplicationEngine, account: types.U return True def get_exec_fee_factor(self, snapshot: storage.Snapshot) -> int: - storage_item = snapshot.storages.try_get(self.create_key(self._PREFIX_EXEC_FEE_FACTOR)) - if storage_item is None: - return self.DEFAULT_EXEC_FEE_FACTOR + storage_item = snapshot.storages.get(self.key_exec_fee_factor, read_only=True) return int(vm.BigInteger(storage_item.value)) def get_storage_price(self, snapshot: storage.Snapshot) -> int: - storage_item = snapshot.storages.try_get(self.create_key(self._PREFIX_STORAGE_PRICE)) - if storage_item is None: - return self.DEFAULT_STORAGE_PRICE + storage_item = snapshot.storages.get(self.key_storage_price, read_only=True) return int(vm.BigInteger(storage_item.value)) def _set_exec_fee_factor(self, engine: contracts.ApplicationEngine, value: int) -> None: @@ -629,26 +595,16 @@ def _set_exec_fee_factor(self, engine: contracts.ApplicationEngine, value: int) raise ValueError("New exec fee value out of range") if not self._check_committee(engine): raise ValueError("Check committee failed") - storage_key = self.create_key(self._PREFIX_EXEC_FEE_FACTOR) - storage_item = engine.snapshot.storages.try_get(storage_key, read_only=False) - if storage_item is None: - storage_item = storage.StorageItem(vm.BigInteger(value).to_array()) - else: - storage_item.value = vm.BigInteger(value).to_array() - engine.snapshot.storages.update(storage_key, storage_item) + storage_item = engine.snapshot.storages.get(self.key_exec_fee_factor, read_only=False) + storage_item.value = vm.BigInteger(value).to_array() def _set_storage_price(self, engine: contracts.ApplicationEngine, value: int) -> None: if value == 0 or value > self.MAX_STORAGE_PRICE: raise ValueError("New storage price value out of range") if not self._check_committee(engine): raise ValueError("Check committee failed") - storage_key = self.create_key(self._PREFIX_STORAGE_PRICE) - storage_item = engine.snapshot.storages.try_get(storage_key, read_only=False) - if storage_item is None: - storage_item = storage.StorageItem(vm.BigInteger(value).to_array()) - else: - storage_item.value = vm.BigInteger(value).to_array() - engine.snapshot.storages.update(storage_key, storage_item) + storage_item = engine.snapshot.storages.get(self.key_storage_price, read_only=False) + storage_item.value = vm.BigInteger(value).to_array() class FungibleToken(NativeContract): diff --git a/neo3/contracts/native/nonfungible.py b/neo3/contracts/native/nonfungible.py index 78b6d55c..13c2e00d 100644 --- a/neo3/contracts/native/nonfungible.py +++ b/neo3/contracts/native/nonfungible.py @@ -164,6 +164,9 @@ def init(self): call_flags=(contracts.CallFlags.WRITE_STATES | contracts.CallFlags.ALLOW_NOTIFY)) + def _initialize(self, engine: contracts.ApplicationEngine) -> None: + engine.snapshot.storages.put(self.key_total_suppply, storage.StorageItem(b'\x00')) + def mint(self, engine: contracts.ApplicationEngine, token: NFTState) -> None: engine.snapshot.storages.put(self.key_token + token.id, storage.StorageItem(token.to_array())) sk_account = self.key_account + token.id @@ -176,13 +179,9 @@ def mint(self, engine: contracts.ApplicationEngine, token: NFTState) -> None: account = NFTAccountState.from_storage(si_account) account.add(token.id) - si_total_supply = engine.snapshot.storages.try_get(self.key_total_suppply, read_only=False) - if si_total_supply is None: - si_total_supply = storage.StorageItem(vm.BigInteger.one().to_array()) - else: - new_value = vm.BigInteger(si_total_supply.value) + 1 - si_total_supply.value = new_value.to_array() - engine.snapshot.storages.update(self.key_total_suppply, si_total_supply) + si_total_supply = engine.snapshot.storages.get(self.key_total_suppply, read_only=False) + new_value = vm.BigInteger(si_total_supply.value) + 1 + si_total_supply.value = new_value.to_array() self._post_transfer(engine, types.UInt160.zero(), token.owner, token.id) @@ -208,11 +207,8 @@ def burn(self, engine: contracts.ApplicationEngine, token_id: bytes) -> None: self._post_transfer(engine, token.owner, types.UInt160.zero(), token_id) def total_supply(self, snapshot: storage.Snapshot) -> vm.BigInteger: - storage_item = snapshot.storages.try_get(self.key_total_suppply) - if storage_item is None: - return vm.BigInteger.zero() - else: - return vm.BigInteger(storage_item.value) + storage_item = snapshot.storages.get(self.key_total_suppply) + return vm.BigInteger(storage_item.value) def owner_of(self, snapshot: storage.Snapshot, token_id: bytes) -> types.UInt160: storage_item = snapshot.storages.get(self.key_token + token_id, read_only=True) diff --git a/tests/contracts/native/test_nameservice.py b/tests/contracts/native/test_nameservice.py index 3cbf3832..f3142302 100644 --- a/tests/contracts/native/test_nameservice.py +++ b/tests/contracts/native/test_nameservice.py @@ -90,12 +90,6 @@ def test_is_available(self): nameservice.is_available(snapshot, "sub.neo.org") self.assertEqual("Invalid format", str(context.exception)) - with self.assertRaises(ValueError) as context: - nameservice.is_available(snapshot, "neo.org") - self.assertEqual("Can't find roots in storage", str(context.exception)) - - # create an empty roots list - snapshot.storages.put(nameservice.key_roots, storage.StorageItem(b'\x00')) with self.assertRaises(ValueError) as context: nameservice.is_available(snapshot, "neo.org") self.assertEqual("'org' is not a registered root", str(context.exception))