@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 List<APITransaction> getInputTransactions(TID txId) throws BCSAPIException { log.trace("get input transactions " + txId); ConnectorMessage m; try (ConnectorSession session = connection.createSession()) { ConnectorProducer transactionRequestProducer = session.createProducer(session.createQueue("inputTransactionsRequest")); m = session.createMessage(); BCSAPIMessage.Hash.Builder builder = BCSAPIMessage.Hash.newBuilder(); builder.addHash(ByteString.copyFrom(txId.unsafeGetArray())); m.setPayload(builder.build().toByteArray()); byte[] response = synchronousRequest(session, transactionRequestProducer, m); if (response != null) { List<BCSAPIMessage.OPTIONAL_TX> txsList = BCSAPIMessage.TXS.parseFrom(response).getTxsList(); List<APITransaction> txs = new ArrayList<>(txsList.size()); for (BCSAPIMessage.OPTIONAL_TX tx : txsList) { if (tx.getIsNull()) { txs.add(null); } else { txs.add(APITransaction.fromProtobuf(tx.getTransaction())); } } return txs; } } catch (ConnectorException | HyperLedgerException | InvalidProtocolBufferException e) { throw new BCSAPIException(e); } return null; }
private byte[] synchronousRequest( ConnectorSession session, ConnectorProducer producer, ConnectorMessage m) throws BCSAPIException { ConnectorTemporaryQueue answerQueue = null; try { answerQueue = session.createTemporaryQueue(); m.setReplyTo(answerQueue); try (ConnectorConsumer consumer = session.createConsumer(answerQueue)) { producer.send(m); ConnectorMessage reply = consumer.receive(clientSettings.getTimeout()); if (reply == null) { throw new BCSAPIException("timeout"); } return reply.getPayload(); } } catch (ConnectorException e) { throw new BCSAPIException(e); } finally { try { if (answerQueue != null) { answerQueue.delete(); } } catch (ConnectorException e) { } } }
@SuppressWarnings("unchecked") private <T> void addTopicListener( String topic, Object inner, ByteArrayConverter<T> converter, TypedListener<T> listener) throws ConnectorException { synchronized (messageDispatcher) { MessageDispatcher<T> dispatcher = messageDispatcher.get(topic); if (dispatcher == null) { ConnectorSession session = connection.createSession(); ConnectorConsumer consumer = session.createConsumer(session.createTopic(topic)); messageDispatcher.put(topic, dispatcher = new MessageDispatcher<T>(consumer, converter)); } dispatcher.addListener(inner, listener); } }
@Override public int getChainHeight() throws BCSAPIException { try (ConnectorSession session = connection.createSession()) { log.trace("get chain height"); ConnectorProducer heightRequestProducer = session.createProducer(session.createQueue("chainHeightRequest")); ConnectorMessage m = session.createMessage(); byte[] response = synchronousRequest(session, heightRequestProducer, m); if (response != null) { return BCSAPIMessage.HEIGHT.parseFrom(response).getHeight(); } } catch (ConnectorException | InvalidProtocolBufferException e) { throw new BCSAPIException(e); } return -1; }
@Override public void sendBlock(Block block) throws BCSAPIException { try (ConnectorSession session = connection.createSession()) { log.trace("send block " + block.getID()); ConnectorProducer blockProducer = session.createProducer(session.createTopic("newBlock")); ConnectorMessage m = session.createMessage(); m.setPayload(block.toBCSAPIMessage().toByteArray()); byte[] reply = synchronousRequest(session, blockProducer, m); if (reply != null) { try { BCSAPIMessage.ExceptionMessage em = BCSAPIMessage.ExceptionMessage.parseFrom(reply); throw new BCSAPIException(em.getMessage(0)); } catch (InvalidProtocolBufferException e) { throw new BCSAPIException("Invalid response", e); } } } catch (ConnectorException e) { throw new BCSAPIException(e); } }
@Override public APIHeader mine(Address address) throws BCSAPIException { try (ConnectorSession session = connection.createSession()) { log.trace("mine to " + address); ConnectorProducer producer = session.createProducer(session.createTopic("mine")); ConnectorMessage m = session.createMessage(); BCSAPIMessage.Script.Builder builder = BCSAPIMessage.Script.newBuilder() .setScript(ByteString.copyFrom(address.getAddressScript().toByteArray())); m.setPayload(builder.build().toByteArray()); byte[] reply = synchronousRequest(session, producer, m); if (reply != null) { return APIHeader.fromProtobuf(BCSAPIMessage.BLK.parseFrom(reply)); } } catch (ConnectorException | InvalidProtocolBufferException | HyperLedgerException 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; }
private BCSAPIMessage.Ping handshake(long nonce) throws BCSAPIException { try (ConnectorSession session = connection.createSession()) { log.trace("ping " + nonce); ConnectorMessage m = session.createMessage(); BCSAPIMessage.Ping.Builder builder = BCSAPIMessage.Ping.newBuilder(); builder.setNonce(nonce); builder.setClientVersion(getClientVersion()); m.setPayload(builder.build().toByteArray()); ConnectorProducer pingProducer = session.createProducer(session.createQueue("ping")); byte[] response = synchronousRequest(session, pingProducer, m); if (response != null) { BCSAPIMessage.Ping echo = BCSAPIMessage.Ping.parseFrom(response); if (echo.getNonce() != nonce) { throw new BCSAPIException("Incorrect echo nonce from ping"); } return echo; } throw new BCSAPIException("no reply"); } catch (ConnectorException | InvalidProtocolBufferException e) { throw new BCSAPIException(e); } }
@Override public APITransaction getTransaction(TID hash) throws BCSAPIException { log.trace("get transaction " + hash); ConnectorMessage m; try (ConnectorSession session = connection.createSession()) { ConnectorProducer transactionRequestProducer = session.createProducer(session.createQueue("transactionRequest")); 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, transactionRequestProducer, m); if (response != null) { APITransaction t; t = APITransaction.fromProtobuf(BCSAPIMessage.TX.parseFrom(response)); return t; } } catch (ConnectorException | HyperLedgerException | InvalidProtocolBufferException e) { throw new BCSAPIException(e); } return null; }
@Override public void spendingTransactions(List<TID> tids, final TransactionListener listener) throws BCSAPIException { try (ConnectorSession session = connection.createSession()) { ConnectorMessage m = session.createMessage(); ConnectorProducer scanAccountProducer = session.createProducer(session.createQueue("spendingTransactions")); BCSAPIMessage.Hash.Builder builder = BCSAPIMessage.Hash.newBuilder(); for (TID tid : tids) { builder.addHash(ByteString.copyFrom(tid.unsafeGetArray())); } m.setPayload(builder.build().toByteArray()); final ConnectorTemporaryQueue answerQueue = session.createTemporaryQueue(); final ConnectorConsumer consumer = session.createConsumer(answerQueue); m.setReplyTo(answerQueue); final Semaphore ready = new Semaphore(0); consumer.setMessageListener( message -> { try { byte[] body = message.getPayload(); if (body != null) { APITransaction t = APITransaction.fromProtobuf(BCSAPIMessage.TX.parseFrom(body)); listener.process(t); } else { consumer.close(); answerQueue.delete(); ready.release(); } } catch (ConnectorException | HyperLedgerException | InvalidProtocolBufferException e) { log.error("Malformed message received for spendingt ransactions request", e); } }); scanAccountProducer.send(m); ready.acquireUninterruptibly(); } catch (ConnectorException e) { throw new BCSAPIException(e); } }
private void scanRequest( Collection<Script> match, final TransactionListener listener, String requestQueue) throws BCSAPIException { try (ConnectorSession session = connection.createSession()) { ConnectorMessage m = session.createMessage(); ConnectorProducer exactMatchProducer = session.createProducer(session.createQueue(requestQueue)); BCSAPIMessage.ExactMatchRequest.Builder builder = BCSAPIMessage.ExactMatchRequest.newBuilder(); for (Script d : match) { builder.addMatch(ByteString.copyFrom(d.toByteArray())); } m.setPayload(builder.build().toByteArray()); final ConnectorTemporaryQueue answerQueue = session.createTemporaryQueue(); final ConnectorConsumer consumer = session.createConsumer(answerQueue); m.setReplyTo(answerQueue); final Semaphore ready = new Semaphore(0); consumer.setMessageListener( message -> { try { byte[] body = message.getPayload(); if (body != null) { APITransaction t = APITransaction.fromProtobuf(BCSAPIMessage.TX.parseFrom(body)); listener.process(t); } else { consumer.close(); answerQueue.delete(); ready.release(); } } catch (ConnectorException | HyperLedgerException | InvalidProtocolBufferException e) { log.error("Malformed message received for scan matching transactions", e); } }); exactMatchProducer.send(m); ready.acquireUninterruptibly(); } catch (ConnectorException e) { throw new BCSAPIException(e); } }
private void scanRequest( MasterPublicKey master, int lookAhead, final TransactionListener listener, String request) throws BCSAPIException { try (ConnectorSession session = connection.createSession()) { ConnectorMessage m = session.createMessage(); ConnectorProducer scanAccountProducer = session.createProducer(session.createQueue(request)); BCSAPIMessage.AccountRequest.Builder builder = BCSAPIMessage.AccountRequest.newBuilder(); builder.setPublicKey(master.serialize(true)); builder.setLookAhead(lookAhead); m.setPayload(builder.build().toByteArray()); final ConnectorTemporaryQueue answerQueue = session.createTemporaryQueue(); final ConnectorConsumer consumer = session.createConsumer(answerQueue); m.setReplyTo(answerQueue); final Semaphore ready = new Semaphore(0); consumer.setMessageListener( message -> { try { byte[] body = message.getPayload(); if (body != null) { APITransaction t = APITransaction.fromProtobuf(BCSAPIMessage.TX.parseFrom(body)); listener.process(t); } else { consumer.close(); answerQueue.delete(); ready.release(); } } catch (ConnectorException | HyperLedgerException | InvalidProtocolBufferException e) { log.error("Malformed message received for account scan transactions", e); } }); scanAccountProducer.send(m); ready.acquireUninterruptibly(); } catch (ConnectorException e) { throw new BCSAPIException(e); } }