Exemplo n.º 1
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
Exemplo n.º 2
0
 def test_deserialize_struct(self):
     s = vm.StructStackItem(self.reference_counter)
     bool1 = vm.BooleanStackItem(True)
     bool2 = vm.BooleanStackItem(False)
     s.append([bool1, bool2])
     s_serialized = contracts.BinarySerializer.serialize(s, 999)
     new_s = contracts.BinarySerializer.deserialize(s_serialized, 999,
                                                    self.reference_counter)
     self.assertIsInstance(new_s, vm.StructStackItem)
     for l, r in zip(new_s._items, s._items):
         self.assertEqual(l, r)
Exemplo n.º 3
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())
Exemplo n.º 4
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())
Exemplo n.º 5
0
    def test_with_map(self):
        """
        var m = new Map(new ReferenceCounter());
        var i = new Integer(new BigInteger(1));
        var i2 = new Integer(new BigInteger(2));
        var b = new Neo.VM.Types.Boolean(true);
        m[i] = b;
        m[i2] = b;

        """
        # moved outside of multiline comment because pycharm is broken: https://youtrack.jetbrains.com/issue/PY-43117
        #Console.WriteLine($"b'\\x{BitConverter.ToString(BinarySerializer.Serialize(m, 999)).Replace("-", @"\x")}'");
        m = vm.MapStackItem(self.reference_counter)
        i = vm.IntegerStackItem(vm.BigInteger(1))
        i2 = vm.IntegerStackItem(vm.BigInteger(2))
        b = vm.BooleanStackItem(True)
        m[i] = b
        m[i2] = b
        expected = b'\x48\x02\x21\x01\x01\x20\x01\x21\x01\x02\x20\x01'
        out = contracts.BinarySerializer.serialize(m, 999)
        self.assertEqual(expected, out)

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

        # now test deserialization
        m[i] = b  # restore m[i] to original content
        new_m = contracts.BinarySerializer.deserialize(out, 2048,
                                                       self.reference_counter)
        self.assertEqual(len(m), len(new_m))
        self.assertEqual(m.keys(), new_m.keys())
        self.assertEqual(m.values(), new_m.values())
Exemplo n.º 6
0
    def _native_to_stackitem(self, value, native_type) -> vm.StackItem:
        """
        Convert native type to VM type

        Note: order of checking matters.
        e.g. a Transaction should be treated as IInteropable, while its also ISerializable
        """
        if isinstance(value, vm.StackItem):
            return value
        elif value is None:
            return vm.NullStackItem()
        elif native_type in [int, vm.BigInteger]:
            return vm.IntegerStackItem(value)
        elif issubclass(native_type, IInteroperable):
            value_ = cast(IInteroperable, value)
            return value_.to_stack_item(self.reference_counter)
        elif issubclass(native_type, serialization.ISerializable):
            serializable_value = cast(serialization.ISerializable, value)
            return vm.ByteStringStackItem(serializable_value.to_array())
        # mypy bug? https://github.com/python/mypy/issues/9756
        elif native_type in [bytes, bytearray]:  # type: ignore
            return vm.ByteStringStackItem(value)
        elif native_type == str:
            return vm.ByteStringStackItem(bytes(value, 'utf-8'))
        elif native_type == bool:
            return vm.BooleanStackItem(value)
        elif issubclass(native_type, (enum.IntFlag, enum.IntEnum)):
            return self._native_to_stackitem(value.value, int)
        else:
            return vm.StackItem.from_interface(value)
Exemplo n.º 7
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))
Exemplo n.º 8
0
 def to_stack_item(self,
                   reference_counter: vm.ReferenceCounter) -> vm.StackItem:
     struct = cast(
         vm.StructStackItem,
         super(ContractMethodDescriptor,
               self).to_stack_item(reference_counter))
     struct.append(vm.IntegerStackItem(self.return_type.value))
     struct.append(vm.IntegerStackItem(self.offset))
     struct.append(vm.BooleanStackItem(self.safe))
     return struct
