Skip to content

Commit

Permalink
Merge pull request #6504 from HenrikJannsen/add_check_for_isInConflic…
Browse files Browse the repository at this point in the history
…tWithSeedNode

Add check for dao state hash conflict with seed node
  • Loading branch information
alejandrogarcia83 committed Jan 6, 2023
2 parents ec411a4 + 7977c86 commit dda32c0
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 93 deletions.
3 changes: 2 additions & 1 deletion core/src/main/java/bisq/core/btc/wallet/WalletService.java
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ public static void signTx(Wallet wallet,
continue;
}
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;
}

Expand Down
17 changes: 5 additions & 12 deletions core/src/main/java/bisq/core/dao/DaoFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
import bisq.core.dao.state.DaoStateListener;
import bisq.core.dao.state.DaoStateService;
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.Tx;
import bisq.core.dao.state.model.blockchain.TxOutput;
Expand Down Expand Up @@ -531,10 +530,13 @@ public Optional<Block> getBlockAtHeight(int chainHeight) {
return daoStateService.getBlockAtHeight(chainHeight);
}

public boolean daoStateNeedsRebuilding() {
return daoStateMonitoringService.isInConflictWithSeedNode() || daoStateMonitoringService.isDaoStateBlockChainNotConnecting();
public boolean isDaoStateReadyAndInSync() {
return daoStateService.isParseBlockChainComplete() &&
!daoStateMonitoringService.isInConflictWithSeedNode() &&
!daoStateMonitoringService.isDaoStateBlockChainNotConnecting();
}


///////////////////////////////////////////////////////////////////////////////////////////
// Use case: Bonding
///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -578,10 +580,6 @@ public long getTotalAmountOfConfiscatedTxOutputs() {
return daoStateService.getTotalAmountOfConfiscatedTxOutputs();
}

public long getTotalAmountOfInvalidatedBsq() {
return daoStateService.getTotalAmountOfInvalidatedBsq();
}

// Contains burned fee and invalidated bsq due invalid txs
public long getTotalAmountOfBurntBsq() {
return daoStateService.getTotalAmountOfBurntBsq();
Expand All @@ -595,11 +593,6 @@ public List<Tx> 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) {
return daoStateService.getLockTime(txId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ public static boolean isHotfixActivated() {
// spike when opening arbitration.
private static final long DPT_MIN_TX_FEE_RATE = 10;


private final DaoStateService daoStateService;
private final BurningManService burningManService;
private int currentChainHeight;
Expand Down Expand Up @@ -127,12 +126,6 @@ public List<Tuple2<Long, String>> getReceivers(int burningManSelectionHeight,
burningManService.getActiveBurningManCandidates(burningManSelectionHeight) :
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 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.
Expand All @@ -146,12 +139,19 @@ public List<Tuple2<Long, String>> getReceivers(int burningManSelectionHeight,
// Smallest tx size is 246. With additional change output we add 32. To be safe we use the largest expected size.
double txSize = 278;
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);
// 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.
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)
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
// used later to be applied to the remaining burningmen share.
double adjustment = 1 - burningManCandidates.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public void onFault(String errorMessage, @Nullable Connection connection) {
}

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.");
missingDataRequestService.reRepublishAllGovernanceData();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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.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.buyer.BuyerFinalizesDelayedPayoutTx;
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
Expand Down Expand Up @@ -71,6 +72,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message,
.with(message)
.from(peer))
.setup(tasks(
CheckIfDaoStateIsInSync.class,
MakerProcessesInputsForDepositTxRequest.class,
ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
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.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.buyer.BuyerFinalizesDelayedPayoutTx;
import bisq.core.trade.protocol.bisq_v1.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest;
Expand Down Expand Up @@ -77,6 +78,7 @@ public void onTakeOffer() {
expect(phase(Trade.Phase.INIT)
.with(TakerEvent.TAKE_OFFER))
.setup(tasks(
CheckIfDaoStateIsInSync.class,
ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
CreateTakerFeeTx.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
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.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.maker.MakerCreateAndSignContract;
import bisq.core.trade.protocol.bisq_v1.tasks.maker.MakerProcessesInputsForDepositTxRequest;
Expand Down Expand Up @@ -73,6 +74,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message,
.with(message)
.from(peer))
.setup(tasks(
CheckIfDaoStateIsInSync.class,
MaybeCreateSubAccount.class,
MakerProcessesInputsForDepositTxRequest.class,
ApplyFilter.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
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.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.seller.MaybeCreateSubAccount;
import bisq.core.trade.protocol.bisq_v1.tasks.seller.SellerCreatesDelayedPayoutTx;
Expand Down Expand Up @@ -73,6 +74,7 @@ public void onTakeOffer() {
.with(TakerEvent.TAKE_OFFER)
.from(trade.getTradingPeerNodeAddress()))
.setup(tasks(
CheckIfDaoStateIsInSync.class,
MaybeCreateSubAccount.class,
ApplyFilter.class,
getVerifyPeersFeePaymentClass(),
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@

import lombok.extern.slf4j.Slf4j;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

@Slf4j
Expand Down Expand Up @@ -74,8 +73,19 @@ protected void run() {
depositTx,
delayedPayoutTxReceivers,
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@

import lombok.extern.slf4j.Slf4j;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

@Slf4j
Expand Down Expand Up @@ -66,8 +65,18 @@ protected void run() {
preparedDepositTx,
delayedPayoutTxReceivers,
lockTime);
checkArgument(buyersPreparedDelayedPayoutTx.getTxId().equals(sellersPreparedDelayedPayoutTx.getTxId()),
"TxIds of buyersPreparedDelayedPayoutTx and sellersPreparedDelayedPayoutTx must be the same");
if (!buyersPreparedDelayedPayoutTx.getTxId().equals(sellersPreparedDelayedPayoutTx.getTxId())) {
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
Expand Down
8 changes: 4 additions & 4 deletions desktop/src/main/java/bisq/desktop/main/MainViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ public void onSetupComplete() {
setupClockWatcherPopup();

marketPricePresentation.setup();
daoPresentation.setup();
daoPresentation.init();
accountPresentation.setup();
settingsPresentation.setup();

Expand Down Expand Up @@ -505,7 +505,7 @@ private void setupHandlers() {
.show());

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());

Expand Down Expand Up @@ -704,7 +704,7 @@ private void updateBtcSyncProgress() {
if (btcSyncProgress.doubleValue() < 1) {
combinedSyncProgress.set(btcSyncProgress.doubleValue());
} else {
combinedSyncProgress.set(daoPresentation.getBsqSyncProgress().doubleValue());
combinedSyncProgress.set(daoPresentation.getDaoStateSyncProgress().doubleValue());
}
}

Expand Down Expand Up @@ -783,7 +783,7 @@ StringProperty getBtcInfo() {

StringProperty getCombinedFooterInfo() {
final StringProperty combinedInfo = new SimpleStringProperty();
combinedInfo.bind(Bindings.concat(this.footerVersionInfo, " ", daoPresentation.getBsqInfo()));
combinedInfo.bind(Bindings.concat(this.footerVersionInfo, " ", daoPresentation.getDaoStateInfo()));
return combinedInfo;
}

Expand Down
Loading

0 comments on commit dda32c0

Please sign in to comment.