Skip to content

Commit

Permalink
https://github.com/neo-project/neo/pull/1848
Browse files Browse the repository at this point in the history
  • Loading branch information
ixje committed Jan 22, 2021
1 parent a4e23c5 commit b5084c8
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 49 deletions.
217 changes: 171 additions & 46 deletions neo3/contracts/native/nativecontract.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion neo3/network/payloads/consensus.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def deserialize_unsigned(self, reader: serialization.BinaryReader) -> None:
self.data = reader.read_var_bytes()

def get_script_hashes_for_verifying(self, snapshot: storage.Snapshot) -> List[types.UInt160]:
validators = contracts.NeoToken().get_next_block_validators(snapshot)
validators = contracts.NeoToken().get_next_block_validators()
if len(validators) < self.validator_index:
raise ValueError("Validator index is out of range")
return [to_script_hash(
Expand Down
2 changes: 1 addition & 1 deletion neo3/network/payloads/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def __init__(self):
self.type_ = TransactionAttributeType.HIGH_PRIORITY

def verify(self, snapshot: storage.Snapshot, tx: Transaction) -> bool:
committee = contracts.NeoToken().get_committee_address(snapshot)
committee = contracts.NeoToken().get_committee_address()
for signer in tx.signers:
if signer.account == committee:
return True
Expand Down
1 change: 1 addition & 0 deletions neo3/storage/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
from .storageitem import StorageItem, StorageFlags, Nep5StorageState
from .storagekey import StorageKey
from .contractstate import ContractState
from .utils import NEOByteCompare, NEOSeekSort
6 changes: 6 additions & 0 deletions neo3/storage/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ def _internal_storage_find(self, contract_script_hash: types.UInt160,
key_prefix: bytes) -> Iterator[Tuple[storage.StorageKey, storage.StorageItem]]:
""" Find key/value pairs for a given smart contract by a given key prefix. """

def _internal_storage_seek(self,
contract_scrip_hash: types.UInt160,
key_prefix: bytes,
seek_direction="forward") -> Iterator[Tuple[storage.StorageKey, storage.StorageItem]]:
""" """

@abc.abstractmethod
def _internal_transaction_put(self, transaction: payloads.Transaction) -> None:
""" Persist a transaction in the real backend (readonly). """
Expand Down
40 changes: 39 additions & 1 deletion neo3/storage/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
from neo3.core import types, serialization
from neo3 import storage
from contextlib import suppress
from functools import cmp_to_key, partial

if TYPE_CHECKING:
from neo3.network import payloads


TKey = TypeVar('TKey', bound='serialization.ISerializable')
TValue = TypeVar('TValue', bound='serialization.ISerializable')

Expand All @@ -36,6 +37,7 @@ def __init__(self, db):
self._internal_get = None
self._internal_try_get = None
self._internal_all = None
self._internal_seek = None

def __getitem__(self, key):
trackable = self._dictionary.get(key, None) # type: Trackable
Expand Down Expand Up @@ -368,6 +370,7 @@ def __init__(self, db):
self._internal_try_get = self._db._internal_storage_try_get
self._internal_all = self._db._internal_storage_all
self._internal_find = self._db._internal_storage_find
self._iternal_seek = self._db._internal_storage_seek

def put(self, key: storage.StorageKey, value: storage.StorageItem) -> None:
"""
Expand Down Expand Up @@ -484,6 +487,41 @@ def find(self, contract_script_hash: types.UInt160, key_prefix: bytes) -> Iterat
yield pair
return None

def seek(self, contract_script_hash: types.UInt160,
key_prefix: bytes,
direction="forward"
) -> Iterator[Tuple[storage.StorageKey, storage.StorageItem]]:

comperator = storage.NEOByteCompare(direction)
results: List[Tuple[storage.StorageKey, storage.StorageItem]] = []
for key, value in self._dictionary.items():
if value.state != TrackState.DELETED and (
len(key_prefix) == 0 or comperator.compare(key.to_array(), key_prefix) >= 0):
results.append((deepcopy(key), deepcopy(value.item)))

cached_keys = self._dictionary.keys()
for key, value in self._internal_seek(contract_script_hash, key_prefix, "forward"):
if key not in cached_keys:
results.append((key, value))
results.sort(key=cmp_to_key(partial(storage.NEOSeekSort, comperator.compare))) # type: ignore

for pair in results:
yield pair
return None

def find_range(self,
contract_script_hash: types.UInt160,
start: bytes,
end: bytes,
direction: str = "forward"
) -> Iterator[Tuple[storage.StorageKey, storage.StorageItem]]:
comperator = storage.NEOByteCompare(direction)
for key, value in self.seek(contract_script_hash, start, direction):
if comperator.compare(key.to_array(), end) < 0:
yield key, value
else:
break


class CachedTXAccess(CachedAccess):
def __init__(self, db):
Expand Down
30 changes: 30 additions & 0 deletions neo3/storage/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Tuple
from neo3 import storage


class NEOByteCompare:
def __init__(self, direction="forward"):
if direction == "forward":
self.direction = 0
else:
self.direction = 1

def compare(self, x: bytes, y: bytes) -> int:
if self.direction == 0:
return self._compare_internal(x, y)
else:
return -self._compare_internal(x, y)

def _compare_internal(self, x: bytes, y: bytes) -> int:
if x == y:
return 0
elif x < y:
return -1
else:
return 1


def NEOSeekSort(comperator_func,
pair_y: Tuple[storage.StorageKey, storage.StorageItem],
pair_x: Tuple[storage.StorageKey, storage.StorageItem]) -> int:
return comperator_func(pair_x[0].key, pair_y[0].key)

0 comments on commit b5084c8

Please sign in to comment.