class ExecutionBlockRetriever {

    public Block getExecutionBlock(String bnOrId) {
        if (LATEST_ID.equals(bnOrId)) {
            return blockchain.getBestBlock();
        }

        if (PENDING_ID.equals(bnOrId)) {
            Optional<Block> latestBlock = minerServer.getLatestBlock();
            if (latestBlock.isPresent()) {
                return latestBlock.get();
            }

            Block bestBlock = blockchain.getBestBlock();
            if (cachedBlock == null || !bestBlock.isParentOf(cachedBlock)) {
                cachedBlock = builder.build(bestBlock, null);
            }

            return cachedBlock;
        }

        // Is the block specifier either a hexadecimal or decimal number?
        Optional<Long> executionBlockNumber = Optional.empty();

        if (Utils.isHexadecimalString(bnOrId)) {
            executionBlockNumber = Optional.of(Utils.hexadecimalStringToLong(bnOrId));
        } else if (Utils.isDecimalString(bnOrId)) {
            executionBlockNumber = Optional.of(Utils.decimalStringToLong(bnOrId));
        }

        if (executionBlockNumber.isPresent()) {
            Block executionBlock = blockchain.getBlockByNumber(executionBlockNumber.get());
            if (executionBlock == null) {
                throw new JsonRpcInvalidParamException(String.format("Invalid block number %d", executionBlockNumber.get()));
            }
            return executionBlock;
        }

        // If we got here, the specifier given is unsupported
        throw new JsonRpcInvalidParamException(String.format(
                "Unsupported block specifier '%s'. Can only be either 'latest', " +
                "'pending' or a specific block number (either hex - prepending '0x' or decimal).",
                bnOrId));
    }

    @Autowired public  ExecutionBlockRetriever(Blockchain blockchain, MinerServer minerServer, BlockToMineBuilder builder);

}