def test_iterator_create_from_buffer(self): engine = test_engine() buffer = vm.BufferStackItem(b'\x03\x04') engine.push(buffer) r = engine.invoke_syscall_by_name("System.Iterator.Create") self.assertIsInstance(r, ByteArrayWrapper) with self.assertRaises(ValueError) as context: r.key() self.assertEqual( "Cannot call 'key' without having advanced the iterator at least once", str(context.exception)) with self.assertRaises(ValueError) as context: r.value() self.assertEqual( "Cannot call 'value' without having advanced the iterator at least once", str(context.exception)) self.assertTrue(r.next()) self.assertEqual(vm.IntegerStackItem(0), r.key()) self.assertEqual(vm.IntegerStackItem(3), r.value()) self.assertTrue(r.next()) self.assertEqual(vm.IntegerStackItem(1), r.key()) self.assertEqual(vm.IntegerStackItem(4), r.value()) self.assertFalse(r.next()) self.assertEqual(vm.IntegerStackItem(1), r.key()) self.assertEqual(vm.IntegerStackItem(4), r.value())
def test_deserialize_buffer(self): data = b'\x01\x02' b = vm.BufferStackItem(data) b_serialized = contracts.BinarySerializer.serialize(b, 999) new_b = contracts.BinarySerializer.deserialize(b_serialized, 999, self.reference_counter) self.assertIsInstance(new_b, vm.BufferStackItem) self.assertEqual(new_b.to_array(), b.to_array())
def test_deserialize_with_invalid_format(self): data = b'\x01\x02' b = vm.BufferStackItem(data) b_serialized = bytearray(contracts.BinarySerializer.serialize(b, 999)) b_serialized[0] = 0xFF # non existing stackitem type with self.assertRaises(ValueError) as context: contracts.BinarySerializer.deserialize(b_serialized, 999, self.reference_counter) self.assertEqual("Invalid format", str(context.exception))
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()