示例#1
0
 def to_stack_item(self, reference_counter: vm.ReferenceCounter) -> vm.StackItem:
     struct = vm.StructStackItem(reference_counter)
     struct.append(vm.ByteStringStackItem(self.name))
     struct.append(vm.ArrayStackItem(reference_counter,
                                     list(map(lambda g: g.to_stack_item(reference_counter), self.groups)))
                   )
     struct.append(vm.ArrayStackItem(reference_counter,
                                     list(map(lambda s: vm.ByteStringStackItem(s), self.supported_standards)))
                   )
     struct.append(self.abi.to_stack_item(reference_counter))
     struct.append(vm.ArrayStackItem(reference_counter,
                                     list(map(lambda p: p.to_stack_item(reference_counter), self.permissions)))
                   )
     if self.trusts.is_wildcard:
         struct.append(vm.NullStackItem())
     else:
         struct.append(
             vm.ArrayStackItem(reference_counter,
                               list(map(lambda t: vm.ByteStringStackItem(t.to_array()),
                                        self.trusts)))  # type: ignore
         )
     if self.extra is None:
         struct.append(vm.ByteStringStackItem("null"))
     else:
         struct.append(vm.ByteStringStackItem(json.dumps(self.extra)))
     return struct
示例#2
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_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)
示例#4
0
 def tokens_of(self, snapshot: storage.Snapshot, owner: types.UInt160) -> interop.IIterator:
     storage_item_account = snapshot.storages.try_get(self.key_account + owner.to_array(), read_only=True)
     reference_counter = vm.ReferenceCounter()
     if storage_item_account is None:
         return interop.ArrayWrapper(vm.ArrayStackItem(reference_counter))
     account = storage_item_account.get(NFTAccountState)
     tokens: List[vm.StackItem] = list(map(lambda t: vm.ByteStringStackItem(t), account.tokens))
     return interop.ArrayWrapper(vm.ArrayStackItem(reference_counter, tokens))
示例#5
0
def get_notifications(engine: contracts.ApplicationEngine, for_hash: types.UInt160) -> vm.ArrayStackItem:
    array = vm.ArrayStackItem(engine.reference_counter)
    for notification in engine.notifications:
        if notification[1] == for_hash:
            notification_stackitem = vm.ArrayStackItem(engine.reference_counter)
            notification_stackitem.append([
                vm.ByteStringStackItem(notification[1].to_array()),  # script_hash
                vm.ByteStringStackItem(notification[2]),  # message
                notification[3].deep_copy()  # state
            ])
            array.append(notification_stackitem)
    if len(array) > engine.MAX_STACK_SIZE:
        raise ValueError("Notification count exceeds limits")
    return array
示例#6
0
    def finish(self, engine: contracts.ApplicationEngine) -> None:
        tx = engine.script_container
        tx = cast(payloads.Transaction, tx)
        response = tx.try_get_attribute(payloads.OracleResponse)
        if response is None:
            raise ValueError("Oracle response not found")

        request = self.get_request(engine.snapshot, response.id)
        if request is None:
            raise ValueError("Oracle request not found")

        state = vm.ArrayStackItem(
            engine.reference_counter,
            [vm.IntegerStackItem(response.id),
             vm.ByteStringStackItem(request.original_tx_id.to_array())
             ]
        )

        msgrouter.interop_notify(self.hash, "OracleResponse", state)

        user_data = contracts.BinarySerializer.deserialize(request.user_data,
                                                           engine.MAX_STACK_SIZE,
                                                           engine.reference_counter)
        args: List[vm.StackItem] = [vm.ByteStringStackItem(request.url.encode()),
                                    user_data,
                                    vm.IntegerStackItem(int(response.code)),
                                    vm.ByteStringStackItem(response.result)]

        engine.call_from_native(self.hash, request.callback_contract, request.callback_method, args)
示例#7
0
 def to_stack_item(self,
                   reference_counter: vm.ReferenceCounter) -> vm.StackItem:
     struct = vm.StructStackItem(reference_counter)
     struct.append(
         vm.ArrayStackItem(
             reference_counter,
             list(
                 map(lambda m: m.to_stack_item(reference_counter),
                     self.methods))))
     struct.append(
         vm.ArrayStackItem(
             reference_counter,
             list(
                 map(lambda e: e.to_stack_item(reference_counter),
                     self.events))))
     return struct
    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_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))
