Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
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())
Beispiel #5
0
    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)
Beispiel #6
0
    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))
Beispiel #7
0
    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)
Beispiel #8
0
    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)
Beispiel #9
0
    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())
Beispiel #10
0
    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
Beispiel #11
0
    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)
Beispiel #12
0
    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))
Beispiel #17
0
    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())
Beispiel #19
0
    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])
Beispiel #20
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
Beispiel #21
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())
Beispiel #22
0
    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()))
Beispiel #23
0
    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)
Beispiel #25
0
 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)
Beispiel #27
0
 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)
Beispiel #28
0
 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())
Beispiel #29
0
 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())
Beispiel #30
0
    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())