예제 #1
0
    def test_hash_origin_case_v2(self):
        request = r'''{
            "jsonrpc": "2.0",
            "method": "icx_sendTransaction",
            "id": 1234,
            "params": {
                "from": "hxbe258ceb872e08851f1f59694dac2558708ece11",
                "to": "hx5bfdb090f43a808005ffc27c25b213145e80b7cd",
                "value": "0xde0b6b3a7640000",
                "fee": "0x1000000",
                "timestamp": "1000000000000",
                "nonce": "0x1",
                "tx_hash": "a247a97a23398daccb66e2d61d63788b3c2edb91e1fdbb4f34d86d485eb72915",
                "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA="
            }
        }'''

        logging.info(f"request : {request}")
        request = json.loads(request)
        logging.info(f"request loaded : {request}")

        question = request["params"]
        answer = "icx_sendTransaction.fee.0x1000000.from.hxbe258ceb872e08851f1f59694dac2558708ece11.nonce.0x1." \
                 "timestamp.1000000000000.to.hx5bfdb090f43a808005ffc27c25b213145e80b7cd." \
                 "value.0xde0b6b3a7640000"

        tv = TransactionVersions()
        version = tv.get_version(question)
        ts = TransactionSerializer.new(version,
                                       tv.get_hash_generator_version(version))
        tx = ts.from_(question)

        result = self.hash_generator.generate_salted_origin(
            ts.to_origin_data(tx))
        self.assertEqual(result, answer)
예제 #2
0
    async def create_icx_tx(self, kwargs: dict):
        result_code = None
        exception = None

        try:
            tv = TransactionVersions()
            tx_version = tv.get_version(kwargs)
            tx_hash_version = self._channel_service.get_channel_option()["tx_hash_version"]

            ts = TransactionSerializer.new(tx_version, tx_hash_version)
            tx = ts.from_(kwargs)

            tv = TransactionVerifier.new(tx_version, tx_hash_version)
            tv.verify(tx)

            block_manager = self._channel_service.block_manager
            block_manager.pre_validate(tx)

            logging.debug(f"create icx input : {kwargs}")

            self._channel_service.broadcast_scheduler.schedule_job(BroadcastCommand.CREATE_TX, tx)
            return message_code.Response.success, tx.hash.hex()

        except TransactionInvalidError as e:
            result_code = e.message_code
            exception = e
        except BaseException as e:
            result_code = TransactionInvalidError.message_code
            exception = e
        finally:
            if exception:
                logging.warning(f"create_icx_tx: tx restore fail for kwargs({kwargs}), {exception}")
                return result_code, None
예제 #3
0
    def test_hash_case_v3_escape(self):
        request = r'''{
            "jsonrpc": "2.0",
            "method": "icx_sendTransaction",
            "id": 1234,
            "params": {
                "version": "0x3",
                "from": "hxbe258ceb872e08851f1f59694dac2558708ece11",
                "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32",
                "stepLimit": "0x12345",
                "timestamp": "0x563a6cf330136",
                "nonce": "0x1",
                "nid": "0x2",
                "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=",
                "dataType": "call",
                "data": {
                    "method": "transfer",
                    "params": {
                        "to": "hx.ab2d8215eab\\14bc6bdd8bfb2c[8151257]032ec{d8}b",
                        "value": "0x1",
                        "array0": [
                            "1",
                            "2.21"
                        ],
                        "array1": [
                            {
                                "hash": "0x12",
                                "value": "0x34"
                            },
                            {
                                "hash": "0x56",
                                "value": "0x78"
                            }
                        ]
                    }
                }
            }
        }'''

        logging.info(f"request : {request}")
        request = json.loads(request)
        logging.info(f"request loaded : {request}")
        logging.info(f"to : {request['params']['data']['params']['to']}")

        question = request['params']
        answer = r"icx_sendTransaction.data.{method.transfer.params." \
                 r"{array0.[1.2\.21].array1.[{hash.0x12.value.0x34}.{hash.0x56.value.0x78}]." \
                 r"to.hx\.ab2d8215eab\\14bc6bdd8bfb2c\[8151257\]032ec\{d8\}b.value.0x1}}." \
                 r"dataType.call.from.hxbe258ceb872e08851f1f59694dac2558708ece11.nid.0x2.nonce.0x1.stepLimit.0x12345." \
                 r"timestamp.0x563a6cf330136.to.cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32.version.0x3"

        tv = TransactionVersions()
        version = tv.get_version(question)
        ts = TransactionSerializer.new(version,
                                       tv.get_hash_generator_version(version))
        tx = ts.from_(question)
        result = self.hash_generator.generate_salted_origin(
            ts.to_origin_data(tx))
        logging.info(f"result : {result}")
        self.assertEqual(result, answer)