Exemplo n.º 9
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
Exemplo n.º 10
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))
Exemplo n.º 11
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())
Exemplo n.º 12
0
    def test_verify_secp256r1(self):
        """
        var privkey = new byte[]
        {
            2, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 1
        };
        var message = new byte[]
        {
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1
        };
        var signature = new byte[] { 56,70,104,22,234,182,23,161,111,25,71,188,12,5,54,28,99,189,8,47,4,82,62,150,57,216,25,130,217,25,123,118,89,149,217,130,12,109,34,125,176,189,142,119,154,140,116,16,32,209,214,87,178,248,214,39,248,29,214,10,205,153,146,111};
        var kp = new KeyPair(privkey);
        Console.WriteLine(Crypto.VerifySignature(message, signature, kp.PublicKey.EncodePoint(false), ECCurve.Secp256r1));
        """
        message = b'\x01' * 32
        priv_key = b'\x02' + b'\x00' * 30 + b'\x01'
        sig = cryptography.sign(message, priv_key)

        # from ecdsa import VerifyingKey, SigningKey, curves as ecdsa_curves
        # import hashlib
        # sk = SigningKey.from_string(priv_key, curve=ecdsa_curves.NIST256p, hashfunc=hashlib.sha256)
        # sig = sk.sign(message, hashfunc=hashlib.sha256)

        kp = cryptography.KeyPair(priv_key)

        sb = vm.ScriptBuilder()
        sb.emit_push(sig)
        sb.emit_push(kp.public_key.encode_point(False))
        sb.emit_push(message)
        sb.emit_syscall(
            syscall_name_to_int("Neo.Crypto.VerifyWithECDsaSecp256r1"))

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

        # first test with an invalid interop item. They must be IVerifiable
        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())
Exemplo n.º 13
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())))
Exemplo n.º 14
0
    def _native_to_stackitem(self, value, native_type) -> vm.StackItem:
        """
        Convert native type to VM type

        Note: order of checking matters.
        e.g. a Transaction should be treated as IInteropable, while its also ISerializable
        """
        if isinstance(value, vm.StackItem):
            return value
        elif value is None:
            return vm.NullStackItem()
        elif native_type in [int, vm.BigInteger]:
            return vm.IntegerStackItem(value)
        elif issubclass(native_type, IInteroperable):
            value_ = cast(IInteroperable, value)
            return value_.to_stack_item(self.reference_counter)
        elif issubclass(native_type, serialization.ISerializable):
            serializable_value = cast(serialization.ISerializable, value)
            return vm.ByteStringStackItem(serializable_value.to_array())
        # mypy bug? https://github.com/python/mypy/issues/9756
        elif native_type in [bytes, bytearray]:  # type: ignore
            return vm.ByteStringStackItem(value)
        elif native_type == str:
            return vm.ByteStringStackItem(bytes(value, 'utf-8'))
        elif native_type == bool:
            return vm.BooleanStackItem(value)
        elif issubclass(native_type, (enum.IntFlag, enum.IntEnum)):
            return self._native_to_stackitem(value.value, int)
        elif hasattr(native_type, '__origin__'
                     ) and native_type.__origin__ == Union:  # type: ignore
            # handle typing.Optional[type], Optional is an alias for Union[x, None]
            # only support specifying 1 type
            if len(native_type.__args__) != 2:
                raise ValueError(
                    f"Don't know how to convert native type {native_type} to stackitem"
                )
            for i in native_type.__args__:
                if i is None:
                    continue
                return self._native_to_stackitem(value, native_type)
            else:
                raise ValueError  # shouldn't be possible, but silences mypy
        else:
            return vm.StackItem.from_interface(value)
