Exemplo n.º 1
0
    def process(self):

        self.process_compact_bytes()

        if self.sub_type:

            byte_data = self.get_decoder_class(
                type_string=self.sub_type,
                data=ScaleBytes(self.compact_bytes),
                runtime_config=self.runtime_config).process()

            if type(byte_data) is int and self.compact_length <= 4:
                return int(byte_data / 4)
            else:
                return byte_data
        else:
            return self.compact_bytes
Exemplo n.º 2
0
    def accumulation_hook(self, db_session):

        self.block.count_log = len(self.block.logs)

        for idx, log_data in enumerate(self.block.logs):
            log_digest = LogDigest(ScaleBytes(log_data))
            log_digest.decode()

            log = Log(
                block_id=self.block.id,
                log_idx=idx,
                type_id=log_digest.index,
                type=log_digest.index_value,
                data=log_digest.value,
            )

            log.save(db_session)
Exemplo n.º 3
0
    def process(self):

        self.process_compact_bytes()

        if self.sub_type:

            byte_data = self.get_decoder_class(
                self.sub_type, ScaleBytes(self.compact_bytes)).process()

            # TODO Assumptions
            if type(byte_data) is int and self.compact_length <= 4:
                return int(byte_data / 4)
            else:
                # TODO raise exception?
                return byte_data
        else:
            return self.compact_bytes
Exemplo n.º 4
0
    def process_encode(self, value):

        if type(value) is not list:
            raise ValueError("Provided value is not a list of booleans")

        if len(value) == 0:
            return ScaleBytes(b'\x00')

        int_value = sum(v << i for i, v in enumerate(value))

        # encode the length in a compact u32
        compact_obj = CompactU32()
        data = compact_obj.encode(len(value))

        byte_length = math.ceil(len(value) / 8)

        return data + int_value.to_bytes(length=byte_length, byteorder='little')
Exemplo n.º 5
0
    def process_encode(self, value):

        if type(value) is not dict:
            raise TypeError(
                "value must be of type dict to encode a GenericCall")

        # Check requirements
        if 'call_index' in value:
            self.call_index = value['call_index']

        elif 'call_module' in value and 'call_function' in value:
            # Look up call module from metadata
            for call_index, (
                    call_module,
                    call_function) in self.metadata.call_index.items():

                if call_module.name == value[
                        'call_module'] and call_function.name == value[
                            'call_function']:
                    self.call_index = call_index
                    self.call_module = call_module
                    self.call_function = call_function
                    break

            if not self.call_index:
                raise ValueError(
                    'Specified call module and function not found in metadata')

        elif not self.call_module or not self.call_function:
            raise ValueError('No call module and function specified')

        data = ScaleBytes(bytearray.fromhex(self.call_index))

        # Encode call params
        if len(self.call_function.args) > 0:
            for arg in self.call_function.args:
                if arg.name not in value['call_args']:
                    raise ValueError('Parameter \'{}\' not specified'.format(
                        arg.name))
                else:
                    param_value = value['call_args'][arg.name]

                    arg_obj = self.get_decoder_class(arg.type,
                                                     metadata=self.metadata)
                    data += arg_obj.encode(param_value)
        return data
Exemplo n.º 6
0
    def process_encode(self, value):

        if type(value) is list:
            value = sum(v << i for i, v in enumerate(reversed(value)))

        if type(value) is not int:
            raise ValueError("Provided value is not an int or a list of booleans")

        if value == 0:
            return ScaleBytes(b'\x00')

        # encode the length in a compact u32
        compact_obj = CompactU32()
        data = compact_obj.encode(value.bit_length())

        byte_length = math.ceil(value.bit_length() / 8)

        return data + value.to_bytes(length=byte_length, byteorder='little')
Exemplo n.º 7
0
    def process_encode(self, value):
        if type(value) == str and value[0:2] != '0x':
            # Assume SS58 encoding address
            if len(value) >= 46:
                from scalecodec.utils.ss58 import ss58_decode
                value = '0x{}'.format(ss58_decode(value))
            else:
                from scalecodec.utils.ss58 import ss58_decode_account_index
                index_obj = GenericAccountIndex()
                value = index_obj.encode(ss58_decode_account_index(value))

        if type(value) == str and value[0:2] == '0x' and len(value) == 66:
            # value is AccountId
            return ScaleBytes('0x{}'.format(value[2:]))
        elif type(value) == int:
            # value is AccountIndex
            raise NotImplementedError('Encoding of AccountIndex Adresses not supported yet')
        else:
            raise ValueError('Value is in unsupported format, expected 32 bytes hex-string for AccountIds or int for AccountIndex')
