@Override
  public void catchUp(List<BID> inventory, int limit, boolean headers, final TrunkListener listener)
      throws BCSAPIException {
    log.trace("catchUp");
    ConnectorMessage m;
    try (ConnectorSession session = connection.createSession()) {
      ConnectorProducer transactionRequestProducer =
          session.createProducer(session.createQueue("catchUpRequest"));

      m = session.createMessage();
      BCSAPIMessage.CatchUpRequest.Builder builder = BCSAPIMessage.CatchUpRequest.newBuilder();
      builder.setLimit(limit);
      builder.setHeaders(true);
      for (BID hash : inventory) {
        builder.addInventory(ByteString.copyFrom(hash.unsafeGetArray()));
      }
      m.setPayload(builder.build().toByteArray());
      byte[] response = synchronousRequest(session, transactionRequestProducer, m);
      if (response != null) {
        BCSAPIMessage.TrunkUpdate blockMessage = BCSAPIMessage.TrunkUpdate.parseFrom(response);
        List<APIBlock> blockList = new ArrayList<>();
        for (BCSAPIMessage.BLK b : blockMessage.getAddedList()) {
          blockList.add(APIBlock.fromProtobuf(b));
        }
        listener.trunkUpdate(blockList);
      }
    } catch (ConnectorException | HyperLedgerException | InvalidProtocolBufferException e) {
      throw new BCSAPIException(e);
    }
  }
  @Override
  public APIBlockIdList getBlockIds(BID blockId, int count) throws BCSAPIException {
    try (ConnectorSession session = connection.createSession()) {
      log.trace("get " + count + " block ids from " + blockId);

      ConnectorProducer blockIdsRequestProducer =
          session.createProducer(session.createQueue("blockIdsRequest"));

      ConnectorMessage m = session.createMessage();
      BCSAPIMessage.BLKIDSREQ.Builder builder = BCSAPIMessage.BLKIDSREQ.newBuilder();
      if (blockId != null) {
        builder.setBlockHash(ByteString.copyFrom(blockId.unsafeGetArray()));
      }
      if (count <= 0) count = 20;
      builder.setCount(count);
      m.setPayload(builder.build().toByteArray());
      byte[] response = synchronousRequest(session, blockIdsRequestProducer, m);
      if (response != null) {
        BCSAPIMessage.BLKIDS message = BCSAPIMessage.BLKIDS.parseFrom(response);
        List<ByteString> blockIdsList = message.getBlockIdsList();
        List<BID> blockIds =
            blockIdsList.stream().map(bs -> new BID(bs.toByteArray())).collect(Collectors.toList());
        return new APIBlockIdList(
            blockIds,
            message.getHeight(),
            message.hasPreviousBlockId()
                ? new BID(message.getPreviousBlockId().toByteArray())
                : null);
      }
    } catch (ConnectorException | InvalidProtocolBufferException e) {
      throw new BCSAPIException(e);
    }

    return null;
  }
  @Override
  public APIHeader getBlockHeader(BID hash) throws BCSAPIException {
    try (ConnectorSession session = connection.createSession()) {
      log.trace("get block header" + hash);

      ConnectorProducer blockHeaderRequestProducer =
          session.createProducer(session.createQueue("headerRequest"));

      ConnectorMessage m = session.createMessage();
      BCSAPIMessage.Hash.Builder builder = BCSAPIMessage.Hash.newBuilder();
      builder.addHash(ByteString.copyFrom(hash.unsafeGetArray()));
      m.setPayload(builder.build().toByteArray());
      byte[] response = synchronousRequest(session, blockHeaderRequestProducer, m);
      if (response != null) {
        return APIHeader.fromProtobuf(BCSAPIMessage.BLK.parseFrom(response));
      }
    } catch (ConnectorException | InvalidProtocolBufferException e) {
      throw new BCSAPIException(e);
    }

    return null;
  }