Exemplo n.º 15
0
 def deserialize(
         json_data: JObject,
         reference_counter: vm.ReferenceCounter = None) -> vm.StackItem:
     """
     Deserialize JSON into a virtual machine stack item
     """
     t = type(json_data)
     if t == dict:
         json_data = cast(dict, json_data)
         if reference_counter is None:
             raise ValueError(
                 "Can't deserialize JSON object without reference counter")
         map_item = vm.MapStackItem(reference_counter)
         for k, v in json_data.items():
             key = vm.ByteStringStackItem(k)
             value = JSONSerializer.deserialize(v, reference_counter)
             map_item[key] = value
         return map_item
     elif t == list:
         if reference_counter is None:
             raise ValueError(
                 "Can't deserialize JSON array without reference counter")
         array_item = vm.ArrayStackItem(reference_counter)
         json_data = cast(list, json_data)
         elements = [
             JSONSerializer.deserialize(e, reference_counter)
             for e in json_data
         ]
         array_item.append(elements)
         return array_item
     elif json_data is None:
         return vm.NullStackItem()
     elif t == str:
         if json_data == "null":
             return vm.NullStackItem()
         return vm.ByteStringStackItem(json_data)  # type: ignore
     elif t == int:
         return vm.IntegerStackItem(json_data)  # type: ignore
     elif t == bool:
         json_data = cast(bool, json_data)
         return vm.BooleanStackItem(json_data)
     else:
         # should never happen or somebody ignored the type checker output
         raise ValueError()
Exemplo n.º 16
0
    def deserialize(data: bytes, max_size: int, max_item_size: int,
                    reference_counter: vm.ReferenceCounter) -> vm.StackItem:
        """
        Deserialize data into a stack item.

        Args:
            data: byte array of a serialized stack item.
            max_size: data reading limit for Array, Struct and Map types.
            max_item_size: data reading limit for ByteString or Buffer types.
            reference_counter: a valid reference counter instance. Get's passed into reference stack items.
        """
        if len(data) == 0:
            raise ValueError("Nothing to deserialize")

        deserialized: List[Union[vm.StackItem, PlaceHolder]] = []
        to_deserialize = 1
        with serialization.BinaryReader(data) as reader:
            while not to_deserialize == 0:
                to_deserialize -= 1
                item_type = vm.StackItemType(reader.read_byte()[0])
                if item_type == vm.StackItemType.ANY:
                    deserialized.append(vm.NullStackItem())
                elif item_type == vm.StackItemType.BOOLEAN:
                    deserialized.append(vm.BooleanStackItem(
                        reader.read_bool()))
                elif item_type == vm.StackItemType.INTEGER:
                    deserialized.append(
                        vm.IntegerStackItem(
                            vm.BigInteger(
                                reader.read_var_bytes(
                                    vm.IntegerStackItem.MAX_SIZE))))
                elif item_type == vm.StackItemType.BYTESTRING:
                    deserialized.append(
                        vm.ByteStringStackItem(
                            reader.read_var_bytes(max_item_size)))
                elif item_type == vm.StackItemType.BUFFER:
                    deserialized.append(
                        vm.BufferStackItem(
                            reader.read_var_bytes(max_item_size)))
                elif item_type in [
                        vm.StackItemType.ARRAY, vm.StackItemType.STRUCT
                ]:
                    count = reader.read_var_int(max_size)
                    deserialized.append(PlaceHolder(item_type, count))
                    to_deserialize += count
                elif item_type == vm.StackItemType.MAP:
                    count = reader.read_var_int(max_size)
                    deserialized.append(PlaceHolder(item_type, count))
                    to_deserialize += count * 2
                else:
                    raise ValueError("Invalid format")

        temp: List[vm.StackItem] = []
        while len(deserialized) > 0:
            item = deserialized.pop()
            if type(item) == PlaceHolder:
                item = cast(PlaceHolder, item)
                if item.type == vm.StackItemType.ARRAY:
                    array = vm.ArrayStackItem(reference_counter)
                    for _ in range(0, item.count):
                        array.append(temp.pop())
                    temp.append(array)
                elif item.type == vm.StackItemType.STRUCT:
                    struct = vm.StructStackItem(reference_counter)
                    for _ in range(0, item.count):
                        struct.append(temp.pop())
                    temp.append(struct)
                elif item.type == vm.StackItemType.MAP:
                    m = vm.MapStackItem(reference_counter)
                    for _ in range(0, item.count):
                        k = temp.pop()
                        k = cast(vm.PrimitiveType, k)
                        v = temp.pop()
                        m[k] = v
                    temp.append(m)
            else:
                item = cast(vm.StackItem, item)
                temp.append(item)
        return temp.pop()