private void invokeOnBlocksDownloaded(final Block block, @Nullable final FilteredBlock fb) { // It is possible for the peer block height difference to be negative when blocks have been solved and broadcast // since the time we first connected to the peer. However, it's weird and unexpected to receive a callback // with negative "blocks left" in this case, so we clamp to zero so the API user doesn't have to think about it. final int blocksLeft = Math.max(0, (int) vPeerVersionMessage.bestHeight - checkNotNull(blockChain).getBestChainHeight()); for (final ListenerRegistration<BlocksDownloadedEventListener> registration : blocksDownloadedEventListeners) { registration.executor.execute(new Runnable() { @Override public void run() { registration.listener.onBlocksDownloaded(Peer.this, block, fb, blocksLeft); } }); } }
private void invokeOnBlocksDownloaded(final Block block, @Nullable final FilteredBlock fb) { // It is possible for the peer block height difference to be negative when blocks have been solved and broadcast // since the time we first connected to the peer. However, it's weird and unexpected to receive a callback // with negative "blocks left" in this case, so we clamp to zero so the API user doesn't have to think about it. final int blocksLeft = Math.max(0, (int) vPeerVersionMessage.bestHeight - checkNotNull(blockChain).getBestChainHeight()); for (final ListenerRegistration<BlocksDownloadedEventListener> registration : blocksDownloadedEventListeners) { registration.executor.execute(new Runnable() { @Override public void run() { registration.listener.onBlocksDownloaded(Peer.this, block, fb, blocksLeft); } }); } }
private void invokeOnBlocksDownloaded(final Block block, @Nullable final FilteredBlock fb) { // It is possible for the peer block height difference to be negative when blocks have been solved and broadcast // since the time we first connected to the peer. However, it's weird and unexpected to receive a callback // with negative "blocks left" in this case, so we clamp to zero so the API user doesn't have to think about it. final int blocksLeft = Math.max(0, (int) vPeerVersionMessage.bestHeight - checkNotNull(blockChain).getBestChainHeight()); for (final ListenerRegistration<BlocksDownloadedEventListener> registration : blocksDownloadedEventListeners) { registration.executor.execute(new Runnable() { @Override public void run() { registration.listener.onBlocksDownloaded(Peer.this, block, fb, blocksLeft); } }); } }
private void invokeOnBlocksDownloaded(final Block block, @Nullable final FilteredBlock fb) { // It is possible for the peer block height difference to be negative when blocks have been solved and broadcast // since the time we first connected to the peer. However, it's weird and unexpected to receive a callback // with negative "blocks left" in this case, so we clamp to zero so the API user doesn't have to think about it. final int blocksLeft = Math.max(0, (int) vPeerVersionMessage.bestHeight - checkNotNull(blockChain).getBestChainHeight()); for (final ListenerRegistration<BlocksDownloadedEventListener> registration : blocksDownloadedEventListeners) { registration.executor.execute(new Runnable() { @Override public void run() { registration.listener.onBlocksDownloaded(Peer.this, block, fb, blocksLeft); } }); } }
/** * Returns the difference between our best chain height and the peers, which can either be positive if we are * behind the peer, or negative if the peer is ahead of us. */ public int getPeerBlockHeightDifference() { checkNotNull(blockChain, "No block chain configured"); // Chain will overflow signed int blocks in ~41,000 years. int chainHeight = (int) getBestHeight(); // chainHeight should not be zero/negative because we shouldn't have given the user a Peer that is to another // client-mode node, nor should it be unconnected. If that happens it means the user overrode us somewhere or // there is a bug in the peer management code. checkState(params.allowEmptyPeerChain() || chainHeight > 0, "Connected to peer with zero/negative chain height", chainHeight); return chainHeight - blockChain.getBestChainHeight(); }
/** * Returns the difference between our best chain height and the peers, which can either be positive if we are * behind the peer, or negative if the peer is ahead of us. */ public int getPeerBlockHeightDifference() { checkNotNull(blockChain, "No block chain configured"); // Chain will overflow signed int blocks in ~41,000 years. int chainHeight = (int) getBestHeight(); // chainHeight should not be zero/negative because we shouldn't have given the user a Peer that is to another // client-mode node, nor should it be unconnected. If that happens it means the user overrode us somewhere or // there is a bug in the peer management code. checkState(params.allowEmptyPeerChain() || chainHeight > 0, "Connected to peer with zero/negative chain height", chainHeight); return chainHeight - blockChain.getBestChainHeight(); }
/** * Returns the difference between our best chain height and the peers, which can either be positive if we are * behind the peer, or negative if the peer is ahead of us. */ public int getPeerBlockHeightDifference() { checkNotNull(blockChain, "No block chain configured"); // Chain will overflow signed int blocks in ~41,000 years. int chainHeight = (int) getBestHeight(); // chainHeight should not be zero/negative because we shouldn't have given the user a Peer that is to another // client-mode node, nor should it be unconnected. If that happens it means the user overrode us somewhere or // there is a bug in the peer management code. checkState(params.allowEmptyPeerChain() || chainHeight > 0, "Connected to peer with zero/negative chain height", chainHeight); return chainHeight - blockChain.getBestChainHeight(); }
/** * Returns the difference between our best chain height and the peers, which can either be positive if we are * behind the peer, or negative if the peer is ahead of us. */ public int getPeerBlockHeightDifference() { checkNotNull(blockChain, "No block chain configured"); // Chain will overflow signed int blocks in ~41,000 years. int chainHeight = (int) getBestHeight(); // chainHeight should not be zero/negative because we shouldn't have given the user a Peer that is to another // client-mode node, nor should it be unconnected. If that happens it means the user overrode us somewhere or // there is a bug in the peer management code. checkState(params.allowEmptyPeerChain() || chainHeight > 0, "Connected to peer with zero/negative chain height", chainHeight); return chainHeight - blockChain.getBestChainHeight(); }
/** * <p>Construct a peer that reads/writes from the given chain. Automatically creates a VersionMessage for you from * the given software name/version strings, which should be something like "MySimpleTool", "1.0" and which will tell * the remote node to relay transaction inv messages before it has received a filter.</p> * * <p>Note that this does <b>NOT</b> make a connection to the given remoteAddress, it only creates a handler for a * connection. If you want to create a one-off connection, create a Peer and pass it to * {@link org.bitcoinj.net.NioClientManager#openConnection(java.net.SocketAddress, StreamConnection)} * or * {@link org.bitcoinj.net.NioClient#NioClient(java.net.SocketAddress, StreamConnection, int)}.</p> * * <p>The remoteAddress provided should match the remote address of the peer which is being connected to, and is * used to keep track of which peers relayed transactions and offer more descriptive logging.</p> */ public Peer(NetworkParameters params, AbstractBlockChain blockChain, PeerAddress peerAddress, String thisSoftwareName, String thisSoftwareVersion) { this(params, new VersionMessage(params, blockChain.getBestChainHeight()), blockChain, peerAddress); this.versionMessage.appendToSubVer(thisSoftwareName, thisSoftwareVersion, null); }
/** * <p>Construct a peer that reads/writes from the given chain. Automatically creates a VersionMessage for you from * the given software name/version strings, which should be something like "MySimpleTool", "1.0" and which will tell * the remote node to relay transaction inv messages before it has received a filter.</p> * * <p>Note that this does <b>NOT</b> make a connection to the given remoteAddress, it only creates a handler for a * connection. If you want to create a one-off connection, create a Peer and pass it to * {@link org.bitcoinj.net.NioClientManager#openConnection(java.net.SocketAddress, StreamConnection)} * or * {@link org.bitcoinj.net.NioClient#NioClient(java.net.SocketAddress, StreamConnection, int)}.</p> * * <p>The remoteAddress provided should match the remote address of the peer which is being connected to, and is * used to keep track of which peers relayed transactions and offer more descriptive logging.</p> */ public Peer(NetworkParameters params, AbstractBlockChain blockChain, PeerAddress peerAddress, String thisSoftwareName, String thisSoftwareVersion) { this(params, new VersionMessage(params, blockChain.getBestChainHeight()), blockChain, peerAddress); this.versionMessage.appendToSubVer(thisSoftwareName, thisSoftwareVersion, null); }
/** * <p>Construct a peer that reads/writes from the given chain. Automatically creates a VersionMessage for you from * the given software name/version strings, which should be something like "MySimpleTool", "1.0" and which will tell * the remote node to relay transaction inv messages before it has received a filter.</p> * * <p>Note that this does <b>NOT</b> make a connection to the given remoteAddress, it only creates a handler for a * connection. If you want to create a one-off connection, create a Peer and pass it to * {@link org.bitcoinj.net.NioClientManager#openConnection(java.net.SocketAddress, StreamConnection)} * or * {@link org.bitcoinj.net.NioClient#NioClient(java.net.SocketAddress, StreamConnection, int)}.</p> * * <p>The remoteAddress provided should match the remote address of the peer which is being connected to, and is * used to keep track of which peers relayed transactions and offer more descriptive logging.</p> */ public Peer(NetworkParameters params, AbstractBlockChain blockChain, PeerAddress peerAddress, String thisSoftwareName, String thisSoftwareVersion) { this(params, new VersionMessage(params, blockChain.getBestChainHeight()), blockChain, peerAddress); this.versionMessage.appendToSubVer(thisSoftwareName, thisSoftwareVersion, null); }
/** * <p>Construct a peer that reads/writes from the given chain. Automatically creates a VersionMessage for you from * the given software name/version strings, which should be something like "MySimpleTool", "1.0" and which will tell * the remote node to relay transaction inv messages before it has received a filter.</p> * * <p>Note that this does <b>NOT</b> make a connection to the given remoteAddress, it only creates a handler for a * connection. If you want to create a one-off connection, create a Peer and pass it to * {@link org.bitcoinj.net.NioClientManager#openConnection(java.net.SocketAddress, StreamConnection)} * or * {@link org.bitcoinj.net.NioClient#NioClient(java.net.SocketAddress, StreamConnection, int)}.</p> * * <p>The remoteAddress provided should match the remote address of the peer which is being connected to, and is * used to keep track of which peers relayed transactions and offer more descriptive logging.</p> */ public Peer(NetworkParameters params, AbstractBlockChain blockChain, PeerAddress peerAddress, String thisSoftwareName, String thisSoftwareVersion) { this(params, new VersionMessage(params, blockChain.getBestChainHeight()), blockChain, peerAddress); this.versionMessage.appendToSubVer(thisSoftwareName, thisSoftwareVersion, null); }
void processSpork(Peer from, SporkMessage spork) { if (context.isLiteMode() && !context.allowInstantXinLiteMode()) return; //disable all darksend/masternode related functionality Sha256Hash hash = spork.getHash(); if (mapSporksActive.containsKey(spork.nSporkID)) { if (mapSporksActive.get(spork.nSporkID).nTimeSigned >= spork.nTimeSigned) { log.info("spork - seen "+hash.toString()+" block " + blockChain.getBestChainHeight()); return; } else { log.info("spork - got updated spork "+hash.toString()+" block " +blockChain.getBestChainHeight()); } } log.info("spork - new "+hash.toString()+" ID "+spork.nSporkID+" Time "+spork.nTimeSigned+" bestHeight" + blockChain.getBestChainHeight()); if (!spork.checkSignature(sporkPubKeyId)) { log.info("spork - invalid signature"); //Misbehaving(pfrom -> GetId(), 100); return; } mapSporks.put(hash, spork); mapSporksActive.put(spork.nSporkID, spork); relay(spork); //does a task if needed executeSpork(spork.nSporkID, spork.nValue); } /*
/** * Sets information that identifies this software to remote nodes. This is a convenience wrapper for creating * a new {@link VersionMessage}, calling {@link VersionMessage#appendToSubVer(String, String, String)} on it, * and then calling {@link PeerGroup#setVersionMessage(VersionMessage)} on the result of that. See the docs for * {@link VersionMessage#appendToSubVer(String, String, String)} for information on what the fields should contain. */ public void setUserAgent(String name, String version, @Nullable String comments) { //TODO Check that height is needed here (it wasnt, but it should be, no?) int height = chain == null ? 0 : chain.getBestChainHeight(); VersionMessage ver = new VersionMessage(params, height); ver.relayTxesBeforeFilter = false; updateVersionMessageRelayTxesBeforeFilter(ver); ver.appendToSubVer(name, version, comments); setVersionMessage(ver); }
/** * Sets information that identifies this software to remote nodes. This is a convenience wrapper for creating * a new {@link VersionMessage}, calling {@link VersionMessage#appendToSubVer(String, String, String)} on it, * and then calling {@link PeerGroup#setVersionMessage(VersionMessage)} on the result of that. See the docs for * {@link VersionMessage#appendToSubVer(String, String, String)} for information on what the fields should contain. */ public void setUserAgent(String name, String version, @Nullable String comments) { //TODO Check that height is needed here (it wasnt, but it should be, no?) int height = chain == null ? 0 : chain.getBestChainHeight(); VersionMessage ver = new VersionMessage(params, height); ver.relayTxesBeforeFilter = false; updateVersionMessageRelayTxesBeforeFilter(ver); ver.appendToSubVer(name, version, comments); setVersionMessage(ver); }
/** * Sets information that identifies this software to remote nodes. This is a convenience wrapper for creating * a new {@link VersionMessage}, calling {@link VersionMessage#appendToSubVer(String, String, String)} on it, * and then calling {@link PeerGroup#setVersionMessage(VersionMessage)} on the result of that. See the docs for * {@link VersionMessage#appendToSubVer(String, String, String)} for information on what the fields should contain. */ public void setUserAgent(String name, String version, @Nullable String comments) { //TODO Check that height is needed here (it wasnt, but it should be, no?) int height = chain == null ? 0 : chain.getBestChainHeight(); VersionMessage ver = new VersionMessage(params, height); ver.relayTxesBeforeFilter = false; updateVersionMessageRelayTxesBeforeFilter(ver); ver.appendToSubVer(name, version, comments); setVersionMessage(ver); }
/** * Sets information that identifies this software to remote nodes. This is a convenience wrapper for creating * a new {@link VersionMessage}, calling {@link VersionMessage#appendToSubVer(String, String, String)} on it, * and then calling {@link PeerGroup#setVersionMessage(VersionMessage)} on the result of that. See the docs for * {@link VersionMessage#appendToSubVer(String, String, String)} for information on what the fields should contain. */ public void setUserAgent(String name, String version, @Nullable String comments) { //TODO Check that height is needed here (it wasnt, but it should be, no?) int height = chain == null ? 0 : chain.getBestChainHeight(); VersionMessage ver = new VersionMessage(params, height); ver.relayTxesBeforeFilter = false; updateVersionMessageRelayTxesBeforeFilter(ver); ver.appendToSubVer(name, version, comments); setVersionMessage(ver); }
/** * Add a wallet to the BlockChain. Note that the wallet will be unaffected by any blocks received while it * was not part of this BlockChain. This method is useful if the wallet has just been created, and its keys * have never been in use, or if the wallet has been loaded along with the BlockChain. Note that adding multiple * wallets is not well tested! */ public final void addWallet(Wallet wallet) { addNewBestBlockListener(Threading.SAME_THREAD, wallet); addReorganizeListener(Threading.SAME_THREAD, wallet); addTransactionReceivedListener(Threading.SAME_THREAD, wallet); int walletHeight = wallet.getLastBlockSeenHeight(); int chainHeight = getBestChainHeight(); if (walletHeight != chainHeight) { log.warn("Wallet/chain height mismatch: {} vs {}", walletHeight, chainHeight); log.warn("Hashes: {} vs {}", wallet.getLastBlockSeenHash(), getChainHead().getHeader().getHash()); // This special case happens when the VM crashes because of a transaction received. It causes the updated // block store to persist, but not the wallet. In order to fix the issue, we roll back the block store to // the wallet height to make it look like as if the block has never been received. if (walletHeight < chainHeight && walletHeight > 0) { try { rollbackBlockStore(walletHeight); log.info("Rolled back block store to height {}.", walletHeight); } catch (BlockStoreException x) { log.warn("Rollback of block store failed, continuing with mismatched heights. This can happen due to a replay."); } } } }
/** * Add a wallet to the BlockChain. Note that the wallet will be unaffected by any blocks received while it * was not part of this BlockChain. This method is useful if the wallet has just been created, and its keys * have never been in use, or if the wallet has been loaded along with the BlockChain. Note that adding multiple * wallets is not well tested! */ public final void addWallet(Wallet wallet) { addNewBestBlockListener(Threading.SAME_THREAD, wallet); addReorganizeListener(Threading.SAME_THREAD, wallet); addTransactionReceivedListener(Threading.SAME_THREAD, wallet); int walletHeight = wallet.getLastBlockSeenHeight(); int chainHeight = getBestChainHeight(); if (walletHeight != chainHeight) { log.warn("Wallet/chain height mismatch: {} vs {}", walletHeight, chainHeight); log.warn("Hashes: {} vs {}", wallet.getLastBlockSeenHash(), getChainHead().getHeader().getHash()); // This special case happens when the VM crashes because of a transaction received. It causes the updated // block store to persist, but not the wallet. In order to fix the issue, we roll back the block store to // the wallet height to make it look like as if the block has never been received. if (walletHeight < chainHeight && walletHeight > 0) { try { rollbackBlockStore(walletHeight); log.info("Rolled back block store to height {}.", walletHeight); } catch (BlockStoreException x) { log.warn("Rollback of block store failed, continuing with mismatched heights. This can happen due to a replay."); } } } }
public void setPeerGroupAndBlockChain(PeerGroup peerGroup, AbstractBlockChain chain) { this.peerGroup = peerGroup; this.blockChain = chain; hashStore = new HashStore(chain.getBlockStore()); chain.addListener(updateHeadListener); if(initializedDash) { sporkManager.setBlockChain(chain); masternodeManager.setBlockChain(chain); masternodeSync.setBlockChain(chain); instantSend.setBlockChain(chain); } params.setDIPActiveAtTip(chain.getBestChainHeight() >= params.getDIP0001BlockHeight()); }