Add blockHeight text field to UI.

This commit is contained in:
Manfred Karrer 2017-04-17 15:34:26 -05:00
parent cfe814e4cd
commit 29e3ad0ee3
6 changed files with 62 additions and 45 deletions

View file

@ -956,7 +956,7 @@ dao.wallet.send.send=Send BSQ funds
dao.wallet.send.sendFunds.headline=Confirm withdrawal request
dao.wallet.send.sendFunds.details=Sending: {0}\nTo receiving address: {1}.\nRequired transaction fee is: {2} ({3} Satoshis/byte)\nTransaction size: {4} Kb\n\nThe recipient will receive: {5}\n\nAre you sure you want to withdraw that amount?
dao.wallet.bsqFee=BSQ fee payment
dao.wallet.chainHeight=Synced with blockchain height: {0} (chain tip height: {1})
####################################################################
# Windows

View file

@ -48,4 +48,8 @@ public class BsqBlockchainManager {
public boolean isParseBlockchainComplete() {
return bsqNode.isParseBlockchainComplete();
}
public void removeBsqChainStateListener(BsqChainStateListener bsqChainStateListener) {
bsqNode.removeBsqChainStateListener(bsqChainStateListener);
}
}

View file

@ -24,19 +24,18 @@ import io.bisq.common.util.Utilities;
import io.bisq.core.dao.blockchain.exceptions.BlockNotConnectingException;
import io.bisq.core.dao.blockchain.vo.*;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
// Represents mutable state of BSQ chain data
// We get accessed the data from non-UserThread context, so we need to handle threading here.
@Slf4j
@ToString
public class BsqChainState implements Persistable {
///////////////////////////////////////////////////////////////////////////////////////////
@ -54,7 +53,7 @@ public class BsqChainState implements Persistable {
// new snapshot is block 90. We only persist at the new snapshot, so we always re-parse from latest snapshot after
// a restart.
// As we only store snapshots when Txos are added it might be that there are bigger gaps than SNAPSHOT_TRIGGER.
private static final int SNAPSHOT_GRID = 10; // set high to deactivate
private static final int SNAPSHOT_GRID = 100; // set high to deactivate
///////////////////////////////////////////////////////////////////////////////////////////
@ -68,12 +67,14 @@ public class BsqChainState implements Persistable {
private final Map<TxIdIndexTuple, SpentInfo> spentInfoByTxOutputMap = new HashMap<>();
private final Map<String, Long> burnedFeeByTxIdMap = new HashMap<>();
private final AtomicReference<String> genesisTxId = new AtomicReference<>();
private final AtomicReference<Integer> chainHeadHeight = new AtomicReference<>(0);
private final AtomicReference<Integer> genesisBlockHeight = new AtomicReference<>(-1);
private final AtomicReference<Tx> genesisTx = new AtomicReference<>();
private final AtomicInteger chainHeadHeight = new AtomicInteger(0);
private final AtomicReference<Tx> genesisTx = new AtomicReference<>(null);
@Getter
private String genesisTxId = "";
@Getter
private int genesisBlockHeight = -1;
// transient
transient private BsqChainState snapshotCandidate;
transient private Storage<BsqChainState> snapshotBsqChainStateStorage;
@ -94,10 +95,10 @@ public class BsqChainState implements Persistable {
///////////////////////////////////////////////////////////////////////////////////////////
synchronized void init(Storage<BsqChainState> snapshotBsqChainStateStorage, String genesisTxId, int genesisBlockHeight) {
void init(Storage<BsqChainState> snapshotBsqChainStateStorage, String genesisTxId, int genesisBlockHeight) {
this.snapshotBsqChainStateStorage = snapshotBsqChainStateStorage;
this.genesisTxId.set(genesisTxId);
this.genesisBlockHeight.set(genesisBlockHeight);
this.genesisTxId = genesisTxId;
this.genesisBlockHeight = genesisBlockHeight;
}
void applySnapshot(@Nullable BsqChainState snapshot) {
@ -117,30 +118,23 @@ public class BsqChainState implements Persistable {
verifiedTxOutputSet.addAll(snapshot.verifiedTxOutputSet);
spentInfoByTxOutputMap.putAll(snapshot.spentInfoByTxOutputMap);
burnedFeeByTxIdMap.putAll(snapshot.burnedFeeByTxIdMap);
chainHeadHeight.set(snapshot.chainHeadHeight.get());
genesisTx.set(snapshot.genesisTx.get());
genesisTxId.set(snapshot.genesisTxId.get());
genesisBlockHeight.set(snapshot.genesisBlockHeight.get());
}
// printDetails();
}
}
synchronized void addBlock(BsqBlock block) throws BlockNotConnectingException {
if (!blocks.contains(block)) {
// TODO
// final int i = new Random().nextInt(1000);
if (blocks.isEmpty() || (/*i != 1 &&*/ blocks.getLast().getHash().equals(block.getPreviousBlockHash()) &&
if (blocks.isEmpty() || (blocks.getLast().getHash().equals(block.getPreviousBlockHash()) &&
block.getHeight() == blocks.getLast().getHeight() + 1)) {
blocks.add(block);
block.getTxs().stream().forEach(this::addTx);
chainHeadHeight.set(block.getHeight());
//printDetails();
maybeMakeSnapshot();
//printDetails();
} else if (!blocks.isEmpty()) {
log.warn("addBlock called with a not connecting block:\n" +
"height()={}, hash()={}, head.height()={}, head.hash()={}",
@ -193,6 +187,10 @@ public class BsqChainState implements Persistable {
return getTx(txId).isPresent();
}
public int getChainHeadHeight() {
return chainHeadHeight.get();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Protected
///////////////////////////////////////////////////////////////////////////////////////////
@ -209,10 +207,6 @@ public class BsqChainState implements Persistable {
}
}
int getChainHeadHeight() {
return chainHeadHeight.get();
}
boolean containsBlock(BsqBlock bsqBlock) {
return blocks.contains(bsqBlock);
}
@ -224,14 +218,6 @@ public class BsqChainState implements Persistable {
.collect(Collectors.toList());
}
int getGenesisBlockHeight() {
return genesisBlockHeight.get();
}
String getGenesisTxId() {
return genesisTxId.get();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
@ -296,7 +282,5 @@ public class BsqChainState implements Persistable {
private boolean isSnapshotHeight(int height) {
return isSnapshotHeight(getGenesisBlockHeight(), height, SNAPSHOT_GRID);
}
}

View file

@ -193,4 +193,8 @@ public abstract class BsqNode {
public void addBsqChainStateListener(BsqChainStateListener bsqChainStateListener) {
bsqChainStateListeners.add(bsqChainStateListener);
}
public void removeBsqChainStateListener(BsqChainStateListener bsqChainStateListener) {
bsqChainStateListeners.remove(bsqChainStateListener);
}
}

View file

@ -20,7 +20,6 @@ package io.bisq.core.dao.blockchain.json;
import com.google.inject.Inject;
import io.bisq.common.storage.PlainTextWrapper;
import io.bisq.common.storage.Storage;
import io.bisq.common.util.Utilities;
import io.bisq.core.dao.RpcOptionKeys;
import io.bisq.core.dao.blockchain.BsqChainState;
import io.bisq.core.dao.blockchain.btcd.PubKeyScript;
@ -62,7 +61,9 @@ public class JsonExporter {
//jsonStorage.queueUpForSave(new PlainTextWrapper(Utilities.objectToJson(array)), 5000);
jsonStorage.queueUpForSave(new PlainTextWrapper(Utilities.objectToJson(BsqChainState.getClone(bsqChainState))), 5000);
final BsqChainState clone = BsqChainState.getClone(bsqChainState);
// TODO use thread
// jsonStorage.queueUpForSave(new PlainTextWrapper(Utilities.objectToJson(clone)), 5000);
// keep the individual file storage option as code as we dont know yet what we will use.
/* log.error("txOutputForJson " + txOutputForJson);

View file

@ -23,6 +23,7 @@ import io.bisq.core.btc.wallet.BsqWalletService;
import io.bisq.core.btc.wallet.BtcWalletService;
import io.bisq.core.dao.blockchain.BsqBlockchainManager;
import io.bisq.core.dao.blockchain.BsqChainState;
import io.bisq.core.dao.blockchain.BsqChainStateListener;
import io.bisq.core.user.DontShowAgainLookup;
import io.bisq.core.user.Preferences;
import io.bisq.gui.common.view.ActivatableView;
@ -32,6 +33,7 @@ import io.bisq.gui.components.HyperlinkWithIcon;
import io.bisq.gui.main.dao.wallet.BsqBalanceUtil;
import io.bisq.gui.main.overlays.popups.Popup;
import io.bisq.gui.util.BsqFormatter;
import io.bisq.gui.util.FormBuilder;
import io.bisq.gui.util.GUIUtil;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
@ -45,6 +47,7 @@ import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import org.bitcoinj.core.Transaction;
@ -59,7 +62,7 @@ public class BsqTxView extends ActivatableView<GridPane, Void> {
TableView<BsqTxListItem> tableView;
private Pane rootParent;
private final BsqFormatter bsqFormatter;
private final BsqWalletService bsqWalletService;
private final BsqBlockchainManager bsqBlockchainManager;
@ -74,7 +77,9 @@ public class BsqTxView extends ActivatableView<GridPane, Void> {
private ChangeListener<Number> parentHeightListener;
private ListChangeListener<Transaction> walletBsqTransactionsListener;
private int gridRow = 0;
private Label chainHeightLabel;
private BsqChainStateListener bsqChainStateListener;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, lifecycle
@ -101,10 +106,6 @@ public class BsqTxView extends ActivatableView<GridPane, Void> {
tableView = new TableView<>();
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
GridPane.setRowIndex(tableView, ++gridRow);
GridPane.setColumnSpan(tableView, 2);
GridPane.setMargin(tableView, new Insets(40, -10, 5, -10));
root.getChildren().add(tableView);
addDateColumn();
addTxIdColumn();
@ -112,8 +113,21 @@ public class BsqTxView extends ActivatableView<GridPane, Void> {
addAmountColumn();
addConfidenceColumn();
chainHeightLabel = FormBuilder.addLabel(root, ++gridRow, "");
chainHeightLabel.setId("num-offers");
chainHeightLabel.setPadding(new Insets(-5, 0, -10, 5));
VBox vBox = new VBox();
vBox.setSpacing(10);
GridPane.setRowIndex(vBox, ++gridRow);
GridPane.setColumnSpan(vBox, 2);
GridPane.setMargin(vBox, new Insets(40, -10, 5, -10));
vBox.getChildren().addAll(tableView, chainHeightLabel);
root.getChildren().add(vBox);
walletBsqTransactionsListener = change -> updateList();
parentHeightListener = (observable, oldValue, newValue) -> layout();
bsqChainStateListener = this::onChainHeightChanged;
}
@Override
@ -124,12 +138,14 @@ public class BsqTxView extends ActivatableView<GridPane, Void> {
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
tableView.setItems(sortedList);
updateList();
bsqBlockchainManager.addBsqChainStateListener(bsqChainStateListener);
if (root.getParent() instanceof Pane) {
rootParent = (Pane) root.getParent();
rootParent.heightProperty().addListener(parentHeightListener);
}
updateList();
onChainHeightChanged();
layout();
}
@ -139,10 +155,18 @@ public class BsqTxView extends ActivatableView<GridPane, Void> {
sortedList.comparatorProperty().unbind();
bsqWalletService.getWalletTransactions().removeListener(walletBsqTransactionsListener);
observableList.forEach(BsqTxListItem::cleanup);
bsqBlockchainManager.removeBsqChainStateListener(bsqChainStateListener);
if (rootParent != null)
rootParent.heightProperty().removeListener(parentHeightListener);
}
private void onChainHeightChanged() {
chainHeightLabel.setText(Res.get("dao.wallet.chainHeight",
bsqChainState.getChainHeadHeight(),
bsqWalletService.getBestChainHeight()));
}
private void updateList() {
observableList.forEach(BsqTxListItem::cleanup);