Search in sources :

Example 1 with RawBlock

use of bisq.core.dao.state.blockchain.RawBlock in project bisq-core by bisq-network.

the class BlockParser method validateIfBlockIsConnecting.

private void validateIfBlockIsConnecting(RawBlock rawBlock) throws BlockNotConnectingException {
    LinkedList<Block> blocks = bsqStateService.getBlocks();
    if (!isBlockConnecting(rawBlock, blocks)) {
        final Block last = blocks.getLast();
        log.warn("addBlock called with a not connecting block. New block:\n" + "height()={}, hash()={}, lastBlock.height()={}, lastBlock.hash()={}", rawBlock.getHeight(), rawBlock.getHash(), last != null ? last.getHeight() : "null", last != null ? last.getHash() : "null");
        throw new BlockNotConnectingException(rawBlock);
    }
}
Also used : RawBlock(bisq.core.dao.state.blockchain.RawBlock) Block(bisq.core.dao.state.blockchain.Block) BlockNotConnectingException(bisq.core.dao.node.parser.exceptions.BlockNotConnectingException)

Example 2 with RawBlock

use of bisq.core.dao.state.blockchain.RawBlock in project bisq-core by bisq-network.

the class FullNodeNetworkService method publishNewBlock.

public void publishNewBlock(Block block) {
    log.info("Publish new block at height={} and block hash={}", block.getHeight(), block.getHash());
    RawBlock rawBlock = RawBlock.fromBlock(block);
    NewBlockBroadcastMessage newBlockBroadcastMessage = new NewBlockBroadcastMessage(rawBlock);
    broadcaster.broadcast(newBlockBroadcastMessage, networkNode.getNodeAddress(), null, true);
}
Also used : RawBlock(bisq.core.dao.state.blockchain.RawBlock) NewBlockBroadcastMessage(bisq.core.dao.node.messages.NewBlockBroadcastMessage)

Example 3 with RawBlock

use of bisq.core.dao.state.blockchain.RawBlock in project bisq-core by bisq-network.

the class GetBlocksRequestHandler method onGetBlocksRequest.

// /////////////////////////////////////////////////////////////////////////////////////////
// API
// /////////////////////////////////////////////////////////////////////////////////////////
public void onGetBlocksRequest(GetBlocksRequest getBlocksRequest, final Connection connection) {
    Log.traceCall(getBlocksRequest + "\n\tconnection=" + connection);
    List<Block> blocks = new LinkedList<>(bsqStateService.getBlocksFromBlockHeight(getBlocksRequest.getFromBlockHeight()));
    List<RawBlock> rawBlocks = blocks.stream().map(RawBlock::fromBlock).collect(Collectors.toList());
    final GetBlocksResponse getBlocksResponse = new GetBlocksResponse(rawBlocks, getBlocksRequest.getNonce());
    log.debug("getBlocksResponse " + getBlocksResponse.getRequestNonce());
    if (timeoutTimer == null) {
        timeoutTimer = UserThread.runAfter(() -> {
            // setup before sending to avoid race conditions
            String errorMessage = "A timeout occurred for getBlocksResponse:" + getBlocksResponse + " on connection:" + connection;
            handleFault(errorMessage, CloseConnectionReason.SEND_MSG_TIMEOUT, connection);
        }, TIMEOUT, TimeUnit.SECONDS);
    }
    SettableFuture<Connection> future = networkNode.sendMessage(connection, getBlocksResponse);
    Futures.addCallback(future, new FutureCallback<Connection>() {

        @Override
        public void onSuccess(Connection connection) {
            if (!stopped) {
                log.trace("Send DataResponse to {} succeeded. getBlocksResponse={}", connection.getPeersNodeAddressOptional(), getBlocksResponse);
                cleanup();
                listener.onComplete();
            } else {
                log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call.");
            }
        }

        @Override
        public void onFailure(@NotNull Throwable throwable) {
            if (!stopped) {
                String errorMessage = "Sending getBlocksResponse to " + connection + " failed. That is expected if the peer is offline. getBlocksResponse=" + getBlocksResponse + "." + "Exception: " + throwable.getMessage();
                handleFault(errorMessage, CloseConnectionReason.SEND_MSG_FAILURE, connection);
            } else {
                log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call.");
            }
        }
    });
}
Also used : RawBlock(bisq.core.dao.state.blockchain.RawBlock) Connection(bisq.network.p2p.network.Connection) RawBlock(bisq.core.dao.state.blockchain.RawBlock) Block(bisq.core.dao.state.blockchain.Block) LinkedList(java.util.LinkedList) GetBlocksResponse(bisq.core.dao.node.messages.GetBlocksResponse)

