From 353ff6d06f11d7f6eed7a4f1be52cfd0ad7e0c68 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Thu, 13 Feb 2025 22:55:55 +0000 Subject: [PATCH 1/2] DelayedPayoutTxReceiverService: Make bm snapshot grid size a constant --- .../core/dao/burningman/DelayedPayoutTxReceiverService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/dao/burningman/DelayedPayoutTxReceiverService.java b/core/src/main/java/bisq/core/dao/burningman/DelayedPayoutTxReceiverService.java index c30f0c8a3fb..f2a1e0f0ffa 100644 --- a/core/src/main/java/bisq/core/dao/burningman/DelayedPayoutTxReceiverService.java +++ b/core/src/main/java/bisq/core/dao/burningman/DelayedPayoutTxReceiverService.java @@ -59,6 +59,8 @@ public class DelayedPayoutTxReceiverService implements DaoStateListener { // See: https://github.com/bisq-network/proposals/issues/412 public static final Date PROPOSAL_412_ACTIVATION_DATE = Utilities.getUTCDate(2024, GregorianCalendar.MAY, 1); + public static final int SNAPSHOT_SELECTION_GRID_SIZE = 10; + // We don't allow to get further back than 767950 (the block height from Dec. 18th 2022). static final int MIN_SNAPSHOT_HEIGHT = Config.baseCurrencyNetwork().isRegtest() ? 0 : 767950; @@ -116,7 +118,8 @@ private void applyBlock(Block block) { // The block height is the last mod(10) height from the range of the last 10-20 blocks (139 -> 120; 140 -> 130, 141 -> 130). // We do not have the latest dao state by that but can ensure maker and taker have the same block. public int getBurningManSelectionHeight() { - return getSnapshotHeight(daoStateService.getGenesisBlockHeight(), currentChainHeight, 10); + return getSnapshotHeight(daoStateService.getGenesisBlockHeight(), currentChainHeight, + SNAPSHOT_SELECTION_GRID_SIZE); } public List> getReceivers(int burningManSelectionHeight, From 96355d7a3cd0ad3cf5d6dfbe62c6cfd28e9a4e45 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Thu, 13 Feb 2025 22:56:00 +0000 Subject: [PATCH 2/2] Handle burning man selection height edge-cases If trader A's block height is 134 his burning man selection height is 120, and if trader B's block height is 135 his burning man selection height is 130. The current burning man selection height verification code doesn't handle these edge-cases. --- .../DelayedPayoutTxReceiverService.java | 2 +- .../bisq/core/offer/OpenOfferManager.java | 6 ++- ...kerProcessesInputsForDepositTxRequest.java | 24 +++++++++- ...rocessesInputsForDepositTxRequestTest.java | 44 +++++++++++++++++++ 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 core/src/test/java/bisq/core/trade/protocol/bisq_v1/tasks/maker/MakerProcessesInputsForDepositTxRequestTest.java diff --git a/core/src/main/java/bisq/core/dao/burningman/DelayedPayoutTxReceiverService.java b/core/src/main/java/bisq/core/dao/burningman/DelayedPayoutTxReceiverService.java index f2a1e0f0ffa..bc7da9d4b81 100644 --- a/core/src/main/java/bisq/core/dao/burningman/DelayedPayoutTxReceiverService.java +++ b/core/src/main/java/bisq/core/dao/burningman/DelayedPayoutTxReceiverService.java @@ -217,7 +217,7 @@ private static int getSnapshotHeight(int genesisHeight, int height, int grid) { // Borrowed from DaoStateSnapshotService. We prefer to not reuse to avoid dependency to an unrelated domain. @VisibleForTesting - static int getSnapshotHeight(int genesisHeight, int height, int grid, int minSnapshotHeight) { + public static int getSnapshotHeight(int genesisHeight, int height, int grid, int minSnapshotHeight) { if (height > (genesisHeight + 3 * grid)) { int ratio = (int) Math.round(height / (double) grid); return Math.max(minSnapshotHeight, ratio * grid - grid); diff --git a/core/src/main/java/bisq/core/offer/OpenOfferManager.java b/core/src/main/java/bisq/core/offer/OpenOfferManager.java index 3e972df040f..2b2bcc9900d 100644 --- a/core/src/main/java/bisq/core/offer/OpenOfferManager.java +++ b/core/src/main/java/bisq/core/offer/OpenOfferManager.java @@ -47,6 +47,7 @@ import bisq.core.trade.ClosedTradableManager; import bisq.core.trade.bisq_v1.TransactionResultHandler; import bisq.core.trade.model.TradableList; +import bisq.core.trade.protocol.bisq_v1.tasks.maker.MakerProcessesInputsForDepositTxRequest; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.Preferences; import bisq.core.user.User; @@ -857,7 +858,10 @@ private void handleOfferAvailabilityRequest(OfferAvailabilityRequest request, No checkArgument(takersBurningManSelectionHeight > 0, "takersBurningManSelectionHeight must not be 0"); int makersBurningManSelectionHeight = delayedPayoutTxReceiverService.getBurningManSelectionHeight(); - checkArgument(takersBurningManSelectionHeight == makersBurningManSelectionHeight, + + boolean areBurningManSelectionHeightsValid = MakerProcessesInputsForDepositTxRequest + .verifyBurningManSelectionHeight(takersBurningManSelectionHeight, makersBurningManSelectionHeight); + checkArgument(areBurningManSelectionHeightsValid, "takersBurningManSelectionHeight does no match makersBurningManSelectionHeight. " + "takersBurningManSelectionHeight=" + takersBurningManSelectionHeight + "; makersBurningManSelectionHeight=" + makersBurningManSelectionHeight); } catch (Throwable t) { diff --git a/core/src/main/java/bisq/core/trade/protocol/bisq_v1/tasks/maker/MakerProcessesInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/bisq_v1/tasks/maker/MakerProcessesInputsForDepositTxRequest.java index 395d400893e..84c9c3bf774 100644 --- a/core/src/main/java/bisq/core/trade/protocol/bisq_v1/tasks/maker/MakerProcessesInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/bisq_v1/tasks/maker/MakerProcessesInputsForDepositTxRequest.java @@ -17,6 +17,7 @@ package bisq.core.trade.protocol.bisq_v1.tasks.maker; +import bisq.core.dao.burningman.DelayedPayoutTxReceiverService; import bisq.core.exceptions.TradePriceOutOfToleranceException; import bisq.core.offer.Offer; import bisq.core.support.dispute.mediation.mediator.Mediator; @@ -83,8 +84,12 @@ protected void run() { checkArgument(takersBurningManSelectionHeight > 0, "takersBurningManSelectionHeight must not be 0"); int makersBurningManSelectionHeight = processModel.getDelayedPayoutTxReceiverService().getBurningManSelectionHeight(); - checkArgument(takersBurningManSelectionHeight == makersBurningManSelectionHeight, + + boolean areBurningManSelectionHeightsValid = verifyBurningManSelectionHeight( + takersBurningManSelectionHeight, makersBurningManSelectionHeight); + checkArgument(areBurningManSelectionHeightsValid, "takersBurningManSelectionHeight does no match makersBurningManSelectionHeight"); + processModel.setBurningManSelectionHeight(makersBurningManSelectionHeight); // We set the taker fee only in the processModel yet not in the trade as the tx was only created but not @@ -132,4 +137,21 @@ protected void run() { failed(t); } } + + public static boolean verifyBurningManSelectionHeight(int takersBurningManSelectionHeight, + int makersBurningManSelectionHeight) { + if (takersBurningManSelectionHeight == makersBurningManSelectionHeight) { + return true; + + } else if (takersBurningManSelectionHeight < makersBurningManSelectionHeight) { + int takersNextBlockBurningManSelectionHeight = + takersBurningManSelectionHeight + DelayedPayoutTxReceiverService.SNAPSHOT_SELECTION_GRID_SIZE; + return takersNextBlockBurningManSelectionHeight == makersBurningManSelectionHeight; + + } else { + int makersNextBlockBurningManSelectionHeight = + makersBurningManSelectionHeight + DelayedPayoutTxReceiverService.SNAPSHOT_SELECTION_GRID_SIZE; + return takersBurningManSelectionHeight == makersNextBlockBurningManSelectionHeight; + } + } } diff --git a/core/src/test/java/bisq/core/trade/protocol/bisq_v1/tasks/maker/MakerProcessesInputsForDepositTxRequestTest.java b/core/src/test/java/bisq/core/trade/protocol/bisq_v1/tasks/maker/MakerProcessesInputsForDepositTxRequestTest.java new file mode 100644 index 00000000000..1ce0adc6dae --- /dev/null +++ b/core/src/test/java/bisq/core/trade/protocol/bisq_v1/tasks/maker/MakerProcessesInputsForDepositTxRequestTest.java @@ -0,0 +1,44 @@ +package bisq.core.trade.protocol.bisq_v1.tasks.maker; + +import bisq.core.dao.burningman.DelayedPayoutTxReceiverService; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MakerProcessesInputsForDepositTxRequestTest { + private static final int GENESIS_HEIGHT = 102; + private static final int GRID_SIZE = DelayedPayoutTxReceiverService.SNAPSHOT_SELECTION_GRID_SIZE; + + @Test + void burningManSelectionHeightSameBlock() { + assertEquals(130, + DelayedPayoutTxReceiverService.getSnapshotHeight(GENESIS_HEIGHT, 139, GRID_SIZE, 0)); + boolean isValid = MakerProcessesInputsForDepositTxRequest + .verifyBurningManSelectionHeight(130, 130); + assertTrue(isValid); + } + + @Test + void burningManSelectionHeightMakerOneBlockInFuture() { + assertEquals(120, + DelayedPayoutTxReceiverService.getSnapshotHeight(GENESIS_HEIGHT, 134, GRID_SIZE, 0)); + assertEquals(130, + DelayedPayoutTxReceiverService.getSnapshotHeight(GENESIS_HEIGHT, 135, GRID_SIZE, 0)); + boolean isValid = MakerProcessesInputsForDepositTxRequest + .verifyBurningManSelectionHeight(120, 130); + assertTrue(isValid); + } + + @Test + void burningManSelectionHeightTakerOneBlockInFuture() { + assertEquals(120, + DelayedPayoutTxReceiverService.getSnapshotHeight(GENESIS_HEIGHT, 134, GRID_SIZE, 0)); + assertEquals(130, + DelayedPayoutTxReceiverService.getSnapshotHeight(GENESIS_HEIGHT, 135, GRID_SIZE, 0)); + boolean isValid = MakerProcessesInputsForDepositTxRequest + .verifyBurningManSelectionHeight(130, 120); + assertTrue(isValid); + } +}