예제 #4
0
    def add_tx(self, request) -> None:
        tx_json = request.tx_json

        tv = TransactionVersions()
        tx_version = tv.get_version(tx_json)
        tx_hash_version = self._channel_service.get_channel_option(
        )["tx_hash_version"]

        ts = TransactionSerializer.new(tx_version, tx_hash_version)
        tx = ts.from_(tx_json)

        tv = TransactionVerifier.new(tx_version, tx_hash_version)
        tv.verify(tx)

        object_has_queue = self._channel_service.get_object_has_queue_by_consensus(
        )
        if tx is not None:
            object_has_queue.add_tx_obj(tx)
            util.apm_event(
                ChannelProperty().peer_id, {
                    'event_type': 'AddTx',
                    'peer_id': ChannelProperty().peer_id,
                    'peer_name': conf.PEER_NAME,
                    'channel_name': ChannelProperty().name,
                    'data': {
                        'tx_hash': tx.tx_hash
                    }
                })
예제 #5
0
    def _makeup_block(self):
        block_builder = BlockBuilder.new("0.1a")

        tx_versions = TransactionVersions()
        while self._txQueue:
            if len(block_builder) >= conf.MAX_TX_SIZE_IN_BLOCK:
                logging.debug(
                    f"consensus_base total size({len(block_builder)}) "
                    f"count({len(block_builder.transactions)}) "
                    f"_txQueue size ({len(self._txQueue)})")
                break

            tx: 'Transaction' = self._txQueue.get_item_in_status(
                TransactionStatusInQueue.normal,
                TransactionStatusInQueue.added_to_block)
            if tx is None:
                break

            tx_hash_version = tx_versions.get_hash_generator_version(
                tx.version)
            tv = TransactionVerifier.new(tx.version, tx_hash_version)

            try:
                tv.verify(tx, self._blockchain)
            except Exception as e:
                logging.warning(f"tx hash invalid. tx: {tx}")
            else:
                block_builder.transactions[tx.hash] = tx

        return block_builder
예제 #6
0
class TxItemJson:
    tx_versions = TransactionVersions()
    tx_serializers = {
        "0x2":
        TransactionSerializer.new(
            "0x2", tx_versions.get_hash_generator_version("0x2")),
        "0x3":
        TransactionSerializer.new(
            "0x3", tx_versions.get_hash_generator_version("0x3"))
    }

    def __init__(self, tx_json: str, channel: str):
        self.channel = channel
        self.__tx_json = tx_json
        self.__len = sys.getsizeof(tx_json) + sys.getsizeof(channel)

    def __len__(self):
        return self.__len

    def get_tx_message(self):
        message = loopchain_pb2.TxSend(tx_json=self.__tx_json,
                                       channel=self.channel)
        return message

    @classmethod
    def create_tx_item(cls, tx: Transaction, channel: str):
        # util.logger.spam(f"tx_item_helper_icx:create_tx_item create_tx_param({create_tx_param})")
        tx_serializer = cls.tx_serializers[tx.version]

        tx_item = TxItemJson(json.dumps(tx_serializer.to_raw_data(tx)),
                             channel)
        return tx_item
예제 #7
0
    async def get_block_v2(self, block_height, block_hash, block_data_filter,
                           tx_data_filter):
        # This is a temporary function for v2 support of exchanges.
        block, block_filter, block_hash, fail_response_code, tx_filter = await self.__get_block(
            block_data_filter, block_hash, block_height, tx_data_filter)
        if fail_response_code:
            return fail_response_code, block_hash, json.dumps({}), ""

        bs = BlockSerializer.new(block.header.version)
        block_data_dict = bs.serialize(block)

        if block.header.height == 0:
            return message_code.Response.success, block_hash, json.dumps(
                block_data_dict), []

        confirmed_tx_list = block_data_dict["confirmed_transaction_list"]
        confirmed_tx_list_without_fail = []

        tv = TransactionVersions()
        tss = {
            "genesis":
            TransactionSerializer.new(
                "genesis", tv.get_hash_generator_version("genesis")),
            "0x2":
            TransactionSerializer.new("0x2",
                                      tv.get_hash_generator_version("0x2")),
            "0x3":
            TransactionSerializer.new("0x3",
                                      tv.get_hash_generator_version("0x3"))
        }

        for tx in confirmed_tx_list:
            version = tv.get_version(tx)
            tx_hash = tss[version].get_hash(tx)

            invoke_result = self._channel_service.block_manager.get_invoke_result(
                tx_hash)

            if 'failure' in invoke_result:
                continue

            if tv.get_version(tx) == "0x3":
                step_used, step_price = int(invoke_result["stepUsed"],
                                            16), int(
                                                invoke_result["stepPrice"], 16)
                tx["fee"] = hex(step_used * step_price)

            confirmed_tx_list_without_fail.append(tx)

        # Replace the existing confirmed_tx_list with v2 ver.
        block_data_dict[
            "confirmed_transaction_list"] = confirmed_tx_list_without_fail
        block_data_json = json.dumps(block_data_dict)

        if fail_response_code:
            return fail_response_code, block_hash, json.dumps({}), []

        return message_code.Response.success, block_hash, block_data_json, []