Exemplo n.º 8
0
    def setUpClass(cls):
        module_path = os.path.dirname(__file__)

        # scale_info_defaults = load_type_registry_file(os.path.join(module_path, 'fixtures', 'scale_info_defaults.json'))

        cls.runtime_config = RuntimeConfigurationObject(ss58_format=42)
        cls.runtime_config.update_type_registry(
            load_type_registry_preset("metadata_types"))
        # cls.runtime_config.update_type_registry(scale_info_defaults)

        cls.metadata_fixture_dict = load_type_registry_file(
            os.path.join(module_path, 'fixtures', 'metadata_hex.json'))

        cls.metadata_obj = cls.runtime_config.create_scale_object(
            'MetadataVersioned',
            data=ScaleBytes(cls.metadata_fixture_dict['V14']))
        cls.metadata_obj.decode()

        cls.runtime_config.add_portable_registry(cls.metadata_obj)
Exemplo n.º 9
0
    def test_box_call(self):
        RuntimeConfiguration().update_type_registry(
            load_type_registry_preset("default"))

        scale_value = ScaleBytes(
            "0x0400006e57561de4b4e63f0af8bf336008252a9597e5cdcb7622c72de4ff39731c5402070010a5d4e8"
        )

        obj = RuntimeConfiguration().create_scale_object(
            'Box<Call>', scale_value, metadata=self.metadata_decoder)
        value = obj.decode()

        self.assertEqual(value['call_function'], 'transfer')
        self.assertEqual(value['call_module'], 'Balances')
        self.assertEqual(
            value['call_args'][0]['value'],
            '0x6e57561de4b4e63f0af8bf336008252a9597e5cdcb7622c72de4ff39731c5402'
        )
        self.assertEqual(value['call_args'][1]['value'], 1000000000000)
Exemplo n.º 10
0
    def test_weak_bounded_vec(self):
        # 87 = ['frame_support', 'storage', 'weak_bounded_vec', 'WeakBoundedVec']
        obj = self.runtime_config.create_scale_object(
            'scale_info::318',
            ScaleBytes(
                "0x0401020304050607080a00000000000000000000000000000000"))
        obj.decode()

        self.assertEqual([{
            "id": "0x0102030405060708",
            'amount': 10,
            'reasons': "Fee"
        }], obj.value)

        data = obj.encode([{
            "id": "0x0102030405060708",
            'amount': 10,
            'reasons': "Fee"
        }])
        self.assertEqual(
            '0x0401020304050607080a00000000000000000000000000000000',
            data.to_hex())
Exemplo n.º 11
0
    def get_block_events(self, block_hash: str) -> list:
        """Find `Request` events for the given `block_hash`.

        Args:
            block_hash (str): block hash for which to find event.

        Returns:
            list: list of tuples (event, decoded_event), where `event` represents a raw
            `Request` events and `decoded_event` is a dict of the decoded event.
        """
        substrate = self.get_connection()
        spec_version = substrate.get_block_runtime_version(block_hash).get(
            "specVersion", 0)

        # Obtain metadata
        metadata = substrate.get_block_metadata(block_hash, spec_version)
        contract_metadata = ContractMetadata.create_from_file(
            self.metadata_file, substrate)

        # Iterate through raw events in the block
        new_events = []
        for event in substrate.get_block_events(block_hash, metadata).elements:
            if (event.event_module.name == "Contracts"
                    and event.event.name == "ContractExecution"):
                contract_event_obj = ContractEvent(
                    data=ScaleBytes(event.params[1]["value"]),
                    runtime_config=substrate.runtime_config,
                    contract_metadata=contract_metadata,
                )
                decoded_event = contract_event_obj.decode()

                # Request event was found, add it to the list
                if decoded_event["name"] == "Request":
                    if (substrate.ss58_encode(event.params[0]["value"])
                            in self.tracked_contracts):
                        new_events.append((event, decoded_event))

        return new_events
Exemplo n.º 12
0
    def process_metadata_type(self, type_string, spec_version):

        runtime_type = RuntimeType.query(self.db_session).filter_by(
            type_string=type_string, spec_version=spec_version).first()

        if not runtime_type:

            # Get current Runtime configuration
            try:
                # TODO move logic to RuntimeConfiguration.get_decoder_class
                # TODO FIX ScaleBytes('0x00') does not process Option<*> properly
                decoder_obj = ScaleDecoder.get_decoder_class(
                    type_string, ScaleBytes('0x00'))

                if decoder_obj.sub_type:

                    # Also process sub type
                    if ',' in decoder_obj.sub_type and decoder_obj.sub_type[
                            -1:] not in ['>', ')']:
                        for sub_type in decoder_obj.sub_type.split(','):
                            self.process_metadata_type(sub_type.strip(),
                                                       spec_version)
                    else:
                        self.process_metadata_type(decoder_obj.sub_type,
                                                   spec_version)

                decoder_class_name = decoder_obj.__class__.__name__

            except NotImplementedError:
                decoder_class_name = '[not implemented]'

            runtime_type = RuntimeType(
                spec_version=spec_version,
                type_string=type_string,
                decoder_class=decoder_class_name,
            )

            runtime_type.save(self.db_session)
