mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +01:00
Merge pull request #6504 from HenrikJannsen/add_check_for_isInConflictWithSeedNode
Add check for dao state hash conflict with seed node
This commit is contained in:
commit
dda32c09ff
14 changed files with 149 additions and 93 deletions
|
@ -291,7 +291,8 @@ public abstract class WalletService {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!connectedOutput.isMine(wallet)) {
|
if (!connectedOutput.isMine(wallet)) {
|
||||||
log.error("connectedOutput is not mine");
|
log.info("ConnectedOutput is not mine. This can be the case for BSQ transactions where the " +
|
||||||
|
"input gets signed by the other wallet. connectedOutput={}", connectedOutput);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,6 @@ import bisq.core.dao.monitoring.DaoStateMonitoringService;
|
||||||
import bisq.core.dao.state.DaoStateListener;
|
import bisq.core.dao.state.DaoStateListener;
|
||||||
import bisq.core.dao.state.DaoStateService;
|
import bisq.core.dao.state.DaoStateService;
|
||||||
import bisq.core.dao.state.model.blockchain.BaseTx;
|
import bisq.core.dao.state.model.blockchain.BaseTx;
|
||||||
import bisq.core.dao.state.model.blockchain.BaseTxOutput;
|
|
||||||
import bisq.core.dao.state.model.blockchain.Block;
|
import bisq.core.dao.state.model.blockchain.Block;
|
||||||
import bisq.core.dao.state.model.blockchain.Tx;
|
import bisq.core.dao.state.model.blockchain.Tx;
|
||||||
import bisq.core.dao.state.model.blockchain.TxOutput;
|
import bisq.core.dao.state.model.blockchain.TxOutput;
|
||||||
|
@ -531,10 +530,13 @@ public class DaoFacade implements DaoSetupService {
|
||||||
return daoStateService.getBlockAtHeight(chainHeight);
|
return daoStateService.getBlockAtHeight(chainHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean daoStateNeedsRebuilding() {
|
public boolean isDaoStateReadyAndInSync() {
|
||||||
return daoStateMonitoringService.isInConflictWithSeedNode() || daoStateMonitoringService.isDaoStateBlockChainNotConnecting();
|
return daoStateService.isParseBlockChainComplete() &&
|
||||||
|
!daoStateMonitoringService.isInConflictWithSeedNode() &&
|
||||||
|
!daoStateMonitoringService.isDaoStateBlockChainNotConnecting();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Use case: Bonding
|
// Use case: Bonding
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -578,10 +580,6 @@ public class DaoFacade implements DaoSetupService {
|
||||||
return daoStateService.getTotalAmountOfConfiscatedTxOutputs();
|
return daoStateService.getTotalAmountOfConfiscatedTxOutputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTotalAmountOfInvalidatedBsq() {
|
|
||||||
return daoStateService.getTotalAmountOfInvalidatedBsq();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains burned fee and invalidated bsq due invalid txs
|
// Contains burned fee and invalidated bsq due invalid txs
|
||||||
public long getTotalAmountOfBurntBsq() {
|
public long getTotalAmountOfBurntBsq() {
|
||||||
return daoStateService.getTotalAmountOfBurntBsq();
|
return daoStateService.getTotalAmountOfBurntBsq();
|
||||||
|
@ -595,11 +593,6 @@ public class DaoFacade implements DaoSetupService {
|
||||||
return daoStateService.getIrregularTxs();
|
return daoStateService.getIrregularTxs();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTotalAmountOfUnspentTxOutputs() {
|
|
||||||
// Does not consider confiscated outputs (they stay as utxo)
|
|
||||||
return daoStateService.getUnspentTxOutputMap().values().stream().mapToLong(BaseTxOutput::getValue).sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Integer> getLockTime(String txId) {
|
public Optional<Integer> getLockTime(String txId) {
|
||||||
return daoStateService.getLockTime(txId);
|
return daoStateService.getLockTime(txId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,6 @@ public class DelayedPayoutTxReceiverService implements DaoStateListener {
|
||||||
// spike when opening arbitration.
|
// spike when opening arbitration.
|
||||||
private static final long DPT_MIN_TX_FEE_RATE = 10;
|
private static final long DPT_MIN_TX_FEE_RATE = 10;
|
||||||
|
|
||||||
|
|
||||||
private final DaoStateService daoStateService;
|
private final DaoStateService daoStateService;
|
||||||
private final BurningManService burningManService;
|
private final BurningManService burningManService;
|
||||||
private int currentChainHeight;
|
private int currentChainHeight;
|
||||||
|
@ -127,12 +126,6 @@ public class DelayedPayoutTxReceiverService implements DaoStateListener {
|
||||||
burningManService.getActiveBurningManCandidates(burningManSelectionHeight) :
|
burningManService.getActiveBurningManCandidates(burningManSelectionHeight) :
|
||||||
burningManService.getBurningManCandidatesByName(burningManSelectionHeight).values();
|
burningManService.getBurningManCandidatesByName(burningManSelectionHeight).values();
|
||||||
|
|
||||||
|
|
||||||
if (burningManCandidates.isEmpty()) {
|
|
||||||
// If there are no compensation requests (e.g. at dev testing) we fall back to the legacy BM
|
|
||||||
return List.of(new Tuple2<>(inputAmount, burningManService.getLegacyBurningManAddress(burningManSelectionHeight)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to use the same txFeePerVbyte value for both traders.
|
// We need to use the same txFeePerVbyte value for both traders.
|
||||||
// We use the tradeTxFee value which is calculated from the average of taker fee tx size and deposit tx size.
|
// We use the tradeTxFee value which is calculated from the average of taker fee tx size and deposit tx size.
|
||||||
// Otherwise, we would need to sync the fee rate of both traders.
|
// Otherwise, we would need to sync the fee rate of both traders.
|
||||||
|
@ -146,12 +139,19 @@ public class DelayedPayoutTxReceiverService implements DaoStateListener {
|
||||||
// Smallest tx size is 246. With additional change output we add 32. To be safe we use the largest expected size.
|
// Smallest tx size is 246. With additional change output we add 32. To be safe we use the largest expected size.
|
||||||
double txSize = 278;
|
double txSize = 278;
|
||||||
long txFeePerVbyte = Math.max(DPT_MIN_TX_FEE_RATE, Math.round(tradeTxFee / txSize));
|
long txFeePerVbyte = Math.max(DPT_MIN_TX_FEE_RATE, Math.round(tradeTxFee / txSize));
|
||||||
|
|
||||||
|
if (burningManCandidates.isEmpty()) {
|
||||||
|
// If there are no compensation requests (e.g. at dev testing) we fall back to the legacy BM
|
||||||
|
long spendableAmount = getSpendableAmount(1, inputAmount, txFeePerVbyte);
|
||||||
|
return List.of(new Tuple2<>(spendableAmount, burningManService.getLegacyBurningManAddress(burningManSelectionHeight)));
|
||||||
|
}
|
||||||
|
|
||||||
long spendableAmount = getSpendableAmount(burningManCandidates.size(), inputAmount, txFeePerVbyte);
|
long spendableAmount = getSpendableAmount(burningManCandidates.size(), inputAmount, txFeePerVbyte);
|
||||||
// We only use outputs > 1000 sat or at least 2 times the cost for the output (32 bytes).
|
// We only use outputs > 1000 sat or at least 2 times the cost for the output (32 bytes).
|
||||||
// If we remove outputs it will be spent as miner fee.
|
// If we remove outputs it will be spent as miner fee.
|
||||||
long minOutputAmount = Math.max(DPT_MIN_OUTPUT_AMOUNT, txFeePerVbyte * 32 * 2);
|
long minOutputAmount = Math.max(DPT_MIN_OUTPUT_AMOUNT, txFeePerVbyte * 32 * 2);
|
||||||
// Sanity check that max share of a non-legacy BM is 20% over MAX_BURN_SHARE (taking into account potential increase due adjustment)
|
// Sanity check that max share of a non-legacy BM is 20% over MAX_BURN_SHARE (taking into account potential increase due adjustment)
|
||||||
long maxOutputAmount = Math.round(inputAmount * (BurningManService.MAX_BURN_SHARE * 1.2));
|
long maxOutputAmount = Math.round(spendableAmount * (BurningManService.MAX_BURN_SHARE * 1.2));
|
||||||
// We accumulate small amounts which gets filtered out and subtract it from 1 to get an adjustment factor
|
// We accumulate small amounts which gets filtered out and subtract it from 1 to get an adjustment factor
|
||||||
// used later to be applied to the remaining burningmen share.
|
// used later to be applied to the remaining burningmen share.
|
||||||
double adjustment = 1 - burningManCandidates.stream()
|
double adjustment = 1 - burningManCandidates.stream()
|
||||||
|
|
|
@ -206,7 +206,7 @@ public class FullNodeNetworkService implements MessageListener, PeerManager.List
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRepublishGovernanceDataRequest() {
|
private void handleRepublishGovernanceDataRequest() {
|
||||||
log.warn("We received a RepublishGovernanceDataRequest and re-published all proposalPayloads and " +
|
log.info("We received a RepublishGovernanceDataRequest and re-published all proposalPayloads and " +
|
||||||
"blindVotePayloads to the P2P network.");
|
"blindVotePayloads to the P2P network.");
|
||||||
missingDataRequestService.reRepublishAllGovernanceData();
|
missingDataRequestService.reRepublishAllGovernanceData();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import bisq.core.trade.protocol.bisq_v1.messages.DepositTxAndDelayedPayoutTxMess
|
||||||
import bisq.core.trade.protocol.bisq_v1.messages.InputsForDepositTxRequest;
|
import bisq.core.trade.protocol.bisq_v1.messages.InputsForDepositTxRequest;
|
||||||
import bisq.core.trade.protocol.bisq_v1.messages.PayoutTxPublishedMessage;
|
import bisq.core.trade.protocol.bisq_v1.messages.PayoutTxPublishedMessage;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.bisq_v1.tasks.ApplyFilter;
|
||||||
|
import bisq.core.trade.protocol.bisq_v1.tasks.CheckIfDaoStateIsInSync;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
|
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
|
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
|
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
|
||||||
|
@ -71,6 +72,7 @@ public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol
|
||||||
.with(message)
|
.with(message)
|
||||||
.from(peer))
|
.from(peer))
|
||||||
.setup(tasks(
|
.setup(tasks(
|
||||||
|
CheckIfDaoStateIsInSync.class,
|
||||||
MakerProcessesInputsForDepositTxRequest.class,
|
MakerProcessesInputsForDepositTxRequest.class,
|
||||||
ApplyFilter.class,
|
ApplyFilter.class,
|
||||||
getVerifyPeersFeePaymentClass(),
|
getVerifyPeersFeePaymentClass(),
|
||||||
|
|
|
@ -27,6 +27,7 @@ import bisq.core.trade.protocol.bisq_v1.messages.DepositTxAndDelayedPayoutTxMess
|
||||||
import bisq.core.trade.protocol.bisq_v1.messages.InputsForDepositTxResponse;
|
import bisq.core.trade.protocol.bisq_v1.messages.InputsForDepositTxResponse;
|
||||||
import bisq.core.trade.protocol.bisq_v1.messages.PayoutTxPublishedMessage;
|
import bisq.core.trade.protocol.bisq_v1.messages.PayoutTxPublishedMessage;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.bisq_v1.tasks.ApplyFilter;
|
||||||
|
import bisq.core.trade.protocol.bisq_v1.tasks.CheckIfDaoStateIsInSync;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
|
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
|
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerFinalizesDelayedPayoutTx;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
|
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
|
||||||
|
@ -77,6 +78,7 @@ public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol
|
||||||
expect(phase(Trade.Phase.INIT)
|
expect(phase(Trade.Phase.INIT)
|
||||||
.with(TakerEvent.TAKE_OFFER))
|
.with(TakerEvent.TAKE_OFFER))
|
||||||
.setup(tasks(
|
.setup(tasks(
|
||||||
|
CheckIfDaoStateIsInSync.class,
|
||||||
ApplyFilter.class,
|
ApplyFilter.class,
|
||||||
getVerifyPeersFeePaymentClass(),
|
getVerifyPeersFeePaymentClass(),
|
||||||
CreateTakerFeeTx.class,
|
CreateTakerFeeTx.class,
|
||||||
|
|
|
@ -27,6 +27,7 @@ import bisq.core.trade.protocol.bisq_v1.messages.DelayedPayoutTxSignatureRespons
|
||||||
import bisq.core.trade.protocol.bisq_v1.messages.DepositTxMessage;
|
import bisq.core.trade.protocol.bisq_v1.messages.DepositTxMessage;
|
||||||
import bisq.core.trade.protocol.bisq_v1.messages.InputsForDepositTxRequest;
|
import bisq.core.trade.protocol.bisq_v1.messages.InputsForDepositTxRequest;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.bisq_v1.tasks.ApplyFilter;
|
||||||
|
import bisq.core.trade.protocol.bisq_v1.tasks.CheckIfDaoStateIsInSync;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
|
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.maker.MakerCreateAndSignContract;
|
import bisq.core.trade.protocol.bisq_v1.tasks.maker.MakerCreateAndSignContract;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.maker.MakerProcessesInputsForDepositTxRequest;
|
import bisq.core.trade.protocol.bisq_v1.tasks.maker.MakerProcessesInputsForDepositTxRequest;
|
||||||
|
@ -73,6 +74,7 @@ public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtoc
|
||||||
.with(message)
|
.with(message)
|
||||||
.from(peer))
|
.from(peer))
|
||||||
.setup(tasks(
|
.setup(tasks(
|
||||||
|
CheckIfDaoStateIsInSync.class,
|
||||||
MaybeCreateSubAccount.class,
|
MaybeCreateSubAccount.class,
|
||||||
MakerProcessesInputsForDepositTxRequest.class,
|
MakerProcessesInputsForDepositTxRequest.class,
|
||||||
ApplyFilter.class,
|
ApplyFilter.class,
|
||||||
|
|
|
@ -26,6 +26,7 @@ import bisq.core.trade.protocol.bisq_v1.messages.CounterCurrencyTransferStartedM
|
||||||
import bisq.core.trade.protocol.bisq_v1.messages.DelayedPayoutTxSignatureResponse;
|
import bisq.core.trade.protocol.bisq_v1.messages.DelayedPayoutTxSignatureResponse;
|
||||||
import bisq.core.trade.protocol.bisq_v1.messages.InputsForDepositTxResponse;
|
import bisq.core.trade.protocol.bisq_v1.messages.InputsForDepositTxResponse;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.ApplyFilter;
|
import bisq.core.trade.protocol.bisq_v1.tasks.ApplyFilter;
|
||||||
|
import bisq.core.trade.protocol.bisq_v1.tasks.CheckIfDaoStateIsInSync;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
|
import bisq.core.trade.protocol.bisq_v1.tasks.TradeTask;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.seller.MaybeCreateSubAccount;
|
import bisq.core.trade.protocol.bisq_v1.tasks.seller.MaybeCreateSubAccount;
|
||||||
import bisq.core.trade.protocol.bisq_v1.tasks.seller.SellerCreatesDelayedPayoutTx;
|
import bisq.core.trade.protocol.bisq_v1.tasks.seller.SellerCreatesDelayedPayoutTx;
|
||||||
|
@ -73,6 +74,7 @@ public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtoc
|
||||||
.with(TakerEvent.TAKE_OFFER)
|
.with(TakerEvent.TAKE_OFFER)
|
||||||
.from(trade.getTradingPeerNodeAddress()))
|
.from(trade.getTradingPeerNodeAddress()))
|
||||||
.setup(tasks(
|
.setup(tasks(
|
||||||
|
CheckIfDaoStateIsInSync.class,
|
||||||
MaybeCreateSubAccount.class,
|
MaybeCreateSubAccount.class,
|
||||||
ApplyFilter.class,
|
ApplyFilter.class,
|
||||||
getVerifyPeersFeePaymentClass(),
|
getVerifyPeersFeePaymentClass(),
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Bisq.
|
||||||
|
*
|
||||||
|
* Bisq is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package bisq.core.trade.protocol.bisq_v1.tasks;
|
||||||
|
|
||||||
|
import bisq.core.trade.model.bisq_v1.Trade;
|
||||||
|
|
||||||
|
import bisq.common.taskrunner.TaskRunner;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class CheckIfDaoStateIsInSync extends TradeTask {
|
||||||
|
public CheckIfDaoStateIsInSync(TaskRunner<Trade> taskHandler, Trade trade) {
|
||||||
|
super(taskHandler, trade);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void run() {
|
||||||
|
try {
|
||||||
|
runInterceptHook();
|
||||||
|
|
||||||
|
checkArgument(processModel.getDaoFacade().isDaoStateReadyAndInSync(), "DAO state is not in sync with seed nodes");
|
||||||
|
complete();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
failed(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ import java.util.List;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -74,8 +73,19 @@ public class BuyerVerifiesFinalDelayedPayoutTx extends TradeTask {
|
||||||
depositTx,
|
depositTx,
|
||||||
delayedPayoutTxReceivers,
|
delayedPayoutTxReceivers,
|
||||||
lockTime);
|
lockTime);
|
||||||
checkArgument(buyersDelayedPayoutTx.getTxId().equals(finalDelayedPayoutTx.getTxId()),
|
|
||||||
"TxIds of buyersDelayedPayoutTx and finalDelayedPayoutTx must be the same");
|
if (!buyersDelayedPayoutTx.getTxId().equals(finalDelayedPayoutTx.getTxId())) {
|
||||||
|
String errorMsg = "TxIds of buyersDelayedPayoutTx and finalDelayedPayoutTx must be the same.";
|
||||||
|
log.error("{} \nbuyersDelayedPayoutTx={}, \nfinalDelayedPayoutTx={}, " +
|
||||||
|
"\nBtcWalletService.chainHeight={}, " +
|
||||||
|
"\nDaoState.chainHeight={}, " +
|
||||||
|
"\nisDaoStateIsInSync={}",
|
||||||
|
errorMsg, buyersDelayedPayoutTx, finalDelayedPayoutTx,
|
||||||
|
processModel.getBtcWalletService().getBestChainHeight(),
|
||||||
|
processModel.getDaoFacade().getChainHeight(),
|
||||||
|
processModel.getDaoFacade().isDaoStateReadyAndInSync());
|
||||||
|
throw new IllegalArgumentException(errorMsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
complete();
|
complete();
|
||||||
|
|
|
@ -32,7 +32,6 @@ import java.util.List;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -66,8 +65,18 @@ public class BuyerVerifiesPreparedDelayedPayoutTx extends TradeTask {
|
||||||
preparedDepositTx,
|
preparedDepositTx,
|
||||||
delayedPayoutTxReceivers,
|
delayedPayoutTxReceivers,
|
||||||
lockTime);
|
lockTime);
|
||||||
checkArgument(buyersPreparedDelayedPayoutTx.getTxId().equals(sellersPreparedDelayedPayoutTx.getTxId()),
|
if (!buyersPreparedDelayedPayoutTx.getTxId().equals(sellersPreparedDelayedPayoutTx.getTxId())) {
|
||||||
"TxIds of buyersPreparedDelayedPayoutTx and sellersPreparedDelayedPayoutTx must be the same");
|
String errorMsg = "TxIds of buyersPreparedDelayedPayoutTx and sellersPreparedDelayedPayoutTx must be the same.";
|
||||||
|
log.error("{} \nbuyersPreparedDelayedPayoutTx={}, \nsellersPreparedDelayedPayoutTx={}, " +
|
||||||
|
"\nBtcWalletService.chainHeight={}, " +
|
||||||
|
"\nDaoState.chainHeight={}, " +
|
||||||
|
"\nisDaoStateIsInSync={}",
|
||||||
|
errorMsg, buyersPreparedDelayedPayoutTx, sellersPreparedDelayedPayoutTx,
|
||||||
|
processModel.getBtcWalletService().getBestChainHeight(),
|
||||||
|
processModel.getDaoFacade().getChainHeight(),
|
||||||
|
processModel.getDaoFacade().isDaoStateReadyAndInSync());
|
||||||
|
throw new IllegalArgumentException(errorMsg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the deposit tx is non-malleable, we already know its final ID, so should check that now
|
// If the deposit tx is non-malleable, we already know its final ID, so should check that now
|
||||||
|
|
|
@ -310,7 +310,7 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
|
||||||
setupClockWatcherPopup();
|
setupClockWatcherPopup();
|
||||||
|
|
||||||
marketPricePresentation.setup();
|
marketPricePresentation.setup();
|
||||||
daoPresentation.setup();
|
daoPresentation.init();
|
||||||
accountPresentation.setup();
|
accountPresentation.setup();
|
||||||
settingsPresentation.setup();
|
settingsPresentation.setup();
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
|
||||||
.show());
|
.show());
|
||||||
|
|
||||||
bisqSetup.getBtcSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress());
|
bisqSetup.getBtcSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress());
|
||||||
daoPresentation.getBsqSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress());
|
daoPresentation.getDaoStateSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress());
|
||||||
|
|
||||||
bisqSetup.setFilterWarningHandler(warning -> new Popup().warning(warning).show());
|
bisqSetup.setFilterWarningHandler(warning -> new Popup().warning(warning).show());
|
||||||
|
|
||||||
|
@ -704,7 +704,7 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
|
||||||
if (btcSyncProgress.doubleValue() < 1) {
|
if (btcSyncProgress.doubleValue() < 1) {
|
||||||
combinedSyncProgress.set(btcSyncProgress.doubleValue());
|
combinedSyncProgress.set(btcSyncProgress.doubleValue());
|
||||||
} else {
|
} else {
|
||||||
combinedSyncProgress.set(daoPresentation.getBsqSyncProgress().doubleValue());
|
combinedSyncProgress.set(daoPresentation.getDaoStateSyncProgress().doubleValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,7 +783,7 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
|
||||||
|
|
||||||
StringProperty getCombinedFooterInfo() {
|
StringProperty getCombinedFooterInfo() {
|
||||||
final StringProperty combinedInfo = new SimpleStringProperty();
|
final StringProperty combinedInfo = new SimpleStringProperty();
|
||||||
combinedInfo.bind(Bindings.concat(this.footerVersionInfo, " ", daoPresentation.getBsqInfo()));
|
combinedInfo.bind(Bindings.concat(this.footerVersionInfo, " ", daoPresentation.getDaoStateInfo()));
|
||||||
return combinedInfo;
|
return combinedInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
package bisq.desktop.main.presentation;
|
package bisq.desktop.main.presentation;
|
||||||
|
|
||||||
import bisq.desktop.Navigation;
|
import bisq.desktop.Navigation;
|
||||||
import bisq.desktop.util.GUIUtil;
|
import bisq.desktop.main.MainView;
|
||||||
|
import bisq.desktop.main.dao.DaoView;
|
||||||
|
import bisq.desktop.main.dao.monitor.MonitorView;
|
||||||
|
import bisq.desktop.main.dao.monitor.daostate.DaoStateMonitorView;
|
||||||
|
import bisq.desktop.main.overlays.popups.Popup;
|
||||||
|
|
||||||
import bisq.core.btc.wallet.BsqWalletService;
|
import bisq.core.btc.wallet.BsqWalletService;
|
||||||
import bisq.core.btc.wallet.BtcWalletService;
|
import bisq.core.btc.wallet.BtcWalletService;
|
||||||
import bisq.core.dao.DaoFacade;
|
import bisq.core.dao.monitoring.DaoStateMonitoringService;
|
||||||
import bisq.core.dao.state.DaoStateListener;
|
import bisq.core.dao.state.DaoStateListener;
|
||||||
import bisq.core.dao.state.DaoStateService;
|
import bisq.core.dao.state.DaoStateService;
|
||||||
import bisq.core.dao.state.model.blockchain.Block;
|
import bisq.core.dao.state.model.blockchain.Block;
|
||||||
|
@ -28,24 +32,21 @@ import javafx.collections.MapChangeListener;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class DaoPresentation implements DaoStateListener {
|
public class DaoPresentation implements DaoStateListener, DaoStateMonitoringService.Listener {
|
||||||
public static final String DAO_NEWS = "daoNews";
|
public static final String DAO_NEWS = "daoNews";
|
||||||
|
|
||||||
private final Preferences preferences;
|
|
||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
private final BtcWalletService btcWalletService;
|
private final BtcWalletService btcWalletService;
|
||||||
private final DaoFacade daoFacade;
|
private final DaoStateMonitoringService daoStateMonitoringService;
|
||||||
private final BsqWalletService bsqWalletService;
|
private final BsqWalletService bsqWalletService;
|
||||||
private final DaoStateService daoStateService;
|
private final DaoStateService daoStateService;
|
||||||
|
|
||||||
private final ChangeListener<Number> walletChainHeightListener;
|
private final ChangeListener<Number> walletChainHeightListener;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final DoubleProperty bsqSyncProgress = new SimpleDoubleProperty(-1);
|
private final DoubleProperty daoStateSyncProgress = new SimpleDoubleProperty(-1);
|
||||||
@Getter
|
@Getter
|
||||||
private final StringProperty bsqInfo = new SimpleStringProperty("");
|
private final StringProperty daoStateInfo = new SimpleStringProperty("");
|
||||||
private final SimpleBooleanProperty showNotification = new SimpleBooleanProperty(false);
|
private final SimpleBooleanProperty showNotification = new SimpleBooleanProperty(false);
|
||||||
private boolean daoConflictWarningShown = false; // allow only one conflict warning per session
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DaoPresentation(Preferences preferences,
|
public DaoPresentation(Preferences preferences,
|
||||||
|
@ -53,12 +54,11 @@ public class DaoPresentation implements DaoStateListener {
|
||||||
BtcWalletService btcWalletService,
|
BtcWalletService btcWalletService,
|
||||||
BsqWalletService bsqWalletService,
|
BsqWalletService bsqWalletService,
|
||||||
DaoStateService daoStateService,
|
DaoStateService daoStateService,
|
||||||
DaoFacade daoFacade) {
|
DaoStateMonitoringService daoStateMonitoringService) {
|
||||||
this.preferences = preferences;
|
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
this.btcWalletService = btcWalletService;
|
this.btcWalletService = btcWalletService;
|
||||||
this.bsqWalletService = bsqWalletService;
|
this.bsqWalletService = bsqWalletService;
|
||||||
this.daoFacade = daoFacade;
|
this.daoStateMonitoringService = daoStateMonitoringService;
|
||||||
this.daoStateService = daoStateService;
|
this.daoStateService = daoStateService;
|
||||||
|
|
||||||
preferences.getDontShowAgainMapAsObservable().addListener((MapChangeListener<? super String, ? super Boolean>) change -> {
|
preferences.getDontShowAgainMapAsObservable().addListener((MapChangeListener<? super String, ? super Boolean>) change -> {
|
||||||
|
@ -73,34 +73,24 @@ public class DaoPresentation implements DaoStateListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Private
|
// Public
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void onUpdateAnyChainHeight() {
|
public void init() {
|
||||||
final int bsqBlockChainHeight = daoFacade.getChainHeight();
|
showNotification.set(false);
|
||||||
final int bsqWalletChainHeight = bsqWalletService.getBestChainHeight();
|
|
||||||
if (bsqWalletChainHeight > 0) {
|
btcWalletService.getChainHeightProperty().addListener(walletChainHeightListener);
|
||||||
final boolean synced = bsqWalletChainHeight == bsqBlockChainHeight;
|
daoStateService.addDaoStateListener(this);
|
||||||
if (bsqBlockChainHeight != bsqWalletChainHeight) {
|
daoStateMonitoringService.addListener(this);
|
||||||
bsqSyncProgress.set(-1);
|
|
||||||
} else {
|
onUpdateAnyChainHeight();
|
||||||
bsqSyncProgress.set(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (synced) {
|
public BooleanProperty getShowDaoUpdatesNotification() {
|
||||||
bsqInfo.set("");
|
return showNotification;
|
||||||
if (daoFacade.daoStateNeedsRebuilding() && !daoConflictWarningShown) {
|
|
||||||
daoConflictWarningShown = true; // only warn max 1 time per session so as not to annoy
|
|
||||||
GUIUtil.showDaoNeedsResyncPopup(navigation);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bsqInfo.set(Res.get("mainView.footer.bsqInfo.synchronizing"));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bsqInfo.set(Res.get("mainView.footer.bsqInfo.synchronizing"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// DaoStateListener
|
// DaoStateListener
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -110,22 +100,37 @@ public class DaoPresentation implements DaoStateListener {
|
||||||
onUpdateAnyChainHeight();
|
onUpdateAnyChainHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Public
|
// DaoStateMonitoringService.Listener
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public BooleanProperty getShowDaoUpdatesNotification() {
|
@Override
|
||||||
return showNotification;
|
public void onDaoStateHashesChanged() {
|
||||||
|
if (!daoStateService.isParseBlockChainComplete()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setup() {
|
if (daoStateMonitoringService.isInConflictWithSeedNode() ||
|
||||||
// devs enable this when a news badge is required
|
daoStateMonitoringService.isDaoStateBlockChainNotConnecting()) {
|
||||||
//showNotification.set(DevEnv.isDaoActivated() && preferences.showAgain(DAO_NEWS));
|
new Popup().warning(Res.get("popup.warning.daoNeedsResync"))
|
||||||
showNotification.set(false);
|
.actionButtonTextWithGoTo("navigation.dao.networkMonitor")
|
||||||
|
.onAction(() -> navigation.navigateTo(MainView.class, DaoView.class, MonitorView.class, DaoStateMonitorView.class))
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.btcWalletService.getChainHeightProperty().addListener(walletChainHeightListener);
|
|
||||||
daoStateService.addDaoStateListener(this);
|
|
||||||
|
|
||||||
onUpdateAnyChainHeight();
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void onUpdateAnyChainHeight() {
|
||||||
|
int bsqWalletChainHeight = bsqWalletService.getBestChainHeight();
|
||||||
|
int daoStateChainHeight = daoStateService.getChainHeight();
|
||||||
|
boolean chainHeightsInSync = bsqWalletChainHeight > 0 && bsqWalletChainHeight == daoStateChainHeight;
|
||||||
|
boolean isDaoStateReady = chainHeightsInSync && daoStateService.isParseBlockChainComplete();
|
||||||
|
daoStateSyncProgress.set(isDaoStateReady ? 0 : -1);
|
||||||
|
daoStateInfo.set(isDaoStateReady ? "" : Res.get("mainView.footer.bsqInfo.synchronizing"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,6 @@ import bisq.desktop.components.indicator.TxConfidenceIndicator;
|
||||||
import bisq.desktop.main.MainView;
|
import bisq.desktop.main.MainView;
|
||||||
import bisq.desktop.main.account.AccountView;
|
import bisq.desktop.main.account.AccountView;
|
||||||
import bisq.desktop.main.account.content.fiataccounts.FiatAccountsView;
|
import bisq.desktop.main.account.content.fiataccounts.FiatAccountsView;
|
||||||
import bisq.desktop.main.dao.DaoView;
|
|
||||||
import bisq.desktop.main.dao.monitor.MonitorView;
|
|
||||||
import bisq.desktop.main.dao.monitor.daostate.DaoStateMonitorView;
|
|
||||||
import bisq.desktop.main.overlays.popups.Popup;
|
import bisq.desktop.main.overlays.popups.Popup;
|
||||||
|
|
||||||
import bisq.core.account.witness.AccountAgeWitness;
|
import bisq.core.account.witness.AccountAgeWitness;
|
||||||
|
@ -806,19 +803,6 @@ public class GUIUtil {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showDaoNeedsResyncPopup(Navigation navigation) {
|
|
||||||
String key = "showDaoNeedsResyncPopup";
|
|
||||||
if (DontShowAgainLookup.showAgain(key)) {
|
|
||||||
UserThread.runAfter(() -> new Popup().warning(Res.get("popup.warning.daoNeedsResync"))
|
|
||||||
.dontShowAgainId(key)
|
|
||||||
.actionButtonTextWithGoTo("navigation.dao.networkMonitor")
|
|
||||||
.onAction(() -> {
|
|
||||||
navigation.navigateTo(MainView.class, DaoView.class, MonitorView.class, DaoStateMonitorView.class);
|
|
||||||
})
|
|
||||||
.show(), 5, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isReadyForTxBroadcastOrShowPopup(P2PService p2PService, WalletsSetup walletsSetup) {
|
public static boolean isReadyForTxBroadcastOrShowPopup(P2PService p2PService, WalletsSetup walletsSetup) {
|
||||||
if (!GUIUtil.isBootstrappedOrShowPopup(p2PService)) {
|
if (!GUIUtil.isBootstrappedOrShowPopup(p2PService)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Reference in a new issue