예제 #8
0
    def add_tx_list(self, request) -> tuple:
        tx_validate_count = 0

        for tx_item in request.tx_list:
            tx_json = json.loads(tx_item.tx_json)

            tv = TransactionVersions()
            tx_version = tv.get_version(tx_json)
            tx_hash_version = self._channel_service.get_channel_option(
            )["tx_hash_version"]

            ts = TransactionSerializer.new(tx_version, tx_hash_version)
            tx = ts.from_(tx_json)

            tv = TransactionVerifier.new(tx_version, tx_hash_version)
            tv.verify(tx)

            # util.logger.spam(f"channel_inner_service:add_tx tx({tx.get_data_string()})")

            object_has_queue = self._channel_service.get_object_has_queue_by_consensus(
            )
            if tx is not None:
                object_has_queue.add_tx_obj(tx)
                tx_validate_count += 1
                util.apm_event(
                    ChannelProperty().peer_id, {
                        'event_type': 'AddTx',
                        'peer_id': ChannelProperty().peer_id,
                        'peer_name': conf.PEER_NAME,
                        'channel_name': ChannelProperty().name,
                        'data': {
                            'tx_hash': tx.hash.hex()
                        }
                    })

        if tx_validate_count == 0:
            response_code = message_code.Response.fail
            message = "fail tx validate while AddTxList"
        else:
            response_code = message_code.Response.success
            message = f"success ({tx_validate_count})/({len(request.tx_list)})"

        return response_code, message
예제 #9
0
    def test_hash_case_v2_v3_compatibility(self):

        # These methods are obsolete.
        # But this one and new one must have same results for v2 request.
        def create_origin_for_hash(json_data: dict):
            def gen_origin_str(json_data: dict):
                ordered_keys = list(json_data)
                ordered_keys.sort()
                for key in ordered_keys:
                    yield key
                    if isinstance(json_data[key], str):
                        yield json_data[key]
                    elif isinstance(json_data[key], dict):
                        yield from gen_origin_str(json_data[key])
                    elif isinstance(json_data[key], int):
                        yield str(json_data[key])
                    else:
                        raise TypeError(
                            f"{key} must be one of them(dict, str, int).")

            origin = ".".join(gen_origin_str(json_data))
            return origin

        def generate_icx_hash(icx_origin_data, tx_hash_key):
            copy_tx = copy.deepcopy(icx_origin_data)
            if 'method' in copy_tx:
                del copy_tx['method']
            if 'signature' in copy_tx:
                del copy_tx['signature']
            if tx_hash_key in copy_tx:
                del copy_tx[tx_hash_key]
            origin = create_origin_for_hash(copy_tx)
            origin = f"icx_sendTransaction.{origin}"
            # gen hash
            return hashlib.sha3_256(origin.encode()).digest()

        request = r'''{
            "jsonrpc": "2.0",
            "method": "icx_sendTransaction",
            "id": 1234,
            "params": {
                "version": "0x3",
                "from": "hxbe258ceb872e08851f1f59694dac2558708ece11",
                "to": "hx5bfdb090f43a808005ffc27c25b213145e80b7cd",
                "value": "0xde0b6b3a7640000",
                "timestamp": "0x563a6cf330136",
                "nonce": "0x1",
                "stepLimit": "0x100000",
                "nid": "0x2",
                "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA="
            }
        }'''

        logging.info(f"request : {request}")
        request = json.loads(request)
        logging.info(f"request loaded : {request}")

        question = request["params"]

        tv = TransactionVersions()
        version = tv.get_version(question)
        ts = TransactionSerializer.new(version,
                                       tv.get_hash_generator_version(version))
        tx = ts.from_(question)

        result_new_hash = self.hash_generator.generate_hash(
            ts.to_origin_data(tx))
        result_old_hash = generate_icx_hash(question, "tx_hash")
        self.assertEqual(result_new_hash, result_old_hash)

        v0_hash_generator = build_hash_generator(0, "icx_sendTransaction")
        result_old_hash = v0_hash_generator.generate_hash(
            ts.to_origin_data(tx))

        self.assertEquals(result_new_hash, result_old_hash)