def _post_transfer(self, engine: contracts.ApplicationEngine, account_from: types.UInt160, account_to: types.UInt160, amount: vm.BigInteger, data: vm.StackItem, call_on_payment: bool) -> None: state = vm.ArrayStackItem(vm.ReferenceCounter()) if account_from == types.UInt160.zero(): state.append(vm.NullStackItem()) else: state.append(vm.ByteStringStackItem(account_from.to_array())) if account_to == types.UInt160.zero(): state.append(vm.NullStackItem()) else: state.append(vm.ByteStringStackItem(account_to.to_array())) state.append(vm.IntegerStackItem(amount)) msgrouter.interop_notify(self.hash, "Transfer", state) # wallet or smart contract if not call_on_payment \ or account_to == types.UInt160.zero() \ or contracts.ManagementContract().get_contract(engine.snapshot, account_to) is None: return if account_from == types.UInt160.zero(): from_: vm.StackItem = vm.NullStackItem() else: from_ = vm.ByteStringStackItem(account_from.to_array()) engine.call_from_native( self.hash, account_to, "onNEP17Payment", [from_, vm.IntegerStackItem(amount), data])
def transfer_helper(self, contract: contracts.NativeContract, from_account: types.UInt160, to_account: types.UInt160, amount: vm.BigInteger): engine = test_engine(has_snapshot=True) block = test_block(0) # set or we won't pass the native deploy call engine.snapshot.persisting_block = block engine.invocation_stack.pop() # we no longer need the default script engine.script_container = TestIVerifiable() engine.script_container.script_hashes = [from_account] sb = vm.ScriptBuilder() sb.emit(vm.OpCode.PUSHNULL) sb.emit_push(amount) sb.emit_push(to_account.to_array()) sb.emit_push(from_account.to_array()) sb.emit_push(4) sb.emit(vm.OpCode.PACK) sb.emit_push(15) # callflags sb.emit_push(b'transfer') sb.emit_push(contract.hash.to_array()) sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) engine.load_script(vm.Script(sb.to_array())) nef = contracts.NEF(script=sb.to_array()) manifest = contracts.ContractManifest("test_contract") contract_state = contracts.ContractState( 1, nef, manifest, 0, contract_hash(from_account, nef.checksum, manifest.name)) engine.snapshot.contracts.put(contract_state) return engine
def transfer_helper(self, contract: contracts.NativeContract, from_account: types.UInt160, to_account: types.UInt160, amount: vm.BigInteger): engine = test_engine(has_snapshot=True) block = test_block(0) # set or we won't pass the native deploy call engine.snapshot.persisting_block = block engine.invoke_syscall_by_name("Neo.Native.Deploy") engine.invocation_stack.pop() # we no longer need the default script engine.script_container = TestIVerifiable() engine.script_container.script_hashes = [from_account] sb = vm.ScriptBuilder() sb.emit_push(amount) sb.emit_push(to_account.to_array()) sb.emit_push(from_account.to_array()) sb.emit_push(3) sb.emit(vm.OpCode.PACK) sb.emit_push(b'transfer') sb.emit_push(contract.script_hash.to_array()) sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) engine.load_script(vm.Script(sb.to_array())) engine.snapshot.contracts.put( storage.ContractState(sb.to_array(), contracts.ContractManifest())) return engine
def test_from_string_wrong_length(self): with self.assertRaises(ValueError) as ctx: UInt160.from_string("1122") self.assertEqual("Invalid UInt160 Format: 4 chars != 40 chars", str(ctx.exception)) with self.assertRaises(ValueError) as ctx: UInt256.from_string("1122") self.assertEqual("Invalid UInt256 Format: 4 chars != 64 chars", str(ctx.exception))
def _internal_contract_delete(self, hash: types.UInt160, batch=None): if batch: db = batch else: db = self._real_db db.delete(DBPrefixes.CONTRACTS + hash.to_array())
def _internal_contract_get(self, hash: types.UInt160): contract_bytes = self._real_db.get(DBPrefixes.CONTRACTS + hash.to_array()) if contract_bytes is None: raise KeyError return contracts.ContractState.deserialize_from_bytes(contract_bytes)
def transfer(self, engine: contracts.ApplicationEngine, account_to: types.UInt160, token_id: bytes) -> bool: if account_to == types.UInt160.zero(): raise ValueError("To account can't be zero") key_token = self.key_token + token_id storage_item = engine.snapshot.storages.try_get(key_token, read_only=True) if storage_item is None: raise ValueError("Token state not found") token_state = NFTState.deserialize_from_bytes(storage_item.value) if token_state.owner != engine.calling_scripthash and engine.checkwitness(token_state.owner): return False if token_state.owner != account_to: token = NFTState.from_stack_item(engine.snapshot.storages.get(key_token, read_only=False)) key_from = self.key_account + token_state.owner.to_array account_state = engine.snapshot.storages.get(key_from).get(NFTAccountState) account_state.remove(token_id) if account_state.balance == 0: engine.snapshot.storages.delete(key_from) token.owner = account_to key_to = self.key_account + account_to.to_array() storage_item = engine.snapshot.storages.try_get(key_to, read_only=False) if storage_item is None: storage_item = storage.StorageItem(NFTAccountState().to_array()) engine.snapshot.storages.put(key_to, storage_item) storage_item.get(NFTAccountState).add(token_id) self.on_transferred(engine, token.owner, token) self._post_transfer(engine, token_state.owner, account_to, token_id) return True
def tokens_of(self, snapshot: storage.Snapshot, owner: types.UInt160) -> interop.IIterator: storage_item_account = snapshot.storages.try_get(self.key_account + owner.to_array(), read_only=True) reference_counter = vm.ReferenceCounter() if storage_item_account is None: return interop.ArrayWrapper(vm.ArrayStackItem(reference_counter)) account = storage_item_account.get(NFTAccountState) tokens: List[vm.StackItem] = list(map(lambda t: vm.ByteStringStackItem(t), account.tokens)) return interop.ArrayWrapper(vm.ArrayStackItem(reference_counter, tokens))
def contract_hash(sender: types.UInt160, checksum: int, name: str) -> types.UInt160: sb = vm.ScriptBuilder() sb.emit(vm.OpCode.ABORT) sb.emit_push(sender.to_array()) sb.emit_push(checksum) sb.emit_push(name) return to_script_hash(sb.to_array())
def test_new_watch_only_account(self): from neo3.core.types import UInt160 for testcase in account_list: account = Account.watch_only( UInt160.from_string(testcase['script_hash'])) self.assertEqual(testcase['address'], account.address) self.assertIsNone(account.encrypted_key) self.assertEqual(testcase['script_hash'], str(account.script_hash)) self.assertIsNone(account.public_key)
def call_from_native(self, calling_scripthash: types.UInt160, hash_: types.UInt160, method: str, args: List[vm.StackItem]) -> None: ctx = self.current_context self._contract_call_internal(hash_, method, contracts.CallFlags.ALL, False, args) self.current_context.calling_scripthash_bytes = calling_scripthash.to_array( ) while self.current_context != ctx: self.step_out()
def is_valid(self, contract_hash: types.UInt160) -> bool: """ Validate if the group has agreed on allowing the specific contract_hash. Args: contract_hash: """ return cryptography.verify_signature( contract_hash.to_array(), self.signature, self.public_key.encode_point(False), cryptography.ECCCurve.SECP256R1)
def script_hash_to_address(script_hash: types.UInt160) -> str: """ Converts the specified script hash to an address. Args: script_hash: script hash to convert. """ version = settings.network.account_version # this is the current Neo's protocol version data = version.to_bytes(1, 'little') + script_hash.to_array() return base58.b58encode_check(data).decode('utf-8')
def test_from_string_various(self): uint160 = UInt160.from_string("11" * 20) expected_data_uint160 = bytearray([0x11] * 20) self.assertEqual(expected_data_uint160, uint160.to_array()) uint256 = UInt256.from_string("11" * 32) expected_data_uint256 = bytearray([0x11] * 32) self.assertEqual(expected_data_uint256, uint256.to_array()) uint160_from_bytes = UInt160.deserialize_from_bytes( expected_data_uint160) self.assertEqual(expected_data_uint160, uint160_from_bytes.to_array()) uint256_from_bytes = UInt256.deserialize_from_bytes( expected_data_uint256) self.assertEqual(expected_data_uint256, uint256_from_bytes.to_array()) # test deserialize with too much data data_uint160 = bytearray(21 * [0x11]) uint160_from_bytes = UInt160.deserialize_from_bytes(data_uint160) self.assertEqual(data_uint160[:20], uint160_from_bytes.to_array()) data_uint256 = bytearray(33 * [0x11]) uint256_from_bytes = UInt256.deserialize_from_bytes(data_uint256) self.assertEqual(expected_data_uint256[:32], uint256_from_bytes.to_array()) # test deserialize with too little data data_uint160 = bytearray(19 * [0x11]) data_uint256 = bytearray(31 * [0x11]) with self.assertRaises(ValueError) as ctx: UInt160.deserialize_from_bytes(data_uint160) self.assertEqual( "Insufficient data 19 bytes is less than the required 20", str(ctx.exception)) with self.assertRaises(ValueError) as ctx: UInt256.deserialize_from_bytes(data_uint256) self.assertEqual( "Insufficient data 31 bytes is less than the required 32", str(ctx.exception))
def _post_transfer(self, engine: contracts.ApplicationEngine, account_from: types.UInt160, account_to: types.UInt160, token_id: bytes) -> None: state = vm.ArrayStackItem(engine.reference_counter) if account_from == types.UInt160.zero(): state.append(vm.NullStackItem()) else: state.append(vm.ByteStringStackItem(account_from.to_array())) if account_to == types.UInt160.zero(): state.append(vm.NullStackItem()) else: state.append(vm.ByteStringStackItem(account_to.to_array())) state.append(vm.IntegerStackItem(1)) state.append(vm.ByteStringStackItem(token_id)) msgrouter.interop_notify(self.hash, "Transfer", state) if account_to != types.UInt160.zero() and \ contracts.ManagementContract().get_contract(engine.snapshot, account_to) is not None: engine.call_from_native(self.hash, account_to, "onNEP17Payment", list(state))
def test_serialize_to_stream(self): data_uint160 = bytearray(20 * [0x11]) data_uint256 = bytearray(32 * [0x11]) uint160 = UInt160(data_uint160) uint256 = UInt256(data_uint256) with serialization.BinaryWriter() as bw: bw.write_serializable(uint160) self.assertEqual(data_uint160, bw._stream.getvalue()) with serialization.BinaryWriter() as bw: bw.write_serializable(uint256) self.assertEqual(data_uint256, bw._stream.getvalue())
def test_deserialize_from_stream(self): data_uint160 = bytearray(20 * [0x11]) data_uint256 = bytearray(32 * [0x11]) with serialization.BinaryReader(data_uint160) as br: # we explicitly call deserialize, instead of br.read_uint160() for coverage uint160 = UInt160.zero() uint160.deserialize(br) self.assertEqual(data_uint160, uint160._data) with serialization.BinaryReader(data_uint256) as br: uint256 = UInt256.zero() uint256.deserialize(br) self.assertEqual(data_uint256, uint256._data)
def parse_single_item(item: Union[Dict, List]): if 'iterator' in item: item = item['iterator'] if item: if type(item[0]['value']) is not list: return [parse_single_item(i) for i in item] else: return { parse_single_item(i['value'][0]): parse_single_item(i['value'][1]) for i in item } _type = item['type'] if _type == 'Any' and 'value' not in item: return None else: value = item['value'] if _type == 'Integer': return int(value) elif _type == 'Boolean': return value elif _type == 'ByteString' or _type == 'Buffer': byte_value = base64.b64decode(value) try: return byte_value.decode() except UnicodeDecodeError: try: len_bytes = len(byte_value) if len_bytes == 20: return Hash160Str.from_UInt160(UInt160(byte_value)) if len_bytes == 32: return Hash256Str.from_UInt256(UInt256(byte_value)) except Exception: pass # may be an N3 address starting with 'N' # TODO: decode to N3 address return byte_value elif _type == 'Array': return [parse_single_item(i) for i in value] elif _type == 'Struct': return tuple([parse_single_item(i) for i in value]) elif _type == 'Map': return { parse_single_item(i['key']): parse_single_item(i['value']) for i in value } elif _type == 'Pointer': return int(value) else: raise ValueError(f'Unknown type {_type}')
def _internal_storage_find(self, contract_script_hash: types.UInt160, key_prefix: bytes): prefix = DBPrefixes.STORAGES + contract_script_hash.to_array() + key_prefix res = {} with self._real_db.iterator(prefix=prefix, include_key=True, include_value=True) as it: for key, value in it: # strip off prefix k = storage.StorageKey.deserialize_from_bytes(key[1:]) v = storage.StorageItem.deserialize_from_bytes(value) res[k] = v # yielding outside of iterator to make sure the LevelDB iterator is closed and not leaking resources for k, v in res.items(): yield k, v
def _unblock_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.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 else: engine.snapshot.storages.delete(storage_key) return True
def is_blocked(self, snapshot: storage.Snapshot, account: types.UInt160) -> bool: """ Check if the account is blocked Transaction from blocked accounts will be rejected by the consensus nodes. """ si = snapshot.storages.try_get(self.key_blocked_account + account.to_array(), read_only=True) if si is None: return False else: return True
def bytes_to_UInt160(bytestring: bytes): return Hash160Str.from_UInt160( UInt160.deserialize_from_bytes(bytestring))
[contract_owner_hash]) print('invoke method balanceOf my NEO:', end=' ') engine.print_results() engine.invoke_method_of_arbitrary_contract(gas.hash, 'balanceOf', [contract_owner_hash]) print('invoke method balanceOf my GAS:', end=' ') engine.print_results() engine.invoke_method_with_print( "deposit", params=[ contract_owner_hash, neo.hash, gas.hash, _30_days_later_ending_milisecond, mint_ratio, 1 ], signers=[ Signer(UInt160.from_string(contract_owner_hash), WitnessScope.GLOBAL) ]) engine.invoke_method_with_print( "deposit", params=[ contract_owner_hash, neo.hash, gas.hash, _30_days_later_ending_milisecond, mint_ratio, 100 ], signers=[ Signer(UInt160.from_string(contract_owner_hash), WitnessScope.GLOBAL) ]) engine.invoke_method_of_arbitrary_contract(neo.hash, 'balanceOf', [contract_owner_hash]) print('invoke method balanceOf my NEO:', end=' ') engine.print_results() engine.get_rToken_balance(rcToken_address, contract_owner_hash)
def balance_of(self, snapshot: storage.Snapshot, owner: types.UInt160) -> vm.BigInteger: storage_item = snapshot.storages.try_get(self.key_account + owner.to_array(), read_only=True) if storage_item is None: return vm.BigInteger.zero() return NFTAccountState.deserialize_from_bytes(storage_item.value).balance
def test_zero(self): uint160 = UInt160.zero() self.assertEqual(20, len(uint160.to_array())) uint256 = UInt256.zero() self.assertEqual(32, len(uint256.to_array()))