Exemplo n.º 13
0
 def test_enum_no_value(self):
     obj = self.runtime_config.create_scale_object('scale_info::21',
                                                   ScaleBytes("0x02"))
     obj.decode()
     self.assertEqual('CodeUpdated', obj.value)
Exemplo n.º 14
0
 def test_str_representation(self):
     obj = ScaleDecoder.get_decoder_class('Bytes', ScaleBytes("0x1054657374"))
     obj.decode()
     self.assertEqual(str(obj), "Test")
Exemplo n.º 15
0
 def test_no_more_bytes_available(self):
     obj = ScaleDecoder.get_decoder_class('[u8; 4]', ScaleBytes("0x010203"))
     self.assertRaises(RemainingScaleBytesNotEmptyException, obj.decode, False)
Exemplo n.º 16
0
 def test_scale_decoder_remaining_bytes(self):
     obj = ScaleDecoder.get_decoder_class('[u8; 3]', ScaleBytes("0x010203"))
     self.assertEqual(obj.get_remaining_bytes(), b"\x01\x02\x03")
Exemplo n.º 17
0
    def test_add_scalebytes(self):
        scale_total = ScaleBytes("0x0102") + "0x0304"

        self.assertEqual(scale_total.data, bytearray.fromhex("01020304"))
Exemplo n.º 18
0
 def test_reset(self):
     scale = ScaleBytes("0x01020304")
     scale.get_next_bytes(1)
     scale.reset()
     self.assertEqual(scale.get_remaining_bytes(), b'\x01\x02\x03\x04')
Exemplo n.º 19
0
 def test_validatorprefs_struct(self):
     obj = ScaleDecoder.get_decoder_class('ValidatorPrefsLegacy', ScaleBytes("0x0c00"))
     obj.decode()
     self.assertEqual(obj.value, {'unstakeThreshold': 3, 'validatorPayment': 0})
Exemplo n.º 20
0
 def process_encode(self, value):
     if value[0:2] != '0x' or len(value) != 130:
         raise ValueError('Value should start with "0x" and should be 64 bytes long')
     return ScaleBytes(value)
Exemplo n.º 21
0
    def process_encode(self, value):

        if -2**256 <= int(value) <= 2**256-1:
            return ScaleBytes(bytearray(int(value).to_bytes(32, 'little', signed=True)))
        else:
            raise ValueError('{} out of range for i256'.format(value))
Exemplo n.º 22
0
 def test_compact_bool_false(self):
     obj = ScaleDecoder.get_decoder_class('bool', ScaleBytes("0x00"))
     obj.decode()
     self.assertEqual(obj.value, False)
Exemplo n.º 23
0
    def process_encode(self, value):

        if 0 <= int(value) <= 2**128 - 1:
            return ScaleBytes(bytearray(int(value).to_bytes(16, 'little')))
        else:
            raise ValueError('{} out of range for u128'.format(value))
Exemplo n.º 24
0
 def process_encode(self, value):
     return ScaleBytes(bytearray())
Exemplo n.º 25
0
    def test_tuple(self):
        obj = self.runtime_config.create_scale_object(
            'scale_info::73', ScaleBytes("0x0400000003000000"))
        obj.decode()

        self.assertEqual((4, 3), obj.value)
Exemplo n.º 26
0
 def test_bytes_data_format(self):
     obj = ScaleDecoder.get_decoder_class('Compact<u32>', ScaleBytes(b"\x02\x09\x3d\x00"))
     obj.decode()
     self.assertEqual(obj.value, 1000000)
Exemplo n.º 27
0
    def process_encode(self, value):

        if -32768 <= int(value) <= 32767:
            return ScaleBytes(bytearray(int(value).to_bytes(2, 'little', signed=True)))
        else:
            raise ValueError('{} out of range for i16'.format(value))
Exemplo n.º 28
0
 def test_compact_bool_invalid(self):
     obj = ScaleDecoder.get_decoder_class('bool', ScaleBytes("0x02"))
     self.assertRaises(InvalidScaleTypeValueException, obj.decode)
Exemplo n.º 29
0
    def on_post(self, req, resp):
        metadata = MetadataDecoder(ScaleBytes(req.media.get('result')))

        resp.status = falcon.HTTP_200
        resp.media = metadata.process()
Exemplo n.º 30
0
    def process_encode(self, value):

        if -2147483648 <= int(value) <= 2147483647:
            return ScaleBytes(bytearray(int(value).to_bytes(4, 'little', signed=True)))
        else:
            raise ValueError('{} out of range for i32'.format(value))