Skip to content

Commit

Permalink
tests: add more coinjoin related tests (#243)
Browse files Browse the repository at this point in the history
* tests(coinjoin): add tests for CoinJoinEntry, CoinJoinQueue, CoinJoinClientOptions

* tests(coinjoin): rename dsq tests
  • Loading branch information
HashEngineering authored Mar 19, 2024
1 parent 4606d5f commit 5c96255
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.collect.Lists;
import org.bitcoinj.core.Coin;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

Expand All @@ -24,6 +25,11 @@ public class CoinJoinClientOptionsTest {
public void startUp() {
CoinJoinClientOptions.reset();
}

@After
public void tearDown() {
CoinJoinClientOptions.reset();
}
@Test
public void getTest() {
assertEquals(CoinJoinClientOptions.getSessions(), DEFAULT_COINJOIN_SESSIONS);
Expand All @@ -37,6 +43,9 @@ public void getTest() {
assertEquals(CoinJoinClientOptions.isMultiSessionEnabled(), DEFAULT_COINJOIN_MULTISESSION);

assertEquals(CoinJoinClientOptions.getDenominations(), CoinJoin.getStandardDenominations());

assertEquals(CoinJoinClientOptions.getDenomsGoal(), DEFAULT_COINJOIN_DENOMS_GOAL);
assertEquals(CoinJoinClientOptions.getDenomsHardCap(), DEFAULT_COINJOIN_DENOMS_HARDCAP);
}

@Test
Expand All @@ -61,5 +70,15 @@ public void setTest() {
denomsWithoutThousandths.remove(CoinJoin.getSmallestDenomination());
CoinJoinClientOptions.removeDenomination(CoinJoin.getSmallestDenomination());
assertEquals(denomsWithoutThousandths, CoinJoinClientOptions.getDenominations());

CoinJoinClientOptions.setDenomsGoal(DEFAULT_COINJOIN_DENOMS_GOAL * 2);
assertEquals(CoinJoinClientOptions.getDenomsGoal(), DEFAULT_COINJOIN_DENOMS_GOAL * 2);
CoinJoinClientOptions.setDenomsHardCap(DEFAULT_COINJOIN_DENOMS_HARDCAP * 2);
assertEquals(CoinJoinClientOptions.getDenomsHardCap(), DEFAULT_COINJOIN_DENOMS_HARDCAP * 2);

CoinJoinClientOptions.removeDenomination(Denomination.SMALLEST.value);
assertEquals(CoinJoin.getStandardDenominations().size() - 1, CoinJoinClientOptions.getDenominations().size());
CoinJoinClientOptions.resetDenominations();
assertEquals(CoinJoin.getStandardDenominations(), CoinJoinClientOptions.getDenominations());
}
}
139 changes: 139 additions & 0 deletions core/src/test/java/org/bitcoinj/coinjoin/CoinJoinEntryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package org.bitcoinj.coinjoin;

import com.google.common.collect.Lists;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Peer;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutPoint;
import org.bitcoinj.core.TransactionOutput;
import org.bitcoinj.core.Utils;
import org.bitcoinj.params.UnitTestParams;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

import static org.easymock.EasyMock.createMock;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class CoinJoinEntryTest {
/*
CoinJoinClientSession.relay: Sending CoinJoinEntry(txCollateral=b8f30db7d0c201dd4f6632fe09ccffadbded3051b5c0f3ac435e9d56f40b777d, mixingInputs.size=5, mixingOutputs.size=5)
input: TxIn for [9d70c0a4566f438091a0659b726551c1faaa477155d90d8b6858c264f7117ba5:1]: <empty>
input: TxIn for [5a23dd70dbf8f595ac55710c708e514c613595aae958c1b9bad02dbac1d7b16e:0]: <empty>
input: TxIn for [8087b393549d86c330abc3f1cf9e07375d39ce91f23c081270d7a1f18ff82621:0]: <empty>
input: TxIn for [ab4dae4aa27dad995ed3372918a7a9247b13149bf1b126194d93b322e1fb92c6:2]: <empty>
input: TxIn for [c471ff68382b91ba49546d7147f851a1b724c2a23c03db2dad457c3c3a9765ac:0]: <empty>
output: TxOut of 0.00100001 DASH to ycRPFRGZSuFE9NufKvJRHVRWgU7HjZHe4E script:DUP HASH160 PUSHDATA(20)[b0a180dfd44ba7066f5f42f3eaf431f0cd668fe3] EQUALVERIFY CHECKSIG
output: TxOut of 0.00100001 DASH to yXQTFMZR93symkQQP6sBdoNWfuTBXC8LRW script:DUP HASH160 PUSHDATA(20)[799bcbf0ff47c4e83fbf1db27a337cc89ed84070] EQUALVERIFY CHECKSIG
output: TxOut of 0.00100001 DASH to yLsPyeigcsyiuTZtXtARc3FjQhiG7jsgXg script:DUP HASH160 PUSHDATA(20)[060ae9e82d52804b66911e8aa4e94d88665ec19f] EQUALVERIFY CHECKSIG
output: TxOut of 0.00100001 DASH to ybKZyyEqADxWAZWdgNZEYu36gHbcD2Ea1m script:DUP HASH160 PUSHDATA(20)[a48fd783b7a6aad534a91f941a9665c8ecf09643] EQUALVERIFY CHECKSIG
output: TxOut of 0.00100001 DASH to yVhMBVUoRCrh7gCuLxkfnhyGHnDSzdKK4E script:DUP HASH160 PUSHDATA(20)[66dd8d620782a0d89e63f0ff2d7935c46e053a42] EQUALVERIFY CHECKSIG to 214614
CoinJoinClientSession.relay: CoinJoinEntry: 05a57b11f764c258688b0dd9557147aafac15165729b65a09180436f56a4c0709d0100000000ffffffff6eb1d7c1ba2dd0bab9c158e9aa9535614c518e700c7155ac95f5f8db70dd235a0000000000ffffffff2126f88ff1a1d77012083cf291ce395d37079ecff1c3ab30c3869d5493b387800000000000ffffffffc692fbe122b3934d1926b1f19b14137b24a9a7182937d35e99ad7da24aae4dab0200000000ffffffffac65973a3c7c45ad2ddb033ca2c224b7a151f847716d5449ba912b3868ff71c40000000000ffffffff0100000001dd86755f2cb8d67c52da2fc42c9a97a2b08e6de01f94037390d46fae68e8ed99000000006b483045022100954aa1d666906e78bcc42806874f153d31d5e1e4ae18dcadcbf8dbfc1123e3900220732c82db96098bbee7a69f284464d5233de0e2adf23401552bf2eba1623509fb0121036bfa0b828ff9b020750e765158495979bea2134b13386e6655e00ce1b9cbe980ffffffff0110270000000000001976a9146f6293e33e78ae0f2d74ba1922b86794b9efb08288ac0000000005a1860100000000001976a914b0a180dfd44ba7066f5f42f3eaf431f0cd668fe388aca1860100000000001976a914799bcbf0ff47c4e83fbf1db27a337cc89ed8407088aca1860100000000001976a914060ae9e82d52804b66911e8aa4e94d88665ec19f88aca1860100000000001976a914a48fd783b7a6aad534a91f941a9665c8ecf0964388aca1860100000000001976a91466dd8d620782a0d89e63f0ff2d7935c46e053a4288ac
*/

static byte[] dsiMessage = Utils.HEX.decode("05a57b11f764c258688b0dd9557147aafac15165729b65a09180436f56a4c0709d0100000000ffffffff6eb1d7c1ba2dd0bab9c158e9aa9535614c518e700c7155ac95f5f8db70dd235a0000000000ffffffff2126f88ff1a1d77012083cf291ce395d37079ecff1c3ab30c3869d5493b387800000000000ffffffffc692fbe122b3934d1926b1f19b14137b24a9a7182937d35e99ad7da24aae4dab0200000000ffffffffac65973a3c7c45ad2ddb033ca2c224b7a151f847716d5449ba912b3868ff71c40000000000ffffffff0100000001dd86755f2cb8d67c52da2fc42c9a97a2b08e6de01f94037390d46fae68e8ed99000000006b483045022100954aa1d666906e78bcc42806874f153d31d5e1e4ae18dcadcbf8dbfc1123e3900220732c82db96098bbee7a69f284464d5233de0e2adf23401552bf2eba1623509fb0121036bfa0b828ff9b020750e765158495979bea2134b13386e6655e00ce1b9cbe980ffffffff0110270000000000001976a9146f6293e33e78ae0f2d74ba1922b86794b9efb08288ac0000000005a1860100000000001976a914b0a180dfd44ba7066f5f42f3eaf431f0cd668fe388aca1860100000000001976a914799bcbf0ff47c4e83fbf1db27a337cc89ed8407088aca1860100000000001976a914060ae9e82d52804b66911e8aa4e94d88665ec19f88aca1860100000000001976a914a48fd783b7a6aad534a91f941a9665c8ecf0964388aca1860100000000001976a91466dd8d620782a0d89e63f0ff2d7935c46e053a4288ac");
static byte[] txCollateralBytes = Utils.HEX.decode("0100000001dd86755f2cb8d67c52da2fc42c9a97a2b08e6de01f94037390d46fae68e8ed99000000006b483045022100954aa1d666906e78bcc42806874f153d31d5e1e4ae18dcadcbf8dbfc1123e3900220732c82db96098bbee7a69f284464d5233de0e2adf23401552bf2eba1623509fb0121036bfa0b828ff9b020750e765158495979bea2134b13386e6655e00ce1b9cbe980ffffffff0110270000000000001976a9146f6293e33e78ae0f2d74ba1922b86794b9efb08288ac00000000");

private CoinJoinEntry coinJoinEntry;
private final NetworkParameters params = UnitTestParams.get();
private List<CoinJoinTransactionInput> mixingInputs;
private List<TransactionOutput> mixingOutputs;
private Transaction txCollateral;
private Peer peer;

@Before
public void setUp() {
// Initialize parameters
mixingInputs = Lists.newArrayList(
new CoinJoinTransactionInput(new TransactionInput(params, null, new byte[0], new TransactionOutPoint(params, 1L, Sha256Hash.wrap("9d70c0a4566f438091a0659b726551c1faaa477155d90d8b6858c264f7117ba5"))), null, 0),
new CoinJoinTransactionInput(new TransactionInput(params, null, new byte[0], new TransactionOutPoint(params, 0L, Sha256Hash.wrap("5a23dd70dbf8f595ac55710c708e514c613595aae958c1b9bad02dbac1d7b16e"))), null, 0),
new CoinJoinTransactionInput(new TransactionInput(params, null, new byte[0], new TransactionOutPoint(params, 0L, Sha256Hash.wrap("8087b393549d86c330abc3f1cf9e07375d39ce91f23c081270d7a1f18ff82621"))), null, 0),
new CoinJoinTransactionInput(new TransactionInput(params, null, new byte[0], new TransactionOutPoint(params, 2L, Sha256Hash.wrap("ab4dae4aa27dad995ed3372918a7a9247b13149bf1b126194d93b322e1fb92c6"))), null, 0),
new CoinJoinTransactionInput(new TransactionInput(params, null, new byte[0], new TransactionOutPoint(params, 0L, Sha256Hash.wrap("c471ff68382b91ba49546d7147f851a1b724c2a23c03db2dad457c3c3a9765ac"))), null, 0)
);
mixingOutputs = Lists.newArrayList(
new TransactionOutput(params, null, Denomination.THOUSANDTH.value, Address.fromBase58(params, "ycRPFRGZSuFE9NufKvJRHVRWgU7HjZHe4E")),
new TransactionOutput(params, null, Denomination.THOUSANDTH.value, Address.fromBase58(params, "yXQTFMZR93symkQQP6sBdoNWfuTBXC8LRW")),
new TransactionOutput(params, null, Denomination.THOUSANDTH.value, Address.fromBase58(params, "yLsPyeigcsyiuTZtXtARc3FjQhiG7jsgXg")),
new TransactionOutput(params, null, Denomination.THOUSANDTH.value, Address.fromBase58(params, "ybKZyyEqADxWAZWdgNZEYu36gHbcD2Ea1m")),
new TransactionOutput(params, null, Denomination.THOUSANDTH.value, Address.fromBase58(params, "yVhMBVUoRCrh7gCuLxkfnhyGHnDSzdKK4E"))
);
txCollateral = new Transaction(params, txCollateralBytes, 0);
peer = createMock(Peer.class);

// Initialize the CoinJoinEntry instance
coinJoinEntry = new CoinJoinEntry(params, mixingInputs, mixingOutputs, txCollateral);
}

@Test
public void testConstructorWithParamsAndPayload() {
// Test constructor with NetworkParameters and payload
CoinJoinEntry entry = new CoinJoinEntry(params, dsiMessage);

assertEquals(mixingInputs, entry.getMixingInputs());
assertEquals(mixingOutputs, entry.getMixingOutputs());
assertEquals(txCollateral, entry.getTxCollateral());
}

@Test
public void testConstructorWithParamsAndInputsOutputsCollateral() {
assertNotNull(coinJoinEntry);
assertEquals(mixingInputs, coinJoinEntry.getMixingInputs());
assertEquals(mixingOutputs, coinJoinEntry.getMixingOutputs());
assertEquals(txCollateral, coinJoinEntry.getTxCollateral());
}

@Test
public void testBitcoinSerializeToStream() {
assertArrayEquals(dsiMessage, coinJoinEntry.bitcoinSerialize());
}

@Test
public void testToStringMethods() {
String result = coinJoinEntry.toString();
assertNotNull(result);
}

@Test
public void testGetters() {
assertEquals(mixingInputs, coinJoinEntry.getMixingInputs());
assertEquals(mixingOutputs, coinJoinEntry.getMixingOutputs());
assertEquals(txCollateral, coinJoinEntry.getTxCollateral());
}

@Test
public void testSetPeer() {
coinJoinEntry.setPeer(peer);
assertEquals(peer, coinJoinEntry.getPeer());
}

@Test
public void testAddScriptSig() {
TransactionInput txin = new TransactionInput(params, null, new byte[0], new TransactionOutPoint(params, 1L, Sha256Hash.wrap("9d70c0a4566f438091a0659b726551c1faaa477155d90d8b6858c264f7117ba5")));
boolean result = coinJoinEntry.addScriptSig(txin);
assertTrue(result);
}

@Test
public void testAddScriptSigFail() {
TransactionInput txin = new TransactionInput(params, null, new byte[0], new TransactionOutPoint(params, 1L, Sha256Hash.wrap("1370c0a4566f438091a0659b726551c1faaa477155d90d8b6858c264f7117ba5")));
boolean result = coinJoinEntry.addScriptSig(txin);
assertFalse(result);
}

@Test
public void testAddScriptSigFailAlreadySetSignature() {
TransactionInput txin = new TransactionInput(params, null, new byte[0], new TransactionOutPoint(params, 1L, Sha256Hash.wrap("9d70c0a4566f438091a0659b726551c1faaa477155d90d8b6858c264f7117ba5")));
boolean result = coinJoinEntry.addScriptSig(txin);
assertTrue(result);
assertFalse(coinJoinEntry.addScriptSig(txin));
}
}
38 changes: 38 additions & 0 deletions core/src/test/java/org/bitcoinj/coinjoin/CoinJoinQueueTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.bitcoinj.crypto.BLSScheme;
import org.bitcoinj.crypto.BLSSecretKey;
import org.bitcoinj.params.UnitTestParams;
import org.bouncycastle.util.encoders.Hex;
import org.dashj.bls.BLSJniLibrary;
import org.dashj.bls.PrivateKey;
import org.junit.Before;
Expand Down Expand Up @@ -68,6 +69,43 @@ public void queueTest() {
assertArrayEquals(payload, queueFromCtor.bitcoinSerialize());
BLSPublicKey masternodeOperatorKey = new BLSPublicKey(Utils.HEX.decode("066d57a6451b7800c1c2a6c6e04fe73ec2e1c95e492bacae760ad2f79ca3c30727ec9bf0daea43c08ff1ad6c2cf07612"), true);
assertTrue(queueFromCtor.checkSignature(masternodeOperatorKey));
assertFalse(queueFromCtor.isTried());
queueFromCtor.setTried(true);
assertTrue(queueFromCtor.isTried());
}

/*
Test using a masternode with a basic operator key and a basic signature
*/
@Test
public void queueWithBasicMasternodePass() {
byte[] payload = Utils.HEX.decode("08000000e6a70ae4131ee990a4c014421685e9a3f4ad1197f8e4f247eb4121905af74a3a17779865000000000160a9852a8fe5d7d4c1be091adbcc226d06b5446d0b3cf75384c945068eab7ede51cfc64666f0d2e6bee07b5b463b8016e209ea16c3a9faa915ddc1037aa59d5c74f403f8b0da263a97a18f81134be41f55b1b59f16f88c8e44c3801bd236f96444");
byte[] masternodePublicKeyBytes = Utils.HEX.decode("a1a2ce03d33508fa6d0d0d106b405824a5a583ce109e1e5513c76d3c70aac13b49ed78980ac7fb0836d391d34c453a5d");
CoinJoinQueue queueFromHex = new CoinJoinQueue(PARAMS, payload, PARAMS.getProtocolVersionNum(NetworkParameters.ProtocolVersion.BLS_BASIC));
BLSPublicKey masternodePublicKey = new BLSPublicKey(masternodePublicKeyBytes, false);

assertTrue(queueFromHex.checkSignature(masternodePublicKey));
assertEquals(8, queueFromHex.getDenomination());
assertArrayEquals(Hex.decode("a9852a8fe5d7d4c1be091adbcc226d06b5446d0b3cf75384c945068eab7ede51cfc64666f0d2e6bee07b5b463b8016e209ea16c3a9faa915ddc1037aa59d5c74f403f8b0da263a97a18f81134be41f55b1b59f16f88c8e44c3801bd236f96444"), queueFromHex.getSignature().getBytes());
assertFalse(queueFromHex.isTried());
assertTrue(queueFromHex.isTimeOutOfBounds());
}

/*
Test using a masternode with a legacy operator key, but a basic signature
*/
@Test
public void queueWithLegacyMasternodeTest() {
byte[] payload = Utils.HEX.decode("04000000d7c0742ff5feecdf9ba16028cdd20ce6d740e8134e726967b472e57c4e80e50a888698650000000001609477d10b679ac351aed7af38747b513847cb60b422aca6982f1ae9c1dc8a07e7a29c9d97b53cfdced846997f045079510924bbe9baf3a074d1ee495c36fbc968d1a632a9189297e5e9fd820343448ed3b559d39b039b13fb6499216fa95aa2bc");
byte[] masternodePublicKeyBytes = Utils.HEX.decode("980d9cbfe63468e27b06bb20224f9f5a443a3a8d31fd4e7d52412121c5b7b2f6036089eae3dbbf36a1a7fa2fc1de654c");
CoinJoinQueue queueFromHex = new CoinJoinQueue(PARAMS, payload, PARAMS.getProtocolVersionNum(NetworkParameters.ProtocolVersion.BLS_BASIC));
BLSPublicKey masternodePublicKey = new BLSPublicKey(masternodePublicKeyBytes, true);

assertTrue(queueFromHex.checkSignature(masternodePublicKey));
assertEquals(4, queueFromHex.getDenomination());
assertArrayEquals(Hex.decode("9477d10b679ac351aed7af38747b513847cb60b422aca6982f1ae9c1dc8a07e7a29c9d97b53cfdced846997f045079510924bbe9baf3a074d1ee495c36fbc968d1a632a9189297e5e9fd820343448ed3b559d39b039b13fb6499216fa95aa2bc"), queueFromHex.getSignature().getBytes());
assertFalse(queueFromHex.isTried());
assertTrue(queueFromHex.isTimeOutOfBounds());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ public void sessionTestTwo() throws Exception {
Message broadcastTxMessage = outbound(spvClient);
assertEquals(CoinJoinBroadcastTx.class, broadcastTxMessage.getClass());
mixingTx = ((CoinJoinBroadcastTx) broadcastTxMessage).getTx();
memPool.add(mixingTx);// wallet.receivePending(mixingTx, Lists.newArrayList());
memPool.add(mixingTx);

CoinJoinBroadcastTx broadcastTxTwo = CoinJoin.getDSTX(mixingTx.getTxId());
assertNotNull(broadcastTxTwo);
Expand Down Expand Up @@ -574,6 +574,7 @@ public void sessionTestTwo() throws Exception {
// assertEquals(initialDenominatedBalance.subtract(mixingFee).subtract(mixed), wallet.getBalanceInfo().getDenominatedTrusted());

// TODO: check wallet balance types here
assertTrue(clientManager.doAutomaticDenominating(true));

if (clientManager.isMixing()) {
clientManager.stopMixing();
Expand Down

0 comments on commit 5c96255

Please sign in to comment.