예제 #1
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())
 def test_iterator_create_from_map(self):
     engine = test_engine()
     map_item = vm.MapStackItem(engine.reference_counter)
     key1 = vm.IntegerStackItem(1)
     key2 = vm.IntegerStackItem(3)
     item1 = vm.IntegerStackItem(2)
     item2 = vm.IntegerStackItem(4)
     map_item[key1] = item1
     map_item[key2] = item2
     engine.push(map_item)
     r = engine.invoke_syscall_by_name("System.Iterator.Create")
     self.assertIsInstance(r, MapWrapper)
     self.assertTrue(r.next())
     value = r.value()
     self.assertIsInstance(value, vm.StructStackItem)
     self.assertEqual(2, len(value))
     self.assertEqual(key1, value[0])
     self.assertEqual(item1, value[1])
     self.assertTrue(r.next())
     value = r.value()
     self.assertIsInstance(value, vm.StructStackItem)
     self.assertEqual(2, len(value))
     self.assertEqual(key2, value[0])
     self.assertEqual(item2, value[1])
     # exhausted the iterator
     self.assertFalse(r.next())
     with self.assertRaises(ValueError) as context:
         r.value()
     self.assertEqual(
         "Cannot call 'value' without having advanced the iterator at least once",
         str(context.exception))
예제 #3
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.MapStackItem(reference_counter))
     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
예제 #4
0
 def test_serialization_map_with_integer_key(self):
     i = vm.IntegerStackItem(123)
     v = vm.IntegerStackItem(321)
     ref_ctr = vm.ReferenceCounter()
     m = vm.MapStackItem(ref_ctr)
     m[i] = v
     expected = r'{"123":321}'
     s = contracts.JSONSerializer.serialize(m, 999)
     self.assertEqual(expected, s)
예제 #5
0
    def test_notify_state_helper_map(self):
        bssi = vm.ByteStringStackItem(b'\x01\x02')  # 2
        primitive = vm.IntegerStackItem(2)  # 1

        engine = test_engine()
        map1 = vm.MapStackItem(engine.reference_counter)
        map1[primitive] = bssi

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

        # self reference
        map1[primitive] = map1
        # asserting to 1 because the key in the map has a length of 1
        self.assertEqual(1, _validate_state_item_limits(engine, map1))
예제 #6
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)
예제 #7
0
 def test_serialization_map(self):
     ref = vm.ReferenceCounter()
     key1 = vm.ByteStringStackItem("test1")
     key2 = vm.ByteStringStackItem("test2")
     key3 = vm.ByteStringStackItem("test3")
     v1 = vm.IntegerStackItem(1)
     v2 = vm.IntegerStackItem(2)
     v3 = vm.IntegerStackItem(3)
     m = vm.MapStackItem(ref)
     m[key1] = v1
     m[key3] = v3
     m[key2] = v2
     s = contracts.JSONSerializer.serialize(m, 999)
     # this is a known deviation. NEO preserved key order, we don't
     # but shouldn't matter as it gets deserialized to a map stackitem
     expected = r'{"test1":1,"test2":2,"test3":3}'
     self.assertEqual(expected, s)
    def test_iterator_key_and_value(self):
        engine = test_engine()
        # same map setup code as test_iterator_create_from_map()
        map_item = vm.MapStackItem(engine.reference_counter)
        key1 = vm.IntegerStackItem(1)
        key2 = vm.IntegerStackItem(3)
        item1 = vm.IntegerStackItem(2)
        item2 = vm.IntegerStackItem(4)
        map_item[key1] = item1
        map_item[key2] = item2

        # we build a script such that we can create an interator, move it forward and retrieves the key and values
        script = vm.ScriptBuilder()
        # initialize 1 slot to store the iterator in
        script.emit(vm.OpCode.INITSLOT)
        script.emit_raw(b'\x01\x00')

        script.emit_syscall(syscall_name_to_int("System.Iterator.Create"))
        # save the iterator and retrieve it again
        script.emit(vm.OpCode.STLOC0)
        script.emit(vm.OpCode.LDLOC0)
        script.emit_syscall(syscall_name_to_int("System.Enumerator.Next"))
        # clear the result of `Enumerator.Next()`, we assume it will say True
        script.emit(vm.OpCode.DROP)

        script.emit(vm.OpCode.LDLOC0)
        script.emit_syscall(syscall_name_to_int("System.Iterator.Key"))

        script.emit(vm.OpCode.LDLOC0)
        script.emit_syscall(syscall_name_to_int("System.Enumerator.Value"))

        engine.load_script(vm.Script(script.to_array()))
        engine.push(map_item)
        engine.execute()

        self.assertEqual(vm.VMState.HALT, engine.state)
        # we expect a key and a value on their
        self.assertEqual(len(engine.result_stack), 2)
        # value was put on last, comes of first
        value = engine.result_stack.pop()
        self.assertEqual(item1, value)

        key = engine.result_stack.pop()
        self.assertEqual(key1, key)
예제 #9
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()
    def test_iterator_keys(self):
        # we iterate over just the 2 keys in our map
        engine = test_engine()
        map_item = vm.MapStackItem(engine.reference_counter)
        key1 = vm.IntegerStackItem(1)
        key2 = vm.IntegerStackItem(3)
        item1 = vm.IntegerStackItem(2)
        item2 = vm.IntegerStackItem(4)
        map_item[key1] = item1
        map_item[key2] = item2

        script = vm.ScriptBuilder()
        # initialize 1 slot to store the iterator in
        script.emit(vm.OpCode.INITSLOT)
        script.emit_raw(b'\x01\x00')

        script.emit_syscall(syscall_name_to_int("System.Iterator.Create"))
        script.emit_syscall(syscall_name_to_int("System.Iterator.Keys"))
        script.emit(vm.OpCode.STLOC0)

        # we have 2 keys in our map, so we can repeat this sequence twice
        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"))

        engine.load_script(vm.Script(script.to_array()))
        engine.push(map_item)
        engine.execute()

        self.assertEqual(vm.VMState.HALT, engine.state)
        # we expect a 2 keys on there
        self.assertEqual(len(engine.result_stack), 2)
        # key2 was put on last, comes of first
        key2_from_engine = engine.result_stack.pop()
        self.assertEqual(key2, key2_from_engine)

        key1_from_engine = engine.result_stack.pop()
        self.assertEqual(key1, key1_from_engine)
예제 #11
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()
예제 #12
0
 def properties(self, engine: contracts.ApplicationEngine, token_id: bytes) -> vm.MapStackItem:
     storage_item = engine.snapshot.storages.get(self.key_token + token_id, read_only=True)
     map_ = vm.MapStackItem(engine.reference_counter)
     for k, v in NFTState.deserialize_from_bytes(storage_item.value).to_json():
         map_[k] = v
     return map_