示例#10
0
    def test_with_array(self):
        """
        var a = new Neo.VM.Types.Array();
        var i = new Integer(new BigInteger(1));
        var i2 = new Integer(new BigInteger(2));
        a.Add(i);
        a.Add(i2);
        """
        # Console.WriteLine($"b'\\x{BitConverter.ToString(BinarySerializer.Serialize(a, 999)).Replace("-", @"\x")}'");
        # moved outside of multiline comment because pycharm is broken: https://youtrack.jetbrains.com/issue/PY-43117
        i = vm.IntegerStackItem(vm.BigInteger(1))
        i2 = vm.IntegerStackItem(vm.BigInteger(2))
        a = vm.ArrayStackItem(self.reference_counter)
        a.append(i)
        a.append(i2)
        expected = b'\x40\x02\x21\x01\x01\x21\x01\x02'
        out = contracts.BinarySerializer.serialize(a, 999)
        self.assertEqual(expected, out)

        # now we add a reference to ourselves.
        with self.assertRaises(ValueError) as context:
            a.append(a)
            contracts.BinarySerializer.serialize(a, 999)
        self.assertEqual("Item already exists", str(context.exception))

        # now test deserialization
        # first remove the reference to self
        a.remove(len(a) - 1)
        new_a = contracts.BinarySerializer.deserialize(out, 2048,
                                                       self.reference_counter)
        self.assertIsInstance(a, vm.ArrayStackItem)
        self.assertEqual(a._items, new_a._items)
示例#11
0
    def _post_transfer(self, engine: contracts.ApplicationEngine,
                       account_from: types.UInt160, account_to: types.UInt160,
                       amount: vm.BigInteger, data: vm.StackItem,
                       call_on_payment: bool) -> None:
        state = vm.ArrayStackItem(vm.ReferenceCounter())
        if account_from == types.UInt160.zero():
            state.append(vm.NullStackItem())
        else:
            state.append(vm.ByteStringStackItem(account_from.to_array()))
        if account_to == types.UInt160.zero():
            state.append(vm.NullStackItem())
        else:
            state.append(vm.ByteStringStackItem(account_to.to_array()))
        state.append(vm.IntegerStackItem(amount))

        msgrouter.interop_notify(self.hash, "Transfer", state)

        # wallet or smart contract
        if not call_on_payment \
                or account_to == types.UInt160.zero() \
                or contracts.ManagementContract().get_contract(engine.snapshot, account_to) is None:
            return

        if account_from == types.UInt160.zero():
            from_: vm.StackItem = vm.NullStackItem()
        else:
            from_ = vm.ByteStringStackItem(account_from.to_array())
        engine.call_from_native(
            self.hash, account_to, "onNEP17Payment",
            [from_, vm.IntegerStackItem(amount), data])
示例#12
0
    def designate_as_role(self, engine: contracts.ApplicationEngine,
                          role: DesignateRole,
                          nodes: List[cryptography.ECPoint]) -> None:
        if len(nodes) == 0:
            raise ValueError(
                "[DesignateContract] Cannot designate empty nodes list")

        if len(nodes) > 32:
            raise ValueError(
                "[DesignateContract] Cannot designate a nodes list larger than 32"
            )

        if not self._check_committee(engine):
            raise ValueError("[DesignateContract] check committee failed")

        if engine.snapshot.persisting_block is None:
            raise ValueError

        nodes.sort()
        index = engine.snapshot.persisting_block.index + 1
        storage_key = self.create_key(
            role.to_bytes(1, 'little') + self._to_uint32(index))
        with serialization.BinaryWriter() as writer:
            writer.write_serializable_list(nodes)
            storage_item = storage.StorageItem(writer.to_array())
        engine.snapshot.storages.update(storage_key, storage_item)

        state = vm.ArrayStackItem(engine.reference_counter)
        state.append(vm.IntegerStackItem(role.value))
        state.append(
            vm.IntegerStackItem(engine.snapshot.persisting_block.index))
        msgrouter.interop_notify(self.hash, "Designation", state)
