Search in sources :

Example 1 with Block

use of bisq.core.dao.state.blockchain.Block 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 Block

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

the class FullNode method addBlockHandler.

// /////////////////////////////////////////////////////////////////////////////////////////
// Private
// /////////////////////////////////////////////////////////////////////////////////////////
private void addBlockHandler() {
    if (!addBlockHandlerAdded) {
        addBlockHandlerAdded = true;
        rpcService.addNewBtcBlockHandler(rawBlock -> {
            if (!isBlockAlreadyAdded(rawBlock)) {
                try {
                    Block block = blockParser.parseBlock(rawBlock);
                    onNewBlock(block);
                } catch (BlockNotConnectingException throwable) {
                    handleError(throwable);
                }
            }
        }, this::handleError);
    }
}
Also used : Block(bisq.core.dao.state.blockchain.Block) BlockNotConnectingException(bisq.core.dao.node.parser.exceptions.BlockNotConnectingException)

Example 3 with Block

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

the class BsqStateServiceTest method testIsBlockHashKnown.

@Test
public void testIsBlockHashKnown() {
    BsqStateService stateService = new BsqStateService(new BsqState(), new GenesisTxInfo("fakegenesistxid", 100));
    Assert.assertEquals("Unknown block should not exist.", false, stateService.isBlockHashKnown("fakeblockhash0"));
    Block block = new Block(0, 1534800000, "fakeblockhash0", null);
    stateService.onNewBlockWithEmptyTxs(block);
    Assert.assertEquals("Block that was added should exist.", true, stateService.isBlockHashKnown("fakeblockhash0"));
    Assert.assertEquals("Block that was never added should still not exist.", false, stateService.isBlockHashKnown("fakeblockhash1"));
    block = new Block(1, 1534800001, "fakeblockhash1", null);
    stateService.onNewBlockWithEmptyTxs(block);
    block = new Block(2, 1534800002, "fakeblockhash2", null);
    stateService.onNewBlockWithEmptyTxs(block);
    block = new Block(3, 1534800003, "fakeblockhash3", null);
    stateService.onNewBlockWithEmptyTxs(block);
    Assert.assertEquals("Block that was never added should still not exist after adding more blocks.", false, stateService.isBlockHashKnown("fakeblockhash4"));
    Assert.assertEquals("Block that was added along with more blocks should exist.", true, stateService.isBlockHashKnown("fakeblockhash3"));
}
Also used : Block(bisq.core.dao.state.blockchain.Block) Test(org.junit.Test)

Example 4 with Block

use of bisq.core.dao.state.blockchain.Block 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 5 with Block

use of bisq.core.dao.state.blockchain.Block 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

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