def test_transfer_partial_balance_to_account_with_balance(self): gas = contracts.GasToken() manifest = contracts.ContractManifest("contract_name") nef = contracts.NEF(script=b'\x40') state_to = contracts.ContractState( 1, nef, manifest, 0, contract_hash(types.UInt160.zero(), nef.checksum, manifest.name)) account_to = state_to.hash storage_key_to = gas.key_account + account_to account_to_state = gas._state() account_to_state.balance = vm.BigInteger(100) storage_item_to = storage.StorageItem(account_to_state.to_array()) account_from = types.UInt160(b'\x01' * 20) storage_key_from = gas.key_account + account_from account_from_state = gas._state() account_from_state.balance = vm.BigInteger(123) storage_item_from = storage.StorageItem(account_from_state.to_array()) amount = vm.BigInteger(50) engine = self.transfer_helper(gas, account_from, account_to, amount) # ensure the source and destination account have balances engine.snapshot.storages.put(storage_key_from, storage_item_from) engine.snapshot.storages.put(storage_key_to, storage_item_to) transfer_event = () def notify_listener(contract_script_hash, event, state): nonlocal transfer_event transfer_event = (contract_script_hash, event, state) msgrouter.interop_notify += notify_listener engine.execute() self.assertEqual(1, len(engine.result_stack)) result = engine.result_stack.pop() self.assertTrue(result) self.assertEqual(gas.hash, transfer_event[0]) self.assertEqual("Transfer", transfer_event[1]) state_items = list(transfer_event[2]) self.assertEqual(account_from, types.UInt160(state_items[0].to_array())) self.assertEqual(account_to, types.UInt160(state_items[1].to_array())) self.assertEqual(amount, state_items[2].to_biginteger()) # validate from account is deducted by `amount` new_storage_account_from = engine.snapshot.storages.get( storage_key_from) new_account_state_from = gas._state.deserialize_from_bytes( new_storage_account_from.value) self.assertEqual(account_from_state.balance - amount, new_account_state_from.balance) # validate to account is credited with `amount` new_storage_account_to = engine.snapshot.storages.get(storage_key_to) new_account_state_to = gas._state.deserialize_from_bytes( new_storage_account_to.value) self.assertEqual(account_to_state.balance + amount, new_account_state_to.balance)
def test_policy_unblock_account(self): # we've tested the full round trip via "System.Contract.Call" in the test # test_policy_set_and_get_blocked_accounts() # Here we take the shortcut and test the unblock account function directly engine = test_engine(has_snapshot=True) block = test_block(0) engine.snapshot.persisting_block = block engine.invoke_syscall_by_name("Neo.Native.Deploy") # we must add a script_container with valid signature to pass the check_comittee() validation check # in the function itself engine.script_container = TestIVerifiable() validator = settings.standby_committee[0] script_hash = to_script_hash( contracts.Contract.create_multisig_redeemscript(1, [validator])) engine.script_container.script_hashes = [script_hash] policy = contracts.PolicyContract() account_not_found = types.UInt160(data=b'\x11' * 20) account = types.UInt160.zero() self.assertTrue(policy._block_account(engine, account)) self.assertFalse(policy._unblock_account(engine, account_not_found)) self.assertTrue(policy._unblock_account(engine, account)) storage_key = storage.StorageKey(policy.script_hash, policy._PREFIX_BLOCKED_ACCOUNTS) storage_item = engine.snapshot.storages.try_get(storage_key) self.assertIsNotNone(storage_item) self.assertEqual(b'\x00', storage_item.value)
def test_create_multisignature_contract(self): """ var priv_key1 = new byte[] { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, }; var priv_key2 = new byte[] { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, }; var kp1 = new KeyPair(priv_key1); var kp2 = new KeyPair(priv_key2); var c = Contract.CreateMultiSigContract(1, new ECPoint[] {kp1.PublicKey, kp2.PublicKey}); Console.WriteLine(c.Script.ToHexString()); Console.WriteLine(c.ScriptHash.ToArray().ToHexString()); """ expected_script = binascii.unhexlify( b'110c2102550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e240c21026ff03b949241ce1dadd43519e6960e0a85b41a69a05c328103aa2bce1594ca1612419ed0dc3a' ) expected_script_hash = types.UInt160( binascii.unhexlify(b'a72d98260b3dd7d7dd4f733490b9c16b5c352644')) keypair1 = cryptography.KeyPair(private_key=b'\x01' * 32) keypair2 = cryptography.KeyPair(private_key=b'\x02' * 32) contract = contracts.Contract.create_multisig_contract( 1, [keypair1.public_key, keypair2.public_key]) self.assertEqual(expected_script, contract.script) self.assertEqual(str(expected_script_hash), str(contract.script_hash))
def test_create_multisignature_contract(self): """ var priv_key1 = new byte[] { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, }; var priv_key2 = new byte[] { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, }; var kp1 = new KeyPair(priv_key1); var kp2 = new KeyPair(priv_key2); var c = Contract.CreateMultiSigContract(1, new ECPoint[] {kp1.PublicKey, kp2.PublicKey}); """ expected_script = binascii.unhexlify( b'110c2102550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e240c21026ff03b949241ce1dadd43519e6960e0a85b41a69a05c328103aa2bce1594ca16120b41138defaf' ) expected_script_hash = types.UInt160( binascii.unhexlify(b'205bc1a9d199eecb30ab0c1ff027456ce7998e1f')) keypair1 = cryptography.KeyPair(private_key=b'\x01' * 32) keypair2 = cryptography.KeyPair(private_key=b'\x02' * 32) contract = contracts.Contract.create_multisig_contract( 1, [keypair1.public_key, keypair2.public_key]) self.assertEqual(expected_script, contract.script) self.assertEqual(expected_script_hash, contract.script_hash)
def _convert(self, stack_item: vm.StackItem, class_type: Type[object]) -> object: """ convert VM type to native """ if class_type in [vm.StackItem, vm.PointerStackItem, vm.ArrayStackItem, vm.InteropStackItem]: return stack_item elif class_type in [int, vm.BigInteger]: return stack_item.to_biginteger() # mypy bug? https://github.com/python/mypy/issues/9756 elif class_type in [bytes, bytearray]: # type: ignore return stack_item.to_array() elif class_type == bool: return stack_item.to_boolean() elif class_type == types.UInt160: return types.UInt160(data=stack_item.to_array()) elif class_type == types.UInt256: return types.UInt256(data=stack_item.to_array()) elif class_type == str: return stack_item.to_array().decode() elif class_type == cryptography.ECPoint: return cryptography.ECPoint.deserialize_from_bytes(stack_item.to_array()) elif issubclass(class_type, enum.Enum): stack_item = cast(vm.IntegerStackItem, stack_item) # mypy seems to have trouble understanding types that support __int__ return class_type(int(stack_item)) # type: ignore else: raise ValueError(f"Unknown class type, don't know how to convert: {class_type}")
def test_is_valid(self): """ var private_key = new byte[] { 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 }; var bad_signature = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; var kp = new KeyPair(private_key); var cg = new ContractGroup() { PubKey = kp.PublicKey, Signature = bad_signature}; Console.Write(cg.ToJson()); """ bad_signature = b'\x00' * 64 cg = contracts.ContractGroup(self.keypair.public_key, bad_signature) self.assertFalse(cg.is_valid(types.UInt160.zero())) # finally test is_valid() with a keypair we know the private key off contract_hash = b'\x01' * 20 signature = cryptography.sign(contract_hash, self.keypair.private_key) cg2 = contracts.ContractGroup(self.keypair.public_key, signature) self.assertTrue(cg2.is_valid(types.UInt160(contract_hash)))
def compute_script_hash(self) -> types.UInt160: """ Compute the script hash over the NEF script member. """ hash = hashlib.new('ripemd160', hashlib.sha256(self.script).digest()).digest() return types.UInt160(data=hash)
def load_context(self, context: vm.ExecutionContext) -> None: if len(context.scripthash_bytes) == 0: context.scripthash_bytes = to_script_hash(context.script._value).to_array() contract_hash = types.UInt160(data=context.scripthash_bytes) counter = self._invocation_counter.get(contract_hash, 0) self._invocation_counter.update({contract_hash: counter + 1}) super(ApplicationEngine, self).load_context(context)
def current_scripthash(self) -> types.UInt160: """ Get the script hash of the current executing smart contract Note: a smart contract can call other smart contracts. """ if len(self.current_context.scripthash_bytes) == 0: return to_script_hash(self.current_context.script._value) return types.UInt160(self.current_context.scripthash_bytes)
def entry_scripthash(self) -> types.UInt160: """ Get the script hash of the first smart contract loaded into the engine Note: a smart contract can call other smart contracts. """ if len(self.entry_context.scripthash_bytes) == 0: return to_script_hash(self.entry_context.script._value) return types.UInt160(self.entry_context.scripthash_bytes)
def test_checkwitness_helper_other_verifiable(self): engine = test_engine(has_snapshot=True, has_container=False, default_script=True) engine.script_container = TestIVerifiable() self.assertFalse(engine.checkwitness(types.UInt160(b'\x01' * 20))) # our test verifiable has 1 verifiable with a UInt160.zero() hash self.assertTrue(engine.checkwitness(types.UInt160.zero()))
def from_stack_item(cls, stack_item: vm.StackItem): array = cast(vm.ArrayStackItem, stack_item) id = int(array[0].to_biginteger()) update_counter = int(array[1].to_biginteger()) hash_ = types.UInt160(array[2].to_array()) nef = contracts.NEF.deserialize_from_bytes(array[3].to_array()) manifest = contracts.ContractManifest.deserialize_from_bytes( array[4].to_array()) return cls(id, nef, manifest, update_counter, hash_)
def test_transfer_full_balance(self): gas = contracts.GasToken() manifest = contracts.ContractManifest() manifest.features = contracts.ContractFeatures.PAYABLE state_to = storage.ContractState(b'\x00' * 20, manifest) account_to = state_to.script_hash() account_from = types.UInt160(b'\x01' * 20) storage_key_from = storage.StorageKey( gas.script_hash, gas._PREFIX_ACCOUNT + account_from.to_array()) account_from_state = gas._state() account_from_state.balance = vm.BigInteger(123) storage_item_from = storage.StorageItem(account_from_state.to_array()) amount = account_from_state.balance engine = self.transfer_helper(gas, account_from, account_to, amount) # ensure the destination contract exists engine.snapshot.contracts.put(state_to) # ensure the source account has balance engine.snapshot.storages.put(storage_key_from, storage_item_from) transfer_event = () def notify_listener(contract_script_hash, event, state): nonlocal transfer_event transfer_event = (contract_script_hash, event, state) msgrouter.interop_notify += notify_listener engine.execute() self.assertEqual(1, len(engine.result_stack)) result = engine.result_stack.pop() self.assertTrue(result) self.assertEqual(gas.script_hash, transfer_event[0]) self.assertEqual("Transfer", transfer_event[1]) state_items = list(transfer_event[2]) self.assertEqual(account_from, types.UInt160(state_items[0].to_array())) self.assertEqual(account_to, types.UInt160(state_items[1].to_array())) self.assertEqual(amount, state_items[2].to_biginteger()) # test that the source account is no longer present in storage as the balance is zero self.assertIsNone(engine.snapshot.storages.try_get(storage_key_from))
def test_transfer_full_balance(self): gas = contracts.GasToken() manifest = contracts.ContractManifest("contract_name_to") nef = contracts.NEF(script=b'\x40') state_to = contracts.ContractState( 1, nef, manifest, 0, contract_hash(types.UInt160.zero(), nef.checksum, manifest.name)) account_to = state_to.hash account_from = types.UInt160(b'\x01' * 20) storage_key_from = gas.key_account + account_from account_from_state = gas._state() account_from_state.balance = vm.BigInteger(123) storage_item_from = storage.StorageItem(account_from_state.to_array()) amount = account_from_state.balance engine = self.transfer_helper(gas, account_from, account_to, amount) # ensure the source account has balance engine.snapshot.storages.put(storage_key_from, storage_item_from) transfer_event = () def notify_listener(contract_script_hash, event, state): nonlocal transfer_event transfer_event = (contract_script_hash, event, state) msgrouter.interop_notify += notify_listener engine.execute() self.assertEqual(1, len(engine.result_stack)) result = engine.result_stack.pop() self.assertTrue(result) self.assertEqual(gas.hash, transfer_event[0]) self.assertEqual("Transfer", transfer_event[1]) state_items = list(transfer_event[2]) self.assertEqual(account_from, types.UInt160(state_items[0].to_array())) self.assertEqual(account_to, types.UInt160(state_items[1].to_array())) self.assertEqual(amount, state_items[2].to_biginteger()) # test that the source account is no longer present in storage as the balance is zero self.assertIsNone(engine.snapshot.storages.try_get(storage_key_from))
def to_script_hash(data: bytes) -> types.UInt160: """ Create a script hash based on the input data. Args: data: data to hash """ intermediate_data = hashlib.sha256(data).digest() data_ = hashlib.new('ripemd160', intermediate_data).digest() return types.UInt160(data_)
def test_contract_create_standard_account(self): keypair = cryptography.KeyPair(b'\x01' * 32) engine = test_engine() engine.push(vm.ByteStringStackItem(keypair.public_key.to_array())) engine.invoke_syscall_by_name("System.Contract.CreateStandardAccount") engine.execute() self.assertEqual(1, len(engine.result_stack)) signature_redeem_script = contracts.Contract.create_signature_redeemscript( keypair.public_key) result_item = types.UInt160(engine.result_stack.pop().to_array()) self.assertEqual(to_script_hash(signature_redeem_script), result_item)
def do_checkwitness(engine: contracts.ApplicationEngine, data: bytes) -> bool: if len(data) == 20: hash_ = types.UInt160(data) elif len(data) == 33: redeemscript = contracts.Contract.create_signature_redeemscript( cryptography.ECPoint.deserialize_from_bytes(data)) hash_ = to_script_hash(redeemscript) else: raise ValueError("Supplied CheckWitness data is not a valid hash") return engine.checkwitness(hash_)
def calling_scripthash(self) -> types.UInt160: """ Get the script hash of the smart contract that called the current executing smart contract. Note: a smart contract can call other smart contracts. Raises: ValueError: if the current executing contract has not been called by another contract. """ if len(self.current_context.calling_scripthash_bytes) == 0: raise ValueError("Cannot retrieve calling script_hash - current context has not yet been called") return types.UInt160(self.current_context.calling_scripthash_bytes)
def test_equals(self): manifest = contracts.ContractManifest() nef = contracts.NEF() state = contracts.ContractState(1, nef, manifest, 0, types.UInt160.zero()) clone = state.clone() self.assertEqual(state, clone) nef2 = contracts.NEF() state2 = contracts.ContractState(2, nef2, manifest, 0, types.UInt160(b'\x01' * 20)) self.assertNotEqual(state, state2) self.assertNotEqual(state, None) self.assertNotEqual(state, object())
def deserialize_unsigned(self, reader: serialization.BinaryReader) -> None: (self.version, prev_hash, merkleroot, self.timestamp, self.index, self.primary_index, consensus) = struct.unpack("<I32s32sQIB20s", reader._stream.read(101)) if self.primary_index >= len(settings.standby_validators): raise ValueError(f"Deserialization error - primary index {self.primary_index} exceeds validator count " f"{len(settings.standby_validators)}") self.prev_hash = types.UInt256(prev_hash) self.merkle_root = types.UInt256(merkleroot) self.next_consensus = types.UInt160(consensus)
def test_policy_set_and_get_blocked_accounts(self): 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 sb = vm.ScriptBuilder() sb.emit_syscall(syscall_name_to_int("Neo.Native.Deploy")) # set or we won't pass the check_comittee() in the policy contract function implementations engine.script_container = TestIVerifiable() validator = settings.standby_committee[0] script_hash = to_script_hash( contracts.Contract.create_multisig_redeemscript(1, [validator])) engine.script_container.script_hashes = [script_hash] # first we setup the stack for calling `blockAccount` # push data to create a vm.Array holding 20 bytes for the UInt160 Account parameter of the _block_account function. sb.emit_push(b'\x11' * 20) sb.emit(vm.OpCode.PUSH1) sb.emit(vm.OpCode.PACK) sb.emit_push("blockAccount") sb.emit_push(contracts.PolicyContract().script_hash.to_array()) sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) # next we call `getBlockedAccounts` sb.emit_contract_call(contracts.PolicyContract().script_hash, "getBlockedAccounts") script = vm.Script(sb.to_array()) engine.load_script(script) # storing the current script in a contract otherwise "System.Contract.Call" will fail its checks engine.snapshot.contracts.put( storage.ContractState(sb.to_array(), contracts.ContractManifest())) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(2, len(engine.result_stack)) get_blocked_accounts_result = engine.result_stack.pop() set_blocked_accounts_result = engine.result_stack.pop() self.assertTrue(set_blocked_accounts_result.to_boolean()) self.assertIsInstance(get_blocked_accounts_result, vm.InteropStackItem) stored_accounts = get_blocked_accounts_result.get_object() self.assertEqual(1, len(stored_accounts)) expected_account = types.UInt160(data=b'\x11' * 20) self.assertEqual(expected_account, stored_accounts[0])
def address_to_script_hash(address: str) -> types.UInt160: """ Converts the specified address to a script hash. Args: address: address to convert Raises: ValueError: if the length of data (address value in bytes) is not valid. ValueError: if the account version is not valid. """ Account.validate_address(address) data = base58.b58decode_check(address) return types.UInt160(data[1:])
def test_is_allowed_based_on_hash(self): # We test the group permissions where all methods are allowed to be called # if contract_hash is valid. dummy_contract_hash = types.UInt160.zero() contract_state = contracts.ContractState(1, contracts.NEF(), contracts.ContractManifest(), 0, dummy_contract_hash) # setup an allowed permission for a contract with UInt160.zero hash for all methods cpd = contracts.ContractPermissionDescriptor( contract_hash=dummy_contract_hash) cp = contracts.ContractPermission( contract=cpd, methods=contracts.WildcardContainer.create_wildcard()) self.assertTrue(cp.is_allowed(contract_state, "dummy_method")) # now create a different contract hash and verify it does not give permission contract_state.hash = types.UInt160(b'\x01' * 20) self.assertFalse(cp.is_allowed(contract_state, "dummy_method"))
def test_checkwitness_with_public_key(self): kp = cryptography.KeyPair(b'\x01' * 32) redeemscript = contracts.Contract.create_signature_redeemscript( kp.public_key) intermediate_data = hashlib.sha256(redeemscript).digest() data = hashlib.new('ripemd160', intermediate_data).digest() hash_ = types.UInt160(data=data) engine = test_engine(has_snapshot=True, has_container=False, default_script=True) engine.script_container = TestIVerifiable() engine.script_container.script_hashes = [hash_] engine.push(vm.ByteStringStackItem(kp.public_key.to_array())) engine.invoke_syscall_by_name("System.Runtime.CheckWitness") self.assertEqual(1, len(engine.current_context.evaluation_stack)) item = engine.pop() self.assertTrue(item.to_boolean())
def test_runtime_getnotifications(self): engine = test_engine() target_hash = types.UInt160.zero() state = vm.ArrayStackItem(engine.reference_counter) notif1 = (object(), target_hash, b'notif1', state) notif2 = (object(), types.UInt160(b'\x01' * 20), b'notif2', state) notif3 = (object(), target_hash, b'notif3', state) engine.notifications = [notif1, notif2, notif3] engine.push(vm.ByteStringStackItem(target_hash.to_array())) engine.invoke_syscall_by_name("System.Runtime.GetNotifications") self.assertEqual(1, len(engine.current_context.evaluation_stack)) notification_items = engine.pop() item1 = notification_items[0] item2 = notification_items[1] self.assertEqual(item1[0].to_array(), types.UInt160.zero().to_array()) self.assertEqual(item1[1].to_array(), b'notif1') self.assertEqual(item2[0].to_array(), types.UInt160.zero().to_array()) self.assertEqual(item2[1].to_array(), b'notif3')
def test_policy_unblock_account(self): engine = test_engine(has_snapshot=True) block = test_block(0) engine.snapshot.persisting_block = block # we must add a script_container with valid signature to pass the check_comittee() validation check # in the function itself engine.script_container = TestIVerifiable() validator = settings.standby_committee[0] script_hash = to_script_hash( contracts.Contract.create_multisig_redeemscript(1, [validator])) engine.script_container.script_hashes = [script_hash] policy = contracts.PolicyContract() account_not_found = types.UInt160(data=b'\x11' * 20) account = types.UInt160.zero() self.assertTrue(policy._block_account(engine, account)) self.assertFalse(policy._unblock_account(engine, account_not_found)) self.assertTrue(policy._unblock_account(engine, account)) storage_key = policy.key_blocked_account + account storage_item = engine.snapshot.storages.try_get(storage_key) self.assertIsNone(storage_item)
def deserialize_unsigned(self, reader: serialization.BinaryReader) -> None: """ Deserialize the unsigned data part of the object from a binary stream. Args: reader: instance. Raises: ValueError: if the primary_index field is greater than the configured consensus validator count. """ (self.version, prev_hash, merkleroot, self.timestamp, self.index, self.primary_index, consensus) = struct.unpack("<I32s32sQIB20s", reader._stream.read(101)) if self.primary_index >= len(settings.standby_validators): raise ValueError(f"Deserialization error - primary index {self.primary_index} exceeds validator count " f"{len(settings.standby_validators)}") self.prev_hash = types.UInt256(prev_hash) self.merkle_root = types.UInt256(merkleroot) self.next_consensus = types.UInt160(consensus)
def script_hash(self) -> types.UInt160: """ Get the script hash based on the verification script.""" intermediate_data = hashlib.sha256(self.verification_script).digest() data = hashlib.new('ripemd160', intermediate_data).digest() return types.UInt160(data=data)
def script_hash(self) -> types.UInt160: """ Get the script hash.""" intermediate_data = hashlib.sha256(self.script).digest() data = hashlib.new('ripemd160', intermediate_data).digest() return types.UInt160(data=data)
def test_contract_call_exceptions(self): engine = test_engine(has_snapshot=True, default_script=False) engine.load_script(vm.Script(hello_world_nef.script)) # can't find contract with self.assertRaises(ValueError) as context: engine._contract_call_internal( types.UInt160.zero(), "valid_method", contracts.CallFlags.ALL, False, vm.ArrayStackItem(engine.reference_counter)) self.assertEqual("[System.Contract.Call] Can't find target contract", str(context.exception)) fake_contract_hash = types.UInt160(b'\x01' * 20) target_contract = contracts.ContractState(0, contract3_nef, contract3_manifest, 0, fake_contract_hash) engine.snapshot.contracts.put(target_contract) # modify the manifest of the current executing contract to only allow to call 1 specific method on other contracts new_current_manifest = deepcopy(hello_world_manifest) new_current_manifest.permissions = [ contracts.ContractPermission( contracts.ContractPermissionDescriptor( ), # allow to call any contract contracts.WildcardContainer( ['method_aaaa']) # allowing to call the listed method only ) ] fake_contract_hash2 = types.UInt160(b'\x02' * 20) new_current_contract = contracts.ContractState(1, hello_world_nef, new_current_manifest, 0, fake_contract_hash2) engine.snapshot.contracts.put(new_current_contract) with self.assertRaises(ValueError) as context: engine._contract_call_internal( target_contract.hash, "invalid_method", contracts.CallFlags.ALL, False, vm.ArrayStackItem(engine.reference_counter)) self.assertEqual( "[System.Contract.Call] Method 'invalid_method' with 0 arguments does not exist on target contract", str(context.exception)) # restore current contract to its original form and try to call a non-existing contract current_contract = contracts.ContractState(1, hello_world_nef, hello_world_manifest, 1, fake_contract_hash2) engine.snapshot.contracts.delete(new_current_contract.hash) engine.snapshot.contracts.put(current_contract) with self.assertRaises(ValueError) as context: engine._contract_call_internal( target_contract.hash, "invalid_method", contracts.CallFlags.ALL, False, vm.ArrayStackItem(engine.reference_counter)) self.assertEqual( "[System.Contract.Call] Method 'invalid_method' with 0 arguments does not exist on target contract", str(context.exception)) # call the target method with invalid number of arguments array = vm.ArrayStackItem(engine.reference_counter) array.append([vm.NullStackItem(), vm.NullStackItem()]) with self.assertRaises(ValueError) as context: engine._contract_call_internal(target_contract.hash, "test_func", contracts.CallFlags.ALL, False, array) self.assertEqual( "[System.Contract.Call] Method 'test_func' with 2 arguments does not exist on target contract", str(context.exception))