示例#13
0
 def get_candidates(self, engine: contracts.ApplicationEngine) -> None:
     array = vm.ArrayStackItem(engine.reference_counter)
     for k, v in self._get_candidates(engine.snapshot):
         struct = vm.StructStackItem(engine.reference_counter)
         struct.append(vm.ByteStringStackItem(k.to_array()))
         struct.append(vm.IntegerStackItem(v))
         array.append(struct)
     engine.push(array)
示例#14
0
 def to_stack_item(self, reference_counter: vm.ReferenceCounter) -> vm.StackItem:
     array = vm.ArrayStackItem(reference_counter)
     script = vm.ByteStringStackItem(self.script)
     manifest = vm.ByteStringStackItem(str(self.manifest))
     has_storage = vm.BooleanStackItem(self.has_storage)
     is_payable = vm.BooleanStackItem(self.is_payable)
     array.append([script, manifest, has_storage, is_payable])
     return array
 def test_enumerator_create_from_array(self):
     engine = test_engine()
     array = vm.ArrayStackItem(engine.reference_counter)
     item1 = vm.ByteStringStackItem(b'\x01')
     array.append(item1)
     engine.push(array)
     r = engine.invoke_syscall_by_name("System.Enumerator.Create")
     self.assertIsInstance(r, ArrayWrapper)
     self.assertTrue(r.next())
     self.assertEqual(item1, r.value())
示例#16
0
 def test_serialization_array(self):
     b = vm.BooleanStackItem(True)
     bs = vm.ByteStringStackItem("test")
     i = vm.IntegerStackItem(123)
     n = vm.NullStackItem()
     ref_ctr = vm.ReferenceCounter()
     a = vm.ArrayStackItem(ref_ctr)
     a.append([b, bs, i, n])
     expected = r'[true,"test",123,null]'
     self.assertEqual(expected, contracts.JSONSerializer.serialize(a, 999))
示例#17
0
 def get_candidates(self, engine: contracts.ApplicationEngine) -> None:
     """
     Fetch all registered candidates, convert them to a StackItem and push them onto the evaluation stack.
     """
     array = vm.ArrayStackItem(engine.reference_counter)
     for k, v in self._get_candidates(engine.snapshot):
         struct = vm.StructStackItem(engine.reference_counter)
         struct.append(vm.ByteStringStackItem(k.to_array()))
         struct.append(vm.IntegerStackItem(v))
         array.append(struct)
     engine.push(array)
示例#18
0
    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
示例#19
0
 def test_runtime_notify_exceed_size(self):
     engine = test_engine()
     engine.push(vm.ArrayStackItem(engine.reference_counter))  # state
     engine.push(
         vm.ByteStringStackItem(
             b'\x01' * (engine.MAX_EVENT_SIZE + 1)))  # event messasge
     with self.assertRaises(ValueError) as context:
         engine.invoke_syscall_by_name("System.Runtime.Notify")
     self.assertEqual(
         "Notify event name length (33) exceeds maximum allowed (32)",
         str(context.exception))
示例#20
0
 def to_stack_item(self,
                   reference_counter: vm.ReferenceCounter) -> vm.StackItem:
     struct = vm.StructStackItem(reference_counter)
     struct.append(vm.ByteStringStackItem(self.name))
     array = vm.ArrayStackItem(
         reference_counter,
         list(
             map(lambda p: p.to_stack_item(reference_counter),
                 self.parameters)))
     struct.append(array)
     return struct
示例#21
0
    def test_notify_state_helper_basics(self):
        bssi = vm.ByteStringStackItem(b'\x01\x02')  # 2
        null = vm.NullStackItem()  # 0
        primitive = vm.IntegerStackItem(2)  # 1

        engine = test_engine()
        array1 = vm.ArrayStackItem(engine.reference_counter)
        array2 = vm.ArrayStackItem(engine.reference_counter)
        array2.append(primitive)

        # we expect a size of 3, given that our self reference should be ignored.
        # 5 would mean a failure of detecting a circular reference for ArrayStackItem types
        array1.append([bssi, null, array2, array1])

        self.assertEqual(3, _validate_state_item_limits(engine, array1))

        with self.assertRaises(ValueError) as context:
            _validate_state_item_limits(engine, vm.InteropStackItem(object()))
        self.assertEqual(
            "An item in the notification state exceeds the allowed notification size limit",
            str(context.exception))
