def test_can_call(self): # create a default contract, which is allowed to call any other contract and any other method cm = contracts.ContractManifest() target_manifest = contracts.ContractManifest() target_manifest.abi.contract_hash = types.UInt160.from_string("11" * 20) self.assertTrue(cm.can_call(target_manifest, "some_method")) # now add a permission that allows all methods, but for a different contract hash contract_hash = types.UInt160.from_string("22" * 20) cpd = contracts.ContractPermissionDescriptor( contract_hash=contract_hash) cp = contracts.ContractPermission( contract=cpd, methods=contracts.WildcardContainer.create_wildcard()) cm.permissions = [cp] self.assertFalse(cm.can_call(target_manifest, "some_method")) # now change the permissions (specifically the contract_hash) to allow calling new_contract_hash = types.UInt160.zero() cpd = contracts.ContractPermissionDescriptor( contract_hash=new_contract_hash) cp = contracts.ContractPermission( contract=cpd, methods=contracts.WildcardContainer.create_wildcard()) cm.permissions = [cp] self.assertTrue(cm.can_call(target_manifest, "some_method"))
def test_getcallingscripthash(self): """ Testing this requires 2 contracts 1) caller_contract: uses a System.Contract.Call to call callee_contract. This will set the calling script hash on the ExecutionContext of the callee_contract 2) callee_contract: uses a System.Runtime.GetCallingScriptHash to return the calling script """ sb = vm.ScriptBuilder() sb.emit_syscall( syscall_name_to_int("System.Runtime.GetCallingScriptHash")) callee_contract_script = sb.to_array() callee_nef = contracts.NEF(script=callee_contract_script) callee_contract_name = "callee_contract" callee_manifest = contracts.ContractManifest(callee_contract_name) callee_manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY, True) ] callee_contract_hash = contract_hash(types.UInt160.zero(), callee_nef.checksum, callee_contract_name) callee_contract = contracts.ContractState(1, callee_nef, callee_manifest, 0, callee_contract_hash) # create caller_contract script sb = vm.ScriptBuilder() sb.emit_dynamic_call(callee_contract.hash, "test_func") caller_script = sb.to_array() caller_nef = contracts.NEF(script=caller_script) caller_contract_name = "caller_contract" caller_manifest = contracts.ContractManifest(caller_contract_name) caller_contract_hash = contract_hash(types.UInt160.zero(), caller_nef.checksum, caller_contract_name) caller_contract = contracts.ContractState(2, caller_nef, caller_manifest, 0, caller_contract_hash) engine = test_engine(has_snapshot=True, default_script=False) engine.snapshot.contracts.put(callee_contract) engine.snapshot.contracts.put(caller_contract) engine.load_script(vm.Script(caller_script)) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertEqual( to_script_hash(caller_nef.script).to_array(), item.to_array())
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_storage_put_new(self): # see `test_storage_get_key_not_found()` for a description on why the storage is setup with a script as is # setup engine = test_engine(has_snapshot=True) script = vm.ScriptBuilder() script.emit(vm.OpCode.PUSH2) # storage put value script.emit(vm.OpCode.PUSH1) # storage put key script.emit_syscall(syscall_name_to_int("System.Storage.GetContext")) script.emit_syscall(syscall_name_to_int("System.Storage.Put")) engine.load_script(vm.Script(script.to_array())) nef = contracts.NEF(script=script.to_array()) manifest = contracts.ContractManifest(f"contractname1") manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY, True) ] hash_ = to_script_hash(nef.script) contract = contracts.ContractState(1, nef, manifest, 0, hash_) engine.snapshot.contracts.put(contract) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) storage_key = storage.StorageKey(1, b'\x01') item = engine.snapshot.storages.try_get(storage_key) self.assertIsNotNone(item) self.assertEqual(b'\x02', item.value)
def test_is_valid(self): # create a contract cm = contracts.ContractManifest("test_contract") method1 = contracts.ContractMethodDescriptor( name="main_entry", offset=0, parameters=[], return_type=contracts.ContractParameterType.INTEGER, safe=True) cm.abi.methods = [method1] # A contract hash is normally created from a combination of transaction sender (UInt160), NEF checksum and manifest.name # For this test we'll keep it simple and pretend that hash is all zeros dummy_contract_hash = types.UInt160.zero() # a "default" contract has no groups data, which is the same as always allow self.assertTrue(cm.is_valid(dummy_contract_hash)) # now try to add a malicious group member (meaning; the member did not actually sign the ABI) private_key = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' keypair = cryptography.KeyPair(private_key) bad_signature = bytes(64) cm.groups = [ contracts.ContractGroup(keypair.public_key, bad_signature) ] # this time validation should fail self.assertFalse(cm.is_valid(dummy_contract_hash)) # Finally test with a group member that did sign the ABI good_signature = cryptography.sign(dummy_contract_hash.to_array(), keypair.private_key) cm.groups = [ contracts.ContractGroup(keypair.public_key, good_signature) ] self.assertTrue(cm.is_valid(dummy_contract_hash))
def test_is_allowed_based_on_group(self): # We test the group permissions where all methods are allowed to be called # if the 'groups' member is valid. private_key = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' keypair = cryptography.KeyPair(private_key) dummy_contract_hash = types.UInt160.from_string("01" * 20) contract_state = contracts.ContractState(1, contracts.NEF(), contracts.ContractManifest(), 0, dummy_contract_hash) signature = cryptography.sign(contract_state.hash.to_array(), keypair.private_key) contract_state.manifest.groups = [ contracts.ContractGroup(keypair.public_key, signature) ] cpd = contracts.ContractPermissionDescriptor(group=keypair.public_key) cp = contracts.ContractPermission( contract=cpd, methods=contracts.WildcardContainer.create_wildcard()) self.assertTrue(cp.is_allowed(contract_state, "dummy_method")) # now modify the manifest to have a different `groups` attribute such that validation fails public_key = cryptography.ECPoint.deserialize_from_bytes( b'\x00') # ECPoint.Infinity contract_state.manifest.groups = [ contracts.ContractGroup(public_key, signature) ] self.assertFalse(cp.is_allowed(contract_state, "dummy_method"))
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 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 test_contractstate_clone(self): manifest = contracts.ContractManifest() nef = contracts.NEF() state = contracts.ContractState(1, nef, manifest, 0, types.UInt160.zero()) clone = state.clone() self.assertNotEqual(id(state), id(clone)) self.assertNotEqual(id(state.manifest), id(clone.manifest))
def test_from_json(self): expected_json = deepcopy(self.expected_json) cm = contracts.ContractManifest.from_json(expected_json) default = contracts.ContractManifest() self.assertEqual(default.groups, cm.groups) self.assertEqual(default.permissions, cm.permissions) self.assertEqual(default.trusts, cm.trusts) self.assertEqual(default.extra, cm.extra)
def test_checkwitness_called_by_entry(self): """ We need to setup 2 contracts 1) caller_contract: uses a System.Contract.Call to call callee_contract. This will set the calling script hash on the ExecutionContext of the callee_contract 2) callee_contract: uses a System.Runtime.CheckWitness """ engine = test_engine(has_snapshot=True, has_container=False, default_script=False) tx = test_tx() tx.signers[0].scope = payloads.WitnessScope.CALLED_BY_ENTRY engine.script_container = tx sb = vm.ScriptBuilder() sb.emit_push(tx.sender.to_array()) sb.emit_syscall(syscall_name_to_int("System.Runtime.CheckWitness")) callee_contract_script = sb.to_array() callee_manifest = contracts.ContractManifest( contract_hash=to_script_hash(callee_contract_script)) callee_manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY) ] callee_contract = storage.ContractState(callee_contract_script, callee_manifest) sb = vm.ScriptBuilder() sb.emit(vm.OpCode.NEWARRAY0) # args (empty array) sb.emit_push('test_func') # target method name sb.emit_push(callee_contract.script_hash().to_array()) # contract hash sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) caller_script = sb.to_array() caller_manifest = contracts.ContractManifest( contract_hash=to_script_hash(caller_script)) caller_contract = storage.ContractState(caller_script, caller_manifest) engine.snapshot.contracts.put(callee_contract) engine.snapshot.contracts.put(caller_contract) engine.load_script(vm.Script(caller_script)) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertTrue(item.to_boolean())
def test_get_invocation_counter_ok(self): """ We need to setup 2 contracts 1) caller_contract: uses a System.Contract.Call to call callee_contract. This will increase the invocation counter of the callee contract 2) callee_contract: uses a System.Runtime.GetInvocationCounter """ engine = test_engine(has_snapshot=True, has_container=False, default_script=False) sb = vm.ScriptBuilder() sb.emit_syscall( syscall_name_to_int("System.Runtime.GetInvocationCounter")) callee_contract_script = sb.to_array() callee_nef = contracts.NEF(script=callee_contract_script) callee_manifest = contracts.ContractManifest("contract1") callee_manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY, True) ] callee_contract = contracts.ContractState( 1, callee_nef, callee_manifest, 0, contract_hash(types.UInt160.zero(), callee_nef.checksum, callee_manifest.name)) sb = vm.ScriptBuilder() sb.emit_dynamic_call(callee_contract.hash, "test_func") caller_script = sb.to_array() caller_nef = contracts.NEF(script=caller_script) caller_manifest = contracts.ContractManifest("contract2") caller_contract = contracts.ContractState( 2, caller_nef, caller_manifest, 0, contract_hash(types.UInt160.zero(), caller_nef.checksum, caller_manifest.name)) engine.snapshot.contracts.put(callee_contract) engine.snapshot.contracts.put(caller_contract) engine.load_script(vm.Script(caller_script)) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertEqual(1, int(item))
def test_equals(self): manifest = contracts.ContractManifest() state = storage.ContractState(b'\x01', manifest) clone = state.clone() self.assertEqual(state, clone) state2 = storage.ContractState(b'\x02', manifest) self.assertNotEqual(state, state2) self.assertNotEqual(state, None) self.assertNotEqual(state, object())
def test_create(self): cm = contracts.ContractManifest("test_contract") method1 = contracts.ContractMethodDescriptor( name="main_entry", offset=0, parameters=[], return_type=contracts.ContractParameterType.INTEGER, safe=True) cm.abi.methods = [method1] self.assertEqual(self.expected_json, cm.to_json())
def test_getcallingscripthash(self): """ Testing this requires 2 contracts 1) caller_contract: uses a System.Contract.Call to call callee_contract. This will set the calling script hash on the ExecutionContext of the callee_contract 2) callee_contract: uses a System.Runtime.GetCallingScriptHash to return the calling script """ sb = vm.ScriptBuilder() sb.emit_syscall( syscall_name_to_int("System.Runtime.GetCallingScriptHash")) callee_contract_script = sb.to_array() callee_manifest = contracts.ContractManifest( contract_hash=to_script_hash(callee_contract_script)) callee_manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY) ] callee_contract = storage.ContractState(callee_contract_script, callee_manifest) # create caller_contract script sb = vm.ScriptBuilder() sb.emit(vm.OpCode.NEWARRAY0) # args (empty array) sb.emit_push('test_func') # target method name sb.emit_push(callee_contract.script_hash().to_array()) # contract hash sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) caller_script = sb.to_array() caller_manifest = contracts.ContractManifest( contract_hash=to_script_hash(caller_script)) caller_contract = storage.ContractState(caller_script, caller_manifest) engine = test_engine(has_snapshot=True, default_script=False) engine.snapshot.contracts.put(callee_contract) engine.snapshot.contracts.put(caller_contract) engine.load_script(vm.Script(caller_script)) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertEqual(caller_contract.script_hash().to_array(), item.to_array())
def test_get_invocation_counter_ok(self): """ We need to setup 2 contracts 1) caller_contract: uses a System.Contract.Call to call callee_contract. This will increase the invocation counter of the callee contract 2) callee_contract: uses a System.Runtime.GetInvocationCounter """ engine = test_engine(has_snapshot=True, has_container=False, default_script=False) sb = vm.ScriptBuilder() sb.emit_syscall( syscall_name_to_int("System.Runtime.GetInvocationCounter")) callee_contract_script = sb.to_array() callee_manifest = contracts.ContractManifest( contract_hash=to_script_hash(callee_contract_script)) callee_manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY) ] callee_contract = storage.ContractState(callee_contract_script, callee_manifest) sb = vm.ScriptBuilder() sb.emit(vm.OpCode.NEWARRAY0) # args (empty array) sb.emit_push('test_func') # target method name sb.emit_push(callee_contract.script_hash().to_array()) # contract hash sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) caller_script = sb.to_array() caller_manifest = contracts.ContractManifest( contract_hash=to_script_hash(caller_script)) caller_contract = storage.ContractState(caller_script, caller_manifest) engine.snapshot.contracts.put(callee_contract) engine.snapshot.contracts.put(caller_contract) engine.load_script(vm.Script(caller_script)) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertEqual(1, int(item))
def setUp(self) -> None: self.RET = b'\x40' self.manifest = contracts.ContractManifest("contract_name") self.nef = contracts.NEF(script=self.RET) self.contract_hash = to_script_hash(self.nef.script) self.contract = contracts.ContractState(1, self.nef, self.manifest, 0, self.contract_hash) self.contract.manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY, True) ]
def init(self): self._methods: Dict[int, _NativeMethodMeta] = {} # offset, meta self._management = contracts.ManagementContract() self._neo = contracts.NeoToken() self._gas = contracts.GasToken() self._policy = contracts.PolicyContract() self._oracle = contracts.OracleContract() self._ledger = contracts.LedgerContract() self._role = contracts.DesignationContract() self._crypto = contracts.CryptoContract() self._stdlib = contracts.StdLibContract() # Find all methods that have been augmented by the @register decorator # and turn them into methods that can be called by VM scripts methods_meta = [] for pair in inspect.getmembers(self, lambda m: hasattr(m, "native_call")): methods_meta.append(_NativeMethodMeta(pair[1])) methods_meta.sort( key=lambda x: (x.descriptor.name, len(x.descriptor.parameters))) sb = vm.ScriptBuilder() for meta in methods_meta: meta.descriptor.offset = len(sb) sb.emit_push(0) self._methods.update({len(sb): meta}) sb.emit_syscall(1736177434) # "System.Contract.CallNative" sb.emit(vm.OpCode.RET) self._script: bytes = sb.to_array() self.nef = contracts.NEF("neo-core-v3.0", self._script) sender = types.UInt160.zero() # OpCode.PUSH1 sb = vm.ScriptBuilder() sb.emit(vm.OpCode.ABORT) sb.emit_push(sender.to_array()) sb.emit_push(0) sb.emit_push(self.service_name()) self._hash: types.UInt160 = to_script_hash(sb.to_array()) self._manifest: contracts.ContractManifest = contracts.ContractManifest( ) self._manifest.name = self.service_name() self._manifest.abi.methods = list( map(lambda m: m.descriptor, methods_meta)) if self._id != NativeContract._id: self._contracts.update({self.service_name(): self}) self._contract_hashes.update({self._hash: self}) self.active_block_index = settings.native_contract_activation.get( self.service_name, 0)
def test_to_account_not_payable(self): gas = contracts.GasToken() state = storage.ContractState(b'\x00', contracts.ContractManifest()) engine = self.transfer_helper(gas, types.UInt160.zero(), state.script_hash(), vm.BigInteger(1)) # default manifest is not payable engine.snapshot.contracts.put(state) engine.execute() self.assertEqual(1, len(engine.result_stack)) result = engine.result_stack.pop() self.assertFalse(result)
def test_policy_block_account_and_is_blocked(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() # 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(15) # call flags sb.emit_push("blockAccount") sb.emit_push(contracts.PolicyContract().hash.to_array()) sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) # next we call `isBlocked` sb.emit_push(b'\x11' * 20) sb.emit(vm.OpCode.PUSH1) sb.emit(vm.OpCode.PACK) sb.emit_push(15) # call flags sb.emit_push("isBlocked") sb.emit_push(contracts.PolicyContract().hash.to_array()) sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) 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 nef = contracts.NEF(script=sb.to_array()) manifest = contracts.ContractManifest("test_contract") sender = engine.script_container.script_hashes[0] contract = contracts.ContractState( 1, nef, manifest, 0, contract_hash(sender, nef.checksum, manifest.name)) engine.snapshot.contracts.put(contract) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(2, len(engine.result_stack)) get_is_blocked_result = engine.result_stack.pop() set_blocked_account_result = engine.result_stack.pop() self.assertTrue(set_blocked_account_result.to_boolean()) self.assertTrue(get_is_blocked_result.to_boolean())
def test_deserialization(self): # this assumes test_serialization() passes cm = contracts.ContractManifest("test_contract") method1 = contracts.ContractMethodDescriptor( name="main_entry", offset=0, parameters=[], return_type=contracts.ContractParameterType.INTEGER, safe=True) cm.abi.methods = [method1] cm_deserialized = contracts.ContractManifest.deserialize_from_bytes( cm.to_array()) self.assertEqual(cm, cm_deserialized)
def test_serialize(self): # if test_create() passes, then we know `to_json()` is ok, which serialize internally uses cm = contracts.ContractManifest("test_contract") method1 = contracts.ContractMethodDescriptor( name="main_entry", offset=0, parameters=[], return_type=contracts.ContractParameterType.INTEGER, safe=True) cm.abi.methods = [method1] with serialization.BinaryReader(cm.to_array()) as br: data = br.read_var_string() self.assertDictEqual(self.expected_json, json.loads(data))
def test_transfer_from_empty_account(self): gas = contracts.GasToken() manifest = contracts.ContractManifest() manifest.features = contracts.ContractFeatures.PAYABLE state = storage.ContractState(b'\x00', manifest) engine = self.transfer_helper(gas, types.UInt160.zero(), state.script_hash(), vm.BigInteger(1)) engine.snapshot.contracts.put(state) engine.execute() self.assertEqual(1, len(engine.result_stack)) result = engine.result_stack.pop() self.assertFalse(result)
def test_contract_is_standard_ok(self): keypair = cryptography.KeyPair(b'\x01' * 32) sig_contract = contracts.Contract.create_signature_contract( keypair.public_key) engine = test_engine(has_snapshot=True) contract = storage.ContractState( sig_contract.script, contracts.ContractManifest(sig_contract.script_hash)) engine.snapshot.contracts.put(contract) engine.push(vm.ByteStringStackItem(contract.script_hash().to_array())) engine.invoke_syscall_by_name("System.Contract.IsStandard") engine.execute() self.assertEqual(True, engine.result_stack.pop().to_boolean())
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 test_to_json_with_trusts_safemethods_extra(self): # create a default manifest m = contracts.ContractManifest(types.UInt160.zero()) t1 = types.UInt160.from_string("01" * 20) t2 = types.UInt160.from_string("02" * 20) m.trusts = contracts.WildcardContainer(data=[t1, t2]) m.safe_methods = contracts.WildcardContainer(data=["safe1"]) m.extra = False json_out = m.to_json() self.assertIn("0x" + str(t1), json_out['trusts']) self.assertIn("0x" + str(t2), json_out['trusts']) self.assertIn("safe1", json_out['safemethods']) self.assertFalse(json_out['extra'])
def test_from_json(self): expected_json = deepcopy(self.expected_json) # we update the defaults to also test the features new_features = {'storage': True, 'payable': True} expected_json['features'] = new_features cm = contracts.ContractManifest.from_json(expected_json) default = contracts.ContractManifest(types.UInt160.zero()) self.assertEqual(default.groups, cm.groups) self.assertIn(contracts.ContractFeatures.HAS_STORAGE, cm.features) self.assertIn(contracts.ContractFeatures.PAYABLE, cm.features) self.assertEqual(default.permissions, cm.permissions) self.assertEqual(default.trusts, cm.trusts) self.assertEqual(default.safe_methods, cm.safe_methods) self.assertEqual(default.extra, cm.extra)
def test_transfer_from_empty_account(self): gas = contracts.GasToken() manifest = contracts.ContractManifest("test_contract2") nef = contracts.NEF(script=b'\x40') state = contracts.ContractState( 2, nef, manifest, 0, contract_hash(types.UInt160.zero(), nef.checksum, manifest.name)) engine = self.transfer_helper(gas, types.UInt160.zero(), state.hash, vm.BigInteger(1)) engine.snapshot.contracts.put(state) engine.execute() self.assertEqual(1, len(engine.result_stack)) result = engine.result_stack.pop() self.assertFalse(result)
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 test_contract_is_standard_fail2(self): # can find contract, but is not a signature contract engine = test_engine(has_snapshot=True) # create a non-standard contract script = b'\x01\x02\x03' script_hash = to_script_hash(script) manifest = contracts.ContractManifest(script_hash) contract = storage.ContractState(script, manifest) engine.snapshot.contracts.put(contract) # push function argument and call engine.push(vm.ByteStringStackItem(script_hash.to_array())) engine.invoke_syscall_by_name("System.Contract.IsStandard") engine.execute() self.assertEqual(False, engine.result_stack.pop().to_boolean())