Skip to content

Commit

Permalink
https://github.com/neo-project/neo/pull/2265
Browse files Browse the repository at this point in the history
  • Loading branch information
ixje committed Feb 18, 2021
1 parent e1f5386 commit d683f7d
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 125 deletions.
8 changes: 6 additions & 2 deletions neo3/contracts/applicationengine.py
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {}

Expand Down
12 changes: 4 additions & 8 deletions neo3/contracts/native/management.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
12 changes: 3 additions & 9 deletions neo3/contracts/native/nameservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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")
Expand All @@ -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")
Expand Down
132 changes: 44 additions & 88 deletions neo3/contracts/native/nativecontract.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -421,19 +429,31 @@ 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.
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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
"""
Expand All @@ -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:
"""
Expand All @@ -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:
"""
Expand All @@ -571,27 +549,19 @@ 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:
"""
Should only be called through syscalls
"""
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
Expand All @@ -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
Expand All @@ -613,42 +583,28 @@ 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:
if value == 0 or value > self.MAX_EXEC_FEE_FACTOR:
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):
Expand Down
20 changes: 8 additions & 12 deletions neo3/contracts/native/nonfungible.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)

Expand All @@ -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)
Expand Down
6 changes: 0 additions & 6 deletions tests/contracts/native/test_nameservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit d683f7d

Please sign in to comment.