Example 4 with RawBlock

use of bisq.core.dao.state.blockchain.RawBlock in project bisq-core by bisq-network.

the class BlockParser method parseBlock.

// /////////////////////////////////////////////////////////////////////////////////////////
// API
// /////////////////////////////////////////////////////////////////////////////////////////
/**
 * @param rawBlock  Contains all transactions of a bitcoin block without any BSQ specific data
 * @return Block: Gets created from the rawBlock but contains only BSQ specific transactions.
 * @throws BlockNotConnectingException If new block does not connect to previous block
 */
public Block parseBlock(RawBlock rawBlock) throws BlockNotConnectingException {
    int blockHeight = rawBlock.getHeight();
    log.debug("Parse block at height={} ", blockHeight);
    validateIfBlockIsConnecting(rawBlock);
    bsqStateService.onNewBlockHeight(blockHeight);
    // We create a block from the rawBlock but the transaction list is not set yet (is empty)
    final Block block = new Block(blockHeight, rawBlock.getTime(), rawBlock.getHash(), rawBlock.getPreviousBlockHash());
    if (isBlockAlreadyAdded(rawBlock)) {
        // TODO check how/if that can happen
        log.warn("Block was already added.");
        DevEnv.logErrorAndThrowIfDevMode("Block was already added. rawBlock=" + rawBlock);
    } else {
        bsqStateService.onNewBlockWithEmptyTxs(block);
    }
    // Worst case is that all txs in a block are depending on another, so only one get resolved at each iteration.
    // Min tx size is 189 bytes (normally about 240 bytes), 1 MB can contain max. about 5300 txs (usually 2000).
    // Realistically we don't expect more then a few recursive calls.
    // There are some blocks with testing such dependency chains like block 130768 where at each iteration only
    // one get resolved.
    // Lately there is a patter with 24 iterations observed
    long startTs = System.currentTimeMillis();
    List<Tx> txList = block.getTxs();
    rawBlock.getRawTxs().forEach(rawTx -> txParser.findTx(rawTx, genesisTxId, genesisBlockHeight, genesisTotalSupply).ifPresent(txList::add));
    log.debug("parseBsqTxs took {} ms", rawBlock.getRawTxs().size(), System.currentTimeMillis() - startTs);
    bsqStateService.onParseBlockComplete(block);
    return block;
}
Also used : Tx(bisq.core.dao.state.blockchain.Tx) RawBlock(bisq.core.dao.state.blockchain.RawBlock) Block(bisq.core.dao.state.blockchain.Block)

Aggregations

RawBlock (bisq.core.dao.state.blockchain.RawBlock)4 Block (bisq.core.dao.state.blockchain.Block)3 GetBlocksResponse (bisq.core.dao.node.messages.GetBlocksResponse)1 NewBlockBroadcastMessage (bisq.core.dao.node.messages.NewBlockBroadcastMessage)1 BlockNotConnectingException (bisq.core.dao.node.parser.exceptions.BlockNotConnectingException)1 Tx (bisq.core.dao.state.blockchain.Tx)1 Connection (bisq.network.p2p.network.Connection)1 LinkedList (java.util.LinkedList)1