def test_itoa(self): engine = test_engine(has_snapshot=True) original_item = 100 base = 10 sb = vm.ScriptBuilder() sb.emit_dynamic_call_with_args(contracts.StdLibContract().hash, "itoa", [original_item, base]) engine.load_script(vm.Script(sb.to_array())) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) item = engine.result_stack.pop() self.assertEqual('100', item.to_array().decode('utf-8')) engine = test_engine(has_snapshot=True) base = 16 sb = vm.ScriptBuilder() sb.emit_dynamic_call_with_args(contracts.StdLibContract().hash, "itoa", [original_item, base]) engine.load_script(vm.Script(sb.to_array())) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) item = engine.result_stack.pop() self.assertEqual('64', item.to_array().decode('utf-8')) engine = test_engine(has_snapshot=True) invalid_base = 2 sb = vm.ScriptBuilder() sb.emit_dynamic_call_with_args(contracts.StdLibContract().hash, "itoa", [original_item, invalid_base]) engine.load_script(vm.Script(sb.to_array())) engine.execute() self.assertEqual(vm.VMState.FAULT, engine.state) self.assertIn("Invalid base specified", engine.exception_message)
def multisig_contract_costs(threshold: int, public_key_count: int) -> int: fee = contracts.ApplicationEngine.opcode_price(vm.OpCode.PUSHDATA1) * (threshold + public_key_count) opcode = vm.OpCode(vm.ScriptBuilder().emit_push(threshold).to_array()[0]) fee += contracts.ApplicationEngine.opcode_price(opcode) opcode = vm.OpCode(vm.ScriptBuilder().emit_push(public_key_count).to_array()[0]) fee += contracts.ApplicationEngine.opcode_price(opcode) fee += contracts.ApplicationEngine.opcode_price(vm.OpCode.SYSCALL) fee += CHECKSIG_PRICE * public_key_count return fee
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_verify_secp256k1(self): """ byte[] message = System.Text.Encoding.Default.GetBytes("hello"); byte[] signature = "5331be791532d157df5b5620620d938bcb622ad02c81cfc184c460efdad18e695480d77440c511e9ad02ea30d773cb54e88f8cbb069644aefa283957085f38b5".HexToBytes(); byte[] pubKey = "03ea01cb94bdaf0cd1c01b159d474f9604f4af35a3e2196f6bdfdb33b2aa4961fa".HexToBytes(); Crypto.VerifySignature(message, signature, pubKey, Neo.Cryptography.ECC.ECCurve.Secp256k1).Should().BeTrue(); """ message = b'hello' signature = binascii.unhexlify( b'5331be791532d157df5b5620620d938bcb622ad02c81cfc184c460efdad18e695480d77440c511e9ad02ea30d773cb54e88f8cbb069644aefa283957085f38b5' ) public_key = binascii.unhexlify( b'03ea01cb94bdaf0cd1c01b159d474f9604f4af35a3e2196f6bdfdb33b2aa4961fa' ) self.assertTrue( cryptography.verify_signature(message, signature, public_key, cryptography.ECCCurve.SECP256K1)) sb = vm.ScriptBuilder() sb.emit_push(signature) sb.emit_push(public_key) sb.emit_push(message) sb.emit_syscall( syscall_name_to_int("Neo.Crypto.VerifyWithECDsaSecp256k1")) engine = test_engine() script = vm.Script(sb.to_array()) engine.load_script(script) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) self.assertEqual(vm.BooleanStackItem(True), engine.result_stack.pop()) # again with bad signature bad_signature = b'\xFF' + signature[1:] sb = vm.ScriptBuilder() sb.emit_push(bad_signature) sb.emit_push(public_key) sb.emit_push(message) sb.emit_syscall( syscall_name_to_int("Neo.Crypto.VerifyWithECDsaSecp256k1")) engine = test_engine() script = vm.Script(sb.to_array()) engine.load_script(script) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) self.assertEqual(vm.BooleanStackItem(False), engine.result_stack.pop())
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 test_storage_get_key_not_found(self): engine = test_engine(has_snapshot=True, has_container=True) script = vm.ScriptBuilder() # key parameter for the `Storage.Get` syscall script.emit(vm.OpCode.PUSH2) script.emit_syscall(syscall_name_to_int("System.Storage.GetContext")) # at this point our stack looks like follows # * storage context # * key script.emit_syscall(syscall_name_to_int("System.Storage.Get")) engine.load_script(vm.Script(script.to_array())) # we have to store our contract or some sanity checks will fail (like getting a StorageContext nef = contracts.NEF(script=script.to_array()) contract = contracts.ContractState(1, nef, self.manifest, 0, to_script_hash(nef.script)) engine.snapshot.contracts.put(contract) storage_key = storage.StorageKey(contract.id, b'\x01') storage_item = storage.StorageItem(b'\x11') engine.snapshot.storages.put(storage_key, storage_item) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertIsInstance(item, vm.NullStackItem)
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_storage_get_ok2(self): # this is basically the same as `test_storage_get_ok` # but performed by executing a script # it exists to validate that the `Optional[bytes]` return value is converted properly engine = test_engine(has_snapshot=True) script = vm.ScriptBuilder() script.emit(vm.OpCode.PUSH1) script.emit_syscall(syscall_name_to_int("System.Storage.GetContext")) script.emit_syscall(syscall_name_to_int("System.Storage.Get")) engine.load_script(vm.Script(script.to_array())) nef = contracts.NEF(script=script.to_array()) contract_hash = to_script_hash(nef.script) contract = contracts.ContractState(1, nef, self.manifest, 0, contract_hash) engine.snapshot.contracts.put(contract) storage_key = storage.StorageKey(contract.id, b'\x01') storage_item = storage.StorageItem(b'\x11') engine.snapshot.storages.put(storage_key, storage_item) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertEqual(storage_item.value, 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_get_key_not_found(self): engine = test_engine(has_snapshot=True) script = vm.ScriptBuilder() # key parameter for the `Get` syscall script.emit(vm.OpCode.PUSH2) script.emit_syscall(syscall_name_to_int("System.Storage.GetContext")) # at this point our stack looks like follows # * storage context # * key script.emit_syscall(syscall_name_to_int("System.Storage.Get")) engine.load_script(vm.Script(script.to_array())) # we set the script parameter of the ContractState to our script # which ensures that `engine.current_scripthash` matches the script we manually build above # this basically means the engine thinks it is running a smart contract that we can find in our storage # which in turns enables us to call the `System.Storage.GetContext` syscall contract = storage.ContractState(script=script.to_array(), _manifest=self.manifest) engine.snapshot.contracts.put(contract) storage_key = storage.StorageKey(contract.script_hash(), b'\x01') storage_item = storage.StorageItem(b'\x11') engine.snapshot.storages.put(storage_key, storage_item) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertIsInstance(item, vm.NullStackItem)
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 for i in range(2): # setup engine = test_engine(has_snapshot=True) script = vm.ScriptBuilder() if i == 0: 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")) else: script.emit(vm.OpCode.PUSH0) # storage put call flags 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.PutEx")) engine.load_script(vm.Script(script.to_array())) contract = storage.ContractState(script=script.to_array(), _manifest=self.manifest) engine.snapshot.contracts.put(contract) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) storage_key = storage.StorageKey(contract.script_hash(), b'\x01') item = engine.snapshot.storages.try_get(storage_key) self.assertIsNotNone(item) self.assertEqual(b'\x02', item.value)
def test_gasleft(self): engine = test_engine() engine.is_test_mode = True sb = vm.ScriptBuilder() sb.emit_syscall(syscall_name_to_int("System.Runtime.GasLeft")) data = sb.to_array() # test with test mode engine.load_script(vm.Script(data)) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack._items)) item = engine.result_stack.pop() self.assertEqual(vm.IntegerStackItem(-1), item) # test with actual consumption engine = test_engine() engine.is_test_mode = False engine.gas_amount = 500 # we can re-use the script engine.load_script(vm.Script(data)) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack._items)) item = engine.result_stack.pop() # the syscall itself costs 400 self.assertEqual(vm.IntegerStackItem(100), item)
def test_ripemd160_other_types(self): """ using var script = new ScriptBuilder(); script.EmitPush(new byte[] {0x1, 0x2, 0x3, 0x4}); script.EmitSysCall(ApplicationEngine.Neo_Crypto_RIPEMD160); // Syscall var engine = ApplicationEngine.Create(TriggerType.Application, null, null, 100_000_000, false); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); var item = engine.ResultStack.Pop<ByteString>(); Console.WriteLine($"{item.GetSpan().ToHexString()}"); """ sb = vm.ScriptBuilder() sb.emit_push(b'\x01\x02\x03\x04') sb.emit_syscall(syscall_name_to_int("Neo.Crypto.RIPEMD160")) engine = test_engine() script = vm.Script(sb.to_array()) engine.load_script(script) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) # captured from C# expected = '179bb366e5e224b8bf4ce302cefc5744961839c5' self.assertEqual(expected, str(engine.result_stack.pop()))
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_serialization(self): script = vm.ScriptBuilder() script.emit_push(5) script.emit_syscall(syscall_name_to_int("System.Json.Serialize")) script.emit(vm.OpCode.PUSH0) script.emit(vm.OpCode.NOT) script.emit_syscall(syscall_name_to_int("System.Json.Serialize")) script.emit_push("test") script.emit_syscall(syscall_name_to_int("System.Json.Serialize")) script.emit(vm.OpCode.PUSHNULL) script.emit_syscall(syscall_name_to_int("System.Json.Serialize")) script.emit(vm.OpCode.NEWMAP) script.emit(vm.OpCode.DUP) script.emit_push("key") script.emit_push("value") script.emit(vm.OpCode.SETITEM) script.emit_syscall(syscall_name_to_int("System.Json.Serialize")) data = script.to_array() engine = contracts.ApplicationEngine(contracts.TriggerType.APPLICATION, None, None, 0, True) engine.load_script(vm.Script(data)) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) def pop_to_human_readable(): return binascii.unhexlify(str( engine.result_stack.pop()).encode()).decode() self.assertEqual('{"key":"value"}', pop_to_human_readable()) self.assertEqual('null', pop_to_human_readable()) self.assertEqual('"test"', pop_to_human_readable()) self.assertEqual('true', pop_to_human_readable()) self.assertEqual('5', pop_to_human_readable())
def sign_tx(self, tx: payloads.Transaction, password: str, magic: Optional[int] = None) -> None: """ Helper function that signs the TX, adds the Witness and Sender Args: tx: transaction to sign password: the password to decrypt the private key for signing magic: the network magic Raises: ValueError: if transaction validation fails """ if magic is None: magic = settings.network.magic self._validate_tx(tx) message = magic.to_bytes(4, byteorder="little", signed=False) + tx.hash().to_array() signature = self.sign(message, password) invocation_script = vm.ScriptBuilder().emit_push(signature).to_array() # mypy can't infer that the is_watchonly check ensures public_key has a value verification_script = contracts.Contract.create_signature_redeemscript( self.public_key) # type: ignore tx.witnesses.insert( 0, payloads.Witness(invocation_script, verification_script))
def test_getscriptcontainer(self): # first test against an invalid script container (IVerifiable, but not IOperable) engine = test_engine() container = payloads.Header._serializable_init() engine.script_container = container with self.assertRaises(ValueError) as context: engine.invoke_syscall_by_name("System.Runtime.GetScriptContainer") self.assertEqual("script container is not a valid IInteroperable type", str(context.exception)) tx = test_tx(1) engine = test_engine() engine.script_container = tx sb = vm.ScriptBuilder() sb.emit_syscall( syscall_name_to_int("System.Runtime.GetScriptContainer")) engine.load_script(vm.Script(sb.to_array())) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack._items)) item = engine.result_stack.pop() self.assertIsInstance(item, vm.ArrayStackItem) # we now have a Block that has been serialized, let's check the hash self.assertEqual(vm.ByteStringStackItem(tx.hash().to_array()), item[0])
def test_check_multisig_with_ECDSA_Secp256k1(self): # values taken from test_verify_secp256k1() engine = test_engine() message = vm.ByteStringStackItem(b'hello') signature = vm.ByteStringStackItem( binascii.unhexlify( b'5331be791532d157df5b5620620d938bcb622ad02c81cfc184c460efdad18e695480d77440c511e9ad02ea30d773cb54e88f8cbb069644aefa283957085f38b5' )) signatures = vm.ArrayStackItem(engine.reference_counter) signatures.append(signature) public_keys = vm.ArrayStackItem(engine.reference_counter) public_key = vm.ByteStringStackItem( binascii.unhexlify( b'03ea01cb94bdaf0cd1c01b159d474f9604f4af35a3e2196f6bdfdb33b2aa4961fa' )) public_keys.append(public_key) sb = vm.ScriptBuilder() sb.emit_syscall( syscall_name_to_int("Neo.Crypto.CheckMultisigWithECDsaSecp256k1")) script = vm.Script(sb.to_array()) engine.load_script(script) engine.push(signatures) engine.push(public_keys) engine.push(message) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) self.assertEqual(vm.BooleanStackItem(True), engine.result_stack.pop())
def test_sha256(self): """ using var script = new ScriptBuilder(); script.EmitPush(new byte[] {0x1, 0x2, 0x3, 0x4}); script.EmitSysCall(ApplicationEngine.Neo_Crypto_SHA256); // Syscall var engine = ApplicationEngine.Create(TriggerType.Application, null, null, 100_000_000, false); engine.LoadScript(script.ToArray()); Assert.AreEqual(engine.Execute(), VMState.HALT); Assert.AreEqual(1, engine.ResultStack.Count); var item = engine.ResultStack.Pop<ByteString>(); Console.WriteLine($"{item.GetSpan().ToHexString()}"); """ sb = vm.ScriptBuilder() sb.emit_push(b'\x01\x02\x03\x04') sb.emit_syscall(syscall_name_to_int("Neo.Crypto.SHA256")) engine = test_engine() script = vm.Script(sb.to_array()) engine.load_script(script) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) # captured from C# expected = '9f64a747e1b97f131fabb6b447296c9b6f0201e79fb3c5356e6c77e89b6a806a' self.assertEqual(expected, str(engine.result_stack.pop()))
def test_iterator_concat(self): engine = test_engine() array1 = vm.ArrayStackItem(engine.reference_counter) item1 = vm.IntegerStackItem(123) array1.append(item1) array2 = vm.ArrayStackItem(engine.reference_counter) item2 = vm.IntegerStackItem(456) array2.append(item2) script = vm.ScriptBuilder() # initialize 1 slot to store the iterator in script.emit(vm.OpCode.INITSLOT) script.emit_raw(b'\x01\x00') # stack state at this point is # * array2 # * array1 script.emit_syscall(syscall_name_to_int("System.Iterator.Create")) # Iterator.create removed array2 and places an iterator on the stack, we store this in a variables slot script.emit(vm.OpCode.STLOC0) # so we can call iterator.create again, with array1 as argument script.emit_syscall(syscall_name_to_int("System.Iterator.Create")) # we restore the iterator of array2 script.emit(vm.OpCode.LDLOC0) # we concat and get [array2, array1] script.emit_syscall(syscall_name_to_int("System.Iterator.Concat")) script.emit(vm.OpCode.STLOC0) # have just 1 value per iterator, so we call next and value just 2 times for _ in range(2): script.emit(vm.OpCode.LDLOC0) script.emit_syscall(syscall_name_to_int("System.Enumerator.Next")) script.emit(vm.OpCode.DROP) script.emit(vm.OpCode.LDLOC0) script.emit_syscall(syscall_name_to_int("System.Enumerator.Value")) # we add a call to key for coverage script.emit(vm.OpCode.LDLOC0) script.emit_syscall(syscall_name_to_int("System.Iterator.Key")) engine.load_script(vm.Script(script.to_array())) engine.push(array1) engine.push(array2) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) # we expect 3 values on there, 1 key/array index and 2 array values self.assertEqual(len(engine.result_stack), 3) key_from_engine = engine.result_stack.pop() self.assertEqual(vm.IntegerStackItem(0), key_from_engine) item1_from_engine = engine.result_stack.pop() self.assertEqual(item1, item1_from_engine) # item2 was put on last, comes of first item2_from_engine = engine.result_stack.pop() self.assertEqual(item2, item2_from_engine)
def init(self, backend: storage.IDBImplementation = None, store_genesis_block=True): # type: ignore self.backend = backend if backend else settings.database self._current_snapshot = None self.genesis_block = self._create_genesis_block() self.genesis_block.rebuild_merkle_root() sb = vm.ScriptBuilder().emit_syscall( syscall_name_to_int("System.Contract.NativeOnPersist")) self.native_onpersist_script = sb.to_array() sb = vm.ScriptBuilder().emit_syscall( syscall_name_to_int("System.Contract.NativePostPersist")) self.native_postpersist_script = sb.to_array() if self.currentSnapshot.best_block_height < 0 and store_genesis_block: self.persist(self.genesis_block)
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_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_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 contract_create_with_data( self, engine: contracts.ApplicationEngine, nef_file: bytes, manifest: bytes, data: vm.StackItem) -> contracts.ContractState: if not isinstance(engine.script_container, payloads.Transaction): raise ValueError( "Cannot create contract without a Transaction script container" ) nef_len = len(nef_file) manifest_len = len(manifest) if (nef_len == 0 or nef_len > engine.MAX_CONTRACT_LENGTH or manifest_len == 0 or manifest_len > contracts.ContractManifest.MAX_LENGTH): raise ValueError("Invalid NEF or manifest length") engine.add_gas( max(engine.STORAGE_PRICE * (nef_len + manifest_len), self.get_minimum_deployment_fee(engine.snapshot))) nef = contracts.NEF.deserialize_from_bytes(nef_file) parsed_manifest = contracts.ContractManifest.from_json( json.loads(manifest.decode())) self.validate(nef.script, parsed_manifest.abi) sb = vm.ScriptBuilder() sb.emit(vm.OpCode.ABORT) sb.emit_push(engine.script_container.sender.to_array()) sb.emit_push(nef.checksum) sb.emit_push(parsed_manifest.name) hash_ = to_script_hash(sb.to_array()) existing_contract = engine.snapshot.contracts.try_get(hash_) if existing_contract is not None: raise ValueError("Contract already exists") contract = contracts.ContractState( self.get_next_available_id(engine.snapshot), nef, parsed_manifest, 0, hash_) if not contract.manifest.is_valid(hash_): raise ValueError("Error: invalid manifest") engine.snapshot.contracts.put(contract) method_descriptor = contract.manifest.abi.get_method("_deploy", 2) if method_descriptor is not None: engine.call_from_native(self.hash, hash_, method_descriptor.name, [data, vm.BooleanStackItem(False)]) msgrouter.interop_notify( self.hash, "Deploy", vm.ArrayStackItem(engine.reference_counter, vm.ByteStringStackItem( contract.hash.to_array()))) return contract
def test_base58_encode(self): engine = test_engine(has_snapshot=True) original_item = 100 sb = vm.ScriptBuilder() sb.emit_dynamic_call_with_args(contracts.StdLibContract().hash, "base58Encode", [original_item]) engine.load_script(vm.Script(sb.to_array())) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) item = engine.result_stack.peek() self.assertEqual('2j', item.to_array().decode())
def test_binary_serialization(self): engine = test_engine(has_snapshot=True) original_item = 100 sb = vm.ScriptBuilder() sb.emit_dynamic_call_with_args(contracts.StdLibContract().hash, "serialize", [original_item]) engine.load_script(vm.Script(sb.to_array())) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) item = engine.result_stack.pop() self.assertIsInstance(item, vm.ByteStringStackItem) self.assertEqual(b'\x21\x01\x64', item.to_array())
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())