示例#1
0
    def create_mock_accounts_pending(self, data):
        accounts = data["accounts"]

        wallet = wallet_from_str(self.shared.wallet)

        assert data["threshold"] == "100000000000000000000000000"
        assert data["source"]

        blocks = {}

        for account_id in accounts:
            blocks[account_id] = ""

            for block in self.shared.pocketable_blocks:
                destination = (
                    block.destination
                    if block.block_type == "send"
                    else block.link_as_account
                )

                if destination != account_id:
                    continue

                try:
                    account = wallet.account_map[destination]
                except KeyError:
                    logger.info(
                        "[MOCK] Account {} to check pending blocks for "
                        "not in mock wallet".format(destination)
                    )
                    continue

                already_pocketed = False

                for account_block in account.blocks:
                    if not account_block.link_block:
                        continue

                    if account_block.link_block.block_hash != block.block_hash:
                        continue

                    if account_block.confirmed:
                        already_pocketed = True
                        break

                if already_pocketed:
                    # Block has already been pocketed
                    continue

                if blocks[account_id] == "":
                    blocks[account_id] = {}

                blocks[account_id][block.block_hash] = {
                    "amount": str(block.amount),
                    "source": block.source
                }

        return {
            "blocks": blocks
        }
示例#2
0
    def do_POST(self):
        result = None

        shared = self.server.shared

        content_length = int(self.headers["Content-Length"])
        post_data = self.rfile.read(content_length)
        post_data = json.loads(post_data)

        with self.server.lock:
            for mock_response in shared.req_responses:
                if mock_response.match(post_data):
                    # If the request parameters correspond, send the
                    # prepared mock response
                    result = mock_response.get()

            if not result and shared.wallet:
                result = self.server.mocker.create_mock_response(post_data)

        if not result:
            logger.info(
                "Didn't find request {}".format(post_data)
            )
            raise ValueError(
                "Didn't find a response for request {}".format(post_data)
            )

        self.send_response(200)

        self.send_header("Content-type", "application/json; charset=utf-8")
        self.end_headers()

        self.wfile.write(bytes(json.dumps(result), "utf-8"))
        return
示例#3
0
 def wrapper(*args, **kwargs):
     wallet = args[0]
     with mock_node.lock:
         logger.info(
             "Hooking wallet to the mocked node from '{}'".format(
                 wrapper._wrapped_method.__name__
             )
         )
         mock_node.shared.wallet = wallet_to_str(wallet)
示例#4
0
    def create_mock_blocks_info(self, data):
        blocks = {}

        wallet = wallet_from_str(self.shared.wallet)

        for block_hash in data["hashes"]:
            found_block = None
            for account in wallet.accounts:
                if block_hash in account.block_map:
                    block = account.block_map[block_hash]

                    found_block = block
                    break

            for block in self.shared.pocketable_blocks:
                if block.block_hash != block_hash:
                    continue

                destination = (
                    block.destination
                    if block.block_type == "send"
                    else block.link_as_account
                )

                try:
                    account = wallet.account_map[destination]
                except KeyError:
                    logger.info(
                        "[MOCK] Account {} not in the mock wallet".format(
                            destination
                        )
                    )

                found_block = block

            if found_block:
                blocks[block_hash] = {
                    "amount": str(found_block.amount),
                    "balance": str(found_block.balance),
                    "contents": found_block.block.json(),
                    # We can fake this for now
                    "height": str(random.randint(2, 10)),
                    "confirmed": "true",
                    "local_timestamp": None
                }
            else:
                logger.info("[MOCK] Didn't find block {}".format(block_hash))

        return {
            "blocks": blocks
        }
示例#5
0
    def wrapper(*args, **kwargs):
        wallet = args[0]
        with mock_node.lock:
            mock_wallet = wallet_from_str(mock_node.shared.wallet)

            if not mock_wallet:
                return

            logger.info(
                "Synchronizing mock wallet with the actual wallet "
                "from '{}'".format(wrapper._wrapped_method.__name__)
            )

            for account in wallet.account_map.values():
                account_id = account.account_id

                if account_id not in mock_wallet.account_map:
                    mock_wallet.add_account(
                        Account.from_dict(account.to_dict())
                    )

                mock_account = mock_wallet.account_map[account_id]

                for block in account.blocks:
                    if block.block_hash not in mock_account.block_map:
                        mock_account.add_block(
                            Block.from_dict(block.to_dict())
                        )

                    mock_block = mock_account.block_map[block.block_hash]

                    if not mock_block.confirmed:
                        mock_block.confirmed = block.confirmed

                    if not mock_block.work:
                        mock_block.work = block.work
                        mock_block.difficulty = block.difficulty

                    if not mock_block.signature:
                        mock_block.signature = block.signature

                mock_account.confirmed_head = None
                mock_account.update_confirmed_head()
                mock_account.precomputed_work = copy.deepcopy(
                    account.precomputed_work
                )

            mock_node.shared.wallet = wallet_to_str(wallet)
            mock_node.synchronize_responses()
