From 848694ad8659bcd5dcea8ebd956cb5650352b5df Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Mon, 9 Dec 2024 10:24:22 +0000 Subject: [PATCH] Add send BSQ from empty wallet test --- .../java/bisq/core/BitcoinjBsqTests.java | 128 ++++++++++-------- 1 file changed, 72 insertions(+), 56 deletions(-) diff --git a/core/src/integrationTest/java/bisq/core/BitcoinjBsqTests.java b/core/src/integrationTest/java/bisq/core/BitcoinjBsqTests.java index 411c67c12e..03e9730243 100644 --- a/core/src/integrationTest/java/bisq/core/BitcoinjBsqTests.java +++ b/core/src/integrationTest/java/bisq/core/BitcoinjBsqTests.java @@ -14,6 +14,7 @@ import bisq.core.dao.state.unconfirmed.UnconfirmedBsqChangeOutputListService; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; import org.bitcoinj.core.InsufficientMoneyException; +import org.bitcoinj.core.PeerGroup; import org.bitcoinj.core.TransactionOutput; import org.bitcoinj.kits.WalletAppKit; import org.bitcoinj.wallet.Wallet; @@ -26,12 +27,15 @@ import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.io.TempDir; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -42,81 +46,73 @@ import bisq.wallets.regtest.BitcoindExtension; import bisq.wallets.regtest.bitcoind.BitcoindRegtestSetup; @ExtendWith(BitcoindExtension.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) @Slf4j public class BitcoinjBsqTests { - private final BitcoindRegtestSetup regtestSetup; + private final BitcoindRegtestSetup bitcoindRegtestSetup; + private final BitcoinjRegtestSetup bitcoinjRegtestSetup; private final BisqRegtestNetworkParams networkParams; + private PeerGroup peerGroup; - public BitcoinjBsqTests(BitcoindRegtestSetup regtestSetup) { - this.regtestSetup = regtestSetup; + private final Wallet btcWallet; + private Wallet bsqWallet; + private final Wallet secondBsqWallet; + private final Wallet emptyBsqWallet; + + private final BisqDefaultCoinSelector btcCoinSelector = new BisqDefaultCoinSelector(true) { + @Override + protected boolean isDustAttackUtxo(TransactionOutput output) { + return false; + } + + @Override + protected boolean isTxOutputSpendable(TransactionOutput output) { + return true; + } + }; + + private BsqCoinSelector bsqCoinSelector; + + private BtcWalletV2 btcWalletV2; + + public BitcoinjBsqTests(BitcoindRegtestSetup bitcoindRegtestSetup) { + this.bitcoindRegtestSetup = bitcoindRegtestSetup; + bitcoinjRegtestSetup = new BitcoinjRegtestSetup(bitcoindRegtestSetup); networkParams = new BisqRegtestNetworkParams(); - networkParams.setPort(regtestSetup.getP2pPort()); + networkParams.setPort(bitcoindRegtestSetup.getP2pPort()); + + var walletFactory = new WalletFactory(networkParams); + btcWallet = walletFactory.createBtcWallet(); + secondBsqWallet = walletFactory.createBsqWallet(); + emptyBsqWallet = walletFactory.createBsqWallet(); } - @Test - void sendBsqTest(@TempDir Path tempDir) throws InterruptedException, InsufficientMoneyException, BsqChangeBelowDustException { - var walletFactory = new WalletFactory(networkParams); - Wallet btcWallet = walletFactory.createBtcWallet(); - Wallet secondBsqWallet = walletFactory.createBsqWallet(); - + @BeforeAll + void setup(@TempDir Path tempDir) throws InterruptedException { var wallets = List.of(btcWallet, secondBsqWallet); var regtestWalletAppKit = new RegtestWalletAppKit(networkParams, tempDir, wallets); regtestWalletAppKit.initialize(); WalletAppKit walletAppKit = regtestWalletAppKit.getWalletAppKit(); - Wallet bsqWallet = walletAppKit.wallet(); + peerGroup = walletAppKit.peerGroup(); + bsqWallet = walletAppKit.wallet(); - var bsqWalletReceivedLatch = new CountDownLatch(1); - bsqWallet.addCoinsReceivedEventListener((wallet, tx, prevBalance, newBalance) -> - bsqWalletReceivedLatch.countDown()); - - var btcWalletReceivedLatch = new CountDownLatch(1); - btcWallet.addCoinsReceivedEventListener((wallet, tx, prevBalance, newBalance) -> - btcWalletReceivedLatch.countDown()); - - Address currentReceiveAddress = bsqWallet.currentReceiveAddress(); - String address = currentReceiveAddress.toString(); - regtestSetup.fundAddress(address, 1.0); - - currentReceiveAddress = btcWallet.currentReceiveAddress(); - address = currentReceiveAddress.toString(); - regtestSetup.fundAddress(address, 1.0); - - regtestSetup.mineOneBlock(); - - boolean isSuccess = bsqWalletReceivedLatch.await(30, TimeUnit.SECONDS); - assertThat("BSQ wallet not funded after 30 seconds.", isSuccess); - - Coin balance = bsqWallet.getBalance(); - assertThat("BitcoinJ BSQ wallet balance should equal 1 BTC.", balance.equals(Coin.COIN)); - - isSuccess = btcWalletReceivedLatch.await(30, TimeUnit.SECONDS); - assertThat("BTC wallet not funded after 30 seconds.", isSuccess); - - balance = btcWallet.getBalance(); - assertThat("BitcoinJ BTC wallet balance should equal 1 BTC.", balance.equals(Coin.COIN)); + bitcoinjRegtestSetup.fundWallet(bsqWallet, 1.0); + bitcoinjRegtestSetup.fundWallet(btcWallet, 1.0); DaoStateService daoStateService = mock(DaoStateService.class); doReturn(true).when(daoStateService) .isTxOutputSpendable(any(TxOutputKey.class)); - var bsqCoinSelector = new BsqCoinSelector(daoStateService, mock(UnconfirmedBsqChangeOutputListService.class)); - var btcCoinSelector = new BisqDefaultCoinSelector(true) { - @Override - protected boolean isDustAttackUtxo(TransactionOutput output) { - return false; - } + bsqCoinSelector = new BsqCoinSelector(daoStateService, mock(UnconfirmedBsqChangeOutputListService.class)); + btcWalletV2 = new BtcWalletV2(btcCoinSelector, btcWallet); + } - @Override - protected boolean isTxOutputSpendable(TransactionOutput output) { - return true; - } - }; - - var btcWalletV2 = new BtcWalletV2(btcCoinSelector, btcWallet); + @Test + void sendBsqTest() throws InterruptedException, InsufficientMoneyException, BsqChangeBelowDustException { var bsqWalletV2 = new BsqWalletV2(networkParams, - walletAppKit.peerGroup(), + peerGroup, btcWalletV2, bsqWallet, bsqCoinSelector); @@ -130,13 +126,33 @@ public class BitcoinjBsqTests { Coin receiverAmount = Coin.ofSat(100 * 100); bsqWalletV2.sendBsq(receiverAddress, receiverAmount, Coin.ofSat(10)); - regtestSetup.mineOneBlock(); + bitcoindRegtestSetup.mineOneBlock(); - isSuccess = secondBsqWalletReceivedLatch.await(30, TimeUnit.SECONDS); + boolean isSuccess = secondBsqWalletReceivedLatch.await(30, TimeUnit.SECONDS); assertThat("Didn't receive BSQ after 30 seconds.", isSuccess); assertEquals(bsqWallet.getBalance(), Coin.ofSat(99990000)); assertEquals(btcWallet.getBalance(), Coin.ofSat(99999747)); assertEquals(secondBsqWallet.getBalance(), Coin.ofSat(10000)); } + + @Test + void sendBsqButNotEnoughBsqTest() { + var bsqWalletV2 = new BsqWalletV2(networkParams, + peerGroup, + btcWalletV2, + emptyBsqWallet, + bsqCoinSelector); + + var secondBsqWalletReceivedLatch = new CountDownLatch(1); + bsqWallet.addCoinsReceivedEventListener((wallet, tx, prevBalance, newBalance) -> + secondBsqWalletReceivedLatch.countDown()); + + // Send 100 BSQ (1 BSQ = 100 Satoshis) + Address receiverAddress = bsqWallet.currentReceiveAddress(); + Coin receiverAmount = Coin.ofSat(100 * 100); + + assertThrows(InsufficientMoneyException.class, () -> + bsqWalletV2.sendBsq(receiverAddress, receiverAmount, Coin.ofSat(10))); + } }