def persist(self, block: payloads.Block): with self.backend.get_snapshotview() as snapshot: snapshot.block_height = block.index snapshot.blocks.put(block) snapshot.persisting_block = block if block.index > 0: engine = contracts.ApplicationEngine( contracts.TriggerType.SYSTEM, None, snapshot, 0, True) # type: ignore engine.load_script(vm.Script(self.native_onpersist_script)) if engine.execute() != vm.VMState.HALT: raise ValueError( f"Failed onPersist in native contracts: {engine.exception_message}" ) cloned_snapshot = snapshot.clone() for tx in block.transactions: tx.block_height = block.index cloned_snapshot.transactions.put(tx) cloned_snapshot.transactions.commit() engine = contracts.ApplicationEngine( contracts.TriggerType.APPLICATION, tx, cloned_snapshot, tx.system_fee) engine.load_script(vm.Script(tx.script)) state = engine.execute() if state == vm.VMState.HALT: cloned_snapshot.commit() else: cloned_snapshot = snapshot.clone() snapshot.commit() self._current_snapshot = snapshot msgrouter.on_block_persisted(block)
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 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_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 persist(self, block: payloads.Block): with self.backend.get_snapshotview() as snapshot: snapshot.persisting_block = block engine = contracts.ApplicationEngine( contracts.TriggerType.ON_PERSIST, None, snapshot, 0, True) # type: ignore engine.load_script(vm.Script(self.native_onpersist_script)) if engine.execute() != vm.VMState.HALT: raise ValueError( f"Failed onPersist in native contracts: {engine.exception_message}" ) cloned_snapshot = snapshot.clone() for tx in block.transactions: tx.block_height = block.index cloned_snapshot.transactions.put(tx) cloned_snapshot.transactions.commit() engine = contracts.ApplicationEngine( contracts.TriggerType.APPLICATION, tx, cloned_snapshot, tx.system_fee) engine.load_script(vm.Script(tx.script)) state = engine.execute() if state == vm.VMState.HALT: cloned_snapshot.commit() else: cloned_snapshot = snapshot.clone() engine = contracts.ApplicationEngine( contracts.TriggerType.POST_PERSIST, None, snapshot, 0, True) # type: ignore engine.load_script(vm.Script(self.native_postpersist_script)) if engine.execute() != vm.VMState.HALT: raise ValueError( f"Failed postPersist in native contracts: {engine.exception_message}" ) """ LedgerContract updates the current block in the post_persist event this means transactions in the persisting block that call LedgerContract.current_hash/current_index() will get refer the (previous) block hash/index, not the block they're included in. Therefore we wait with persisting the block until here """ snapshot.blocks.put(block) snapshot.best_block_height = block.index snapshot.commit() self._current_snapshot = snapshot msgrouter.on_block_persisted(block)
def test_serialize_with_invalid_stackitem(self): s = vm.Script(b'') p = vm.PointerStackItem(s, 0) with self.assertRaises(ValueError) as context: contracts.BinarySerializer.serialize(p, 999) self.assertIn("Cannot serialize", str(context.exception))
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_contract_call_ex(self): # code is the same as "test_contract_call" except for the interop engine = test_engine(has_snapshot=True, default_script=False) # current executing contract contract = storage.ContractState(hello_world_nef.script, hello_world_manifest) engine.snapshot.contracts.put(contract) # target contract target_contract = storage.ContractState(contract3_nef.script, contract3_manifest) engine.snapshot.contracts.put(target_contract) engine.load_script(vm.Script(contract.script)) engine.push(vm.IntegerStackItem(15)) # call flags array = vm.ArrayStackItem(engine.reference_counter) array.append(vm.IntegerStackItem(3)) engine.push(array) # args engine.push(vm.ByteStringStackItem("test_func2")) # method engine.push( vm.ByteStringStackItem(target_contract.script_hash().to_array())) engine.invoke_syscall_by_name("System.Contract.CallEx") engine.execute() self.assertEqual(2, len(engine.result_stack)) main_contract_return_value = engine.result_stack.pop() syscall_called_contract_return_value = engine.result_stack.pop() self.assertEqual("hello world", main_contract_return_value.to_array().decode()) self.assertEqual(4, int(syscall_called_contract_return_value))
def test_contract_update_exceptions6(self): # asking to update with a new script but with an invalid manifest (new manifest does not support storage, # while the old contract has existing storage) engine = test_engine(has_snapshot=True, default_script=False) contract_old = storage.ContractState(hello_world_nef.script, deepcopy(hello_world_manifest)) contract_old.manifest.features |= contracts.ContractFeatures.HAS_STORAGE engine.snapshot.contracts.put(contract_old) storage_key = storage.StorageKey(contract_old.script_hash(), b'firstkey') storage_item = storage.StorageItem(b'firstitem') engine.snapshot.storages.put(storage_key, storage_item) # we load the stored as script to properly setup "engine.current_scripthash" engine.load_script(vm.Script(contract_old.script)) # next we push the necessary items on the stack before calling the update funcztion # we take the matching manifest and change it to have no storage bad_manifest = deepcopy(bye_world_manifest) bad_manifest.features &= ~contracts.ContractFeatures.HAS_STORAGE engine.push(vm.ByteStringStackItem(str(bad_manifest).encode())) engine.push(vm.ByteStringStackItem(bye_world_nef.script)) with self.assertRaises(ValueError) as context: engine.invoke_syscall_by_name("System.Contract.Update") self.assertEqual( "Error: New contract does not support storage while old contract has existing storage", str(context.exception))
def test_contract_update_ok(self): engine = test_engine(has_snapshot=True, default_script=False) # the real world setup should be # 1) deploy a smart contract with an update function that internally calls "System.Contract.Update" # 2) perform a contract call to the old contract and supply a new script + manifest as arguments # # here we will bypass deploying a contract with an update function and directly call "System.Contract.Update" on # the engine. We start by persisting the contract we want to update contract = storage.ContractState(hello_world_nef.script, hello_world_manifest) engine.snapshot.contracts.put(contract) # we load the old contract as script to properly setup "engine.current_scripthash" engine.load_script(vm.Script(contract.script)) # next we push the necessary items on the stack before calling the update function engine.push(vm.ByteStringStackItem(str(bye_world_manifest).encode())) engine.push(vm.ByteStringStackItem(bye_world_nef.script)) engine.invoke_syscall_by_name("System.Contract.Update") # test that we cannot find the old contract anymore self.assertIsNone( engine.snapshot.contracts.try_get(contract.script_hash())) new_contract = storage.ContractState(bye_world_nef.script, bye_world_manifest) # make sure the new contract is still there (and that we not just cleared the whole storage) self.assertIsNotNone( engine.snapshot.contracts.try_get(new_contract.script_hash()))
def test_contract_call(self): engine = test_engine(has_snapshot=True, default_script=False) # current executing contract fake_hash = types.UInt160.deserialize_from_bytes(b'\x01' * 20) contract = contracts.ContractState(0, hello_world_nef, hello_world_manifest, 0, fake_hash) engine.snapshot.contracts.put(contract) # target contract fake_hash2 = types.UInt160.deserialize_from_bytes(b'\x02' * 20) target_contract = contracts.ContractState(1, contract3_nef, contract3_manifest, 0, fake_hash2) engine.snapshot.contracts.put(target_contract) engine.load_script(vm.Script(contract.script)) array = vm.ArrayStackItem(engine.reference_counter) array.append(vm.IntegerStackItem(3)) engine.push(array) # args engine.push(vm.IntegerStackItem(15)) # callflags engine.push(vm.ByteStringStackItem("test_func2")) # method engine.push(vm.ByteStringStackItem(target_contract.hash.to_array())) engine.invoke_syscall_by_name("System.Contract.Call") engine.execute() self.assertEqual(2, len(engine.result_stack)) main_contract_return_value = engine.result_stack.pop() syscall_called_contract_return_value = engine.result_stack.pop() self.assertEqual("hello world", main_contract_return_value.to_array().decode()) self.assertEqual(4, int(syscall_called_contract_return_value))
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 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 calculate_system_fee(tx: payloads.Transaction, snapshot: storage.Snapshot) -> int: engine = contracts.ApplicationEngine(contracts.TriggerType.APPLICATION, tx, snapshot, 0, test_mode=True) engine.load_script(vm.Script(tx.script)) if engine.execute() == vm.VMState.FAULT: raise ValueError("Transaction script execution failed") else: return engine.gas_consumed
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_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 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 test_serialization_invalid_type(self): s = vm.Script(b'') p = vm.PointerStackItem(s, 0) with self.assertRaises(TypeError) as context: contracts.JSONSerializer.serialize(p, 999) self.assertEqual( "Object of type PointerStackItem is not JSON serializable", str(context.exception))
def test_validate_sample_contract(self): engine = test_engine() engine.load_script(vm.Script(hello_world_nef.script)) 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.ByteStringStackItem) self.assertEqual(vm.ByteStringStackItem(b'hello world'), item)
def validate(self, script: bytes, abi: contracts.ContractABI): s = vm.Script(script, True) for method in abi.methods: s.get_instruction(method.offset) events = [] for event in abi.events: if event.name in events: raise ValueError("Duplicate event in ABI") else: events.append(event)
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())