示例#6
0
    def create_mock_response(self, data):
        action = data["action"]

        try:
            if action == "account_history":
                return self.create_mock_account_history(data)
            elif action == "blocks_info":
                return self.create_mock_blocks_info(data)
            elif action == "accounts_pending":
                return self.create_mock_accounts_pending(data)
            elif action == "process":
                return self.create_mock_process(data)
            elif action == "active_difficulty":
                return self.create_mock_active_difficulty(data)
            elif action == "version":
                return self.create_mock_version(data)
            else:
                logger.info("[MOCK] Got non-mockable action '{}'".format(action))
        except Exception as exc:
            logger.info("[MOCK] Mock function failed with {}".format(str(exc)))
示例#7
0
    async def handle_subscription(self, response):
        action = response["action"]
        topic = response["topic"]

        if action == "subscribe":
            self.subscriptions[topic] = response.get("options", {})
            logger.info(
                "[MOCK] Subscribed %s %s", topic, self.subscriptions[topic]
            )
        elif action == "unsubscribe":
            try:
                del self.subscriptions[topic]
                logger.info(
                    "[MOCK] Unsubscribed from topic '%s'",
                    topic
                )
            except KeyError:
                logger.info(
                    "[MOCK] Tried to unsubscribe from topic '%s' "
                    "which is not active", topic
                )
示例#8
0
    def create_mock_process(self, data):
        block_data = data["block"]
        wallet = wallet_from_str(self.shared.wallet)

        block = RawBlock.from_json(block_data)

        if not block.signature:
            logger.info(
                "[MOCK] Trying to process unsigned block {}".format(
                    block.block_hash
                )
            )
            return None

        if not block.work:
            logger.info(
                "[MOCK] Trying to process block with no work {}".format(
                    block.block_hash
                )
            )
            return None

        account = wallet.account_map[block.account]
        mock_block = account.block_map[block.block_hash]

        if mock_block.confirmed:
            logger.info(
                "[MOCK] Trying to process confirmed block {}".format(
                    block.block_hash
                )
            )
            return None

        logger.info(
            "[MOCK] Confirming block {}".format(block.block_hash)
        )

        if self.shared.broadcast_fail_counter is not None:
            if self.shared.broadcast_fail_counter == 0:
                return {
                    "error": "Gap source block"
                }
            else:
                self.shared.broadcast_fail_counter -= 1

        if self.shared.difficulty_raise_counter is not None:
            if self.shared.difficulty_raise_counter == 0:
                self.shared.difficulty_raise_counter = None

                self.shared.work_difficulty = derive_work_difficulty(
                    multiplier=1.15, base_difficulty=self.shared.work_difficulty
                )
                return {
                    "error": "Block work is less than threshold"
                }
            else:
                self.shared.difficulty_raise_counter -= 1

        mock_block.confirmed = True

        self.shared.block_arrival_time[block.block_hash] = time.time()
        self.shared.wallet = wallet_to_str(wallet)

        return {
            "hash": block.block_hash
        }
示例#9
0
    def create_mock_account_history(self, data):
        account_id = data["account"]

        wallet = wallet_from_str(self.shared.wallet)

        assert data["raw"]
        assert data["reverse"]
        assert data["count"] == 500

        head = data.get("head", None)

        result = {
            "account": account_id
        }

        try:
            account = wallet.account_map[account_id]
        except KeyError:
            logger.info(
                "[MOCK] Account {} not in mock wallet".format(account_id)
            )

        if not account.blocks:
            return {"error": "Account not found"}

        account_entries = ""

        found_head = False
        for i, block in enumerate(account.blocks):
            block_hash = block.block_hash

            if block_hash == head:
                found_head = True
            elif i == 0 and head is None:
                found_head = True

            if found_head and block.confirmed:
                arrival_time = self.shared.block_arrival_time.get(block.block_hash, 0)
                broadcast_complete = block_hash in self.shared.broadcast_blocks

                # Don't report the block just yet if it's delayed,
                # unless it's been broadcast by WebSocket
                if not broadcast_complete and \
                        time.time() < arrival_time + self.shared.broadcast_delay:
                    continue

                self.shared.broadcast_blocks.add(block_hash)

                if block.link_block:
                    subtype = "receive"
                elif block.tx_type == "send/receive":
                    subtype = "send"
                else:
                    subtype = block.tx_type

                if account_entries == "":
                    account_entries = []

                account_entries.append({
                    "account": account.account_id,
                    "amount": str(block.amount),
                    "balance": str(block.balance),
                    "hash": block.block_hash,
                    "link": block.link,
                    "local_timestamp": None,
                    "previous": block.previous,
                    "representative": block.representative,
                    "signature": block.signature,
                    "subtype": subtype,
                    "type": block.block_type,
                    "work": block.work
                })

        result["history"] = account_entries

        return result