示例#22
0
 def to_stack_item(self,
                   reference_counter: vm.ReferenceCounter) -> vm.StackItem:
     array = vm.ArrayStackItem(reference_counter)
     id_ = vm.IntegerStackItem(self.id)
     nef = vm.ByteStringStackItem(self.nef.to_array())
     update_counter = vm.IntegerStackItem(self.update_counter)
     hash_ = vm.ByteStringStackItem(self.hash.to_array())
     array.append([
         id_, update_counter, hash_, nef,
         self.manifest.to_stack_item(reference_counter)
     ])
     return array
示例#23
0
    def test_serialization_array_nested(self):
        bool_t = vm.BooleanStackItem(True)
        bool_f = vm.BooleanStackItem(False)
        bs1 = vm.ByteStringStackItem("test1")
        bs2 = vm.ByteStringStackItem("test2")

        i1 = vm.IntegerStackItem(123)
        i2 = vm.IntegerStackItem(321)
        ref_ctr = vm.ReferenceCounter()

        a1 = vm.ArrayStackItem(ref_ctr)
        a1.append([bool_t, bs1, i1])

        a2 = vm.ArrayStackItem(ref_ctr)
        a2.append([bool_f, bs2, i2])

        parent = vm.ArrayStackItem(ref_ctr)
        parent.append([a1, a2])
        expected = r'[[true,"test1",123],[false,"test2",321]]'
        self.assertEqual(expected,
                         contracts.JSONSerializer.serialize(parent, 999))
    def test_contract_call_ex_fail(self):
        engine = test_engine()
        array = vm.ArrayStackItem(engine.reference_counter)
        engine.push(vm.IntegerStackItem(123))  # invalid value for CallFlags
        engine.push(array)  # args
        engine.push(vm.ByteStringStackItem("test_func2"))  # method
        engine.push(vm.ByteStringStackItem(b'\x00'))  # call flags

        with self.assertRaises(ValueError) as context:
            engine.invoke_syscall_by_name("System.Contract.CallEx")
        self.assertIn("Failed to convert parameter stack item",
                      str(context.exception))
示例#25
0
    def test_check_multisig_with_ECDSA_Secp256r1(self):
        engine = test_engine()
        message = vm.ByteStringStackItem(b'hello')
        kp1 = cryptography.KeyPair(private_key=b'\x01' * 32)
        sig1 = cryptography.sign(message.to_array(), kp1.private_key)

        sb = vm.ScriptBuilder()
        sb.emit_syscall(
            syscall_name_to_int("Neo.Crypto.CheckMultisigWithECDsaSecp256r1"))

        script = vm.Script(sb.to_array())
        engine.load_script(script)

        # setup the stack for the syscall
        signatures = vm.ArrayStackItem(engine.reference_counter)
        signatures.append(vm.ByteStringStackItem(sig1))

        public_keys = vm.ArrayStackItem(engine.reference_counter)
        public_keys.append(
            vm.ByteStringStackItem(kp1.public_key.encode_point(False)))

        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())

        # do the same but change the message such that the signature and key are wrong
        engine = test_engine()
        engine.load_script(script)
        engine.push(signatures)
        engine.push(public_keys)
        engine.push(vm.ByteStringStackItem(b'badmessage'))
        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())
示例#26
0
    def test_runtime_getnotifications_limit_exceeded(self):
        engine = test_engine()
        target_hash = types.UInt160.zero()
        state = vm.ArrayStackItem(engine.reference_counter)

        # we can't adjust the limit, so we need to exceed it
        for i in range(0, engine.MAX_STACK_SIZE + 1):
            engine.notifications.append(
                (object(), target_hash, b'notif' + str(i).encode(), state))
        engine.push(vm.ByteStringStackItem(target_hash.to_array()))
        with self.assertRaises(ValueError) as context:
            engine.invoke_syscall_by_name("System.Runtime.GetNotifications")

        self.assertEqual("Notification count exceeds limits",
                         str(context.exception))
 def test_array_key_exception(self):
     """
     calling `key` on an array iterator without having called `next` should fail
     """
     engine = test_engine()
     array = vm.ArrayStackItem(engine.reference_counter)
     item = vm.IntegerStackItem(123)
     array.append(item)
     engine.push(array)
     engine.invoke_syscall_by_name("System.Iterator.Create")
     with self.assertRaises(ValueError) as context:
         engine.invoke_syscall_by_name("System.Iterator.Key")
     self.assertEqual(
         "Cannot call 'key' without having advanced the iterator at least once",
         str(context.exception))
示例#28
0
    def test_serialization_basics(self):
        ref = vm.ReferenceCounter()
        m = vm.MapStackItem(ref)
        s = contracts.JSONSerializer.serialize(m, 999)
        self.assertEqual("{}", s)

        a = vm.ArrayStackItem(ref)
        s = contracts.JSONSerializer.serialize(a, 999)
        self.assertEqual(r'[]', s)

        i1 = vm.IntegerStackItem(1)
        i2 = vm.IntegerStackItem(9007199254740992)
        a.append([i1, i2])
        s = contracts.JSONSerializer.serialize(a, 999)
        self.assertEqual(r'[1,"9007199254740992"]', s)
示例#29
0
    def contract_update_with_data(self, engine: contracts.ApplicationEngine,
                                  nef_file: bytes, manifest: bytes,
                                  data: vm.StackItem) -> None:
        nef_len = len(nef_file)
        manifest_len = len(manifest)

        engine.add_gas(engine.STORAGE_PRICE * (nef_len + manifest_len))

        contract = engine.snapshot.contracts.try_get(engine.calling_scripthash,
                                                     read_only=False)
        if contract is None:
            raise ValueError("Can't find contract to update")

        if nef_len == 0:
            raise ValueError(f"Invalid NEF length: {nef_len}")

        # update contract
        contract.nef = contracts.NEF.deserialize_from_bytes(nef_file)

        if manifest_len == 0 or manifest_len > contracts.ContractManifest.MAX_LENGTH:
            raise ValueError(f"Invalid manifest length: {manifest_len}")

        manifest_new = contracts.ContractManifest.from_json(
            json.loads(manifest.decode()))
        if manifest_new.name != contract.manifest.name:
            raise ValueError("Error: cannot change contract name")
        if not contract.manifest.is_valid(contract.hash):
            raise ValueError("Error: manifest does not match with script")
        contract.manifest = manifest_new

        self.validate(contract.nef.script, contract.manifest.abi)

        contract.update_counter += 1

        if len(nef_file) != 0:
            method_descriptor = contract.manifest.abi.get_method("_deploy", 2)
            if method_descriptor is not None:
                engine.call_from_native(self.hash, contract.hash,
                                        method_descriptor.name,
                                        [data, vm.BooleanStackItem(True)])

        msgrouter.interop_notify(
            self.hash, "Update",
            vm.ArrayStackItem(engine.reference_counter,
                              vm.ByteStringStackItem(
                                  contract.hash.to_array())))
示例#30
0
    def test_native_call(self):
        engine = test_engine(has_snapshot=True, default_script=True)
        block = test_block(0)

        engine.snapshot.persisting_block = block
        # need to create and store a contract matching the current_context.script
        # otherwise system.contract.call checks will fail
        engine.snapshot.contracts.put(
            storage.ContractState(b'\x40', contracts.ContractManifest()))
        engine.invoke_syscall_by_name("Neo.Native.Deploy")
        engine.push(vm.ArrayStackItem(
            engine.reference_counter))  # empty array for no arguments
        engine.push(vm.ByteStringStackItem(b'getMaxTransactionsPerBlock'))
        policy_contract_hash = vm.ByteStringStackItem(
            contracts.PolicyContract().script_hash.to_array())
        engine.push(policy_contract_hash)
        engine.invoke_syscall_by_name("System.Contract.Call")