Commit a0c10aa8 authored by zeroleak's avatar zeroleak
Browse files

load txs mock from local json files for tests

parent 672106e2
......@@ -61,12 +61,6 @@ server.rpc-client.mock-tx-broadcast = false
For testing purpose, *server.rpc-client.mock-tx-broadcast* can be enabled to mock txs instead of broadcasting it.
When enabled, server will keep whirlpool txs in memory until server restart and act as if these txs are confirmed in blockchain.
```
server.rpc-client.protocol = mock
```
For testing purpose, *server.rpc-client.protocol* can be set to *mock* to read blockchain data from mock instead of retrieving it from a real bitcoin node.
### Building
- Use *build.sh* on your local developer machine:
```
......
package com.samourai.whirlpool.server.tools;
import com.samourai.whirlpool.server.beans.RpcTransaction;
import com.samourai.whirlpool.server.services.BlockchainDataService;
import com.samourai.whirlpool.server.utils.TestUtils;
import com.samourai.whirlpool.server.utils.Utils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Profile;
import org.springframework.test.context.junit4.SpringRunner;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
/**
* Utility for RPC testing.
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = DEFINED_PORT)
@Profile("default") // not test profile for this tool
public class RpcToolsApplication {
private static final Logger log = LoggerFactory.getLogger(RpcToolsApplication.class);
@Autowired
private BlockchainDataService blockchainDataService;
@Autowired
private TestUtils testUtils;
@Autowired
private ApplicationContext applicationContext;
@Test
public void testRun() throws Exception {
Assert.assertEquals(BlockchainDataService.class, blockchainDataService.getClass());
Assert.assertTrue(blockchainDataService.testConnectivity());
log.info("------------ application-rpc ------------");
String[] txids = {
"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187",
"7ea75da574ebabf8d17979615b059ab53aae3011926426204e730d164a0d0f16",
"5369dfb71b36ed2b91ca43f388b869e617558165e4f8306b80857d88bdd624f2",
"3bb546df988d8a577c2b2f216a18b7e337ebaf759187ae88e0eee01829f04eb1",
};
for (String txid : txids) {
printTx(txid);
}
}
private void printTx(String txid) throws Exception {
RpcTransaction tx = blockchainDataService.__getRpcTransaction(txid).get();
Assert.assertEquals(txid, tx.getTxid());
String json = Utils.toJsonString(tx);
String fileName = testUtils.getMockFileName(txid);
System.out.println("writing " + fileName + ": " + json);
Files.write(Paths.get(fileName), json.getBytes(), StandardOpenOption.CREATE);
}
}
......@@ -4,21 +4,11 @@ import com.samourai.wallet.bip47.rpc.BIP47Wallet;
import com.samourai.wallet.hd.HD_Wallet;
import com.samourai.wallet.segwit.SegwitAddress;
import com.samourai.wallet.segwit.bech32.Bech32Util;
import com.samourai.whirlpool.server.beans.Mix;
import com.samourai.whirlpool.server.beans.RpcOut;
import com.samourai.whirlpool.server.beans.RpcTransaction;
import com.samourai.whirlpool.server.beans.TxOutPoint;
import com.samourai.whirlpool.server.services.BlockchainDataService;
import com.samourai.whirlpool.server.services.CryptoService;
import com.samourai.whirlpool.server.services.MockBlockchainDataService;
import org.bitcoinj.core.*;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.MnemonicCode;
import org.bitcoinj.script.Script;
import org.bitcoinj.wallet.KeyChain;
import org.bitcoinj.wallet.KeyChainGroup;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Assert;
import org.springframework.stereotype.Service;
import java.io.InputStream;
......@@ -28,12 +18,10 @@ import java.security.SecureRandom;
public class TestUtils {
private CryptoService cryptoService;
protected Bech32Util bech32Util;
protected BlockchainDataService blockchainDataService;
public TestUtils(CryptoService cryptoService, Bech32Util bech32Util, BlockchainDataService blockchainDataService) {
public TestUtils(CryptoService cryptoService, Bech32Util bech32Util) {
this.cryptoService = cryptoService;
this.bech32Util = bech32Util;
this.blockchainDataService = blockchainDataService;
}
public SegwitAddress createSegwitAddress() throws Exception {
......@@ -76,52 +64,8 @@ public class TestUtils {
return generateWallet(purpose, seed, "test");
}
public TxOutPoint createAndMockTxOutPoint(SegwitAddress address, long amount) throws Exception {
return createAndMockTxOutPoint(address, amount, null, null, null);
}
public TxOutPoint createAndMockTxOutPoint(SegwitAddress address, long amount, int nbConfirmations) throws Exception {
return createAndMockTxOutPoint(address, amount, nbConfirmations, null, null);
}
public TxOutPoint createAndMockTxOutPoint(SegwitAddress address, long amount, Integer nbConfirmations, String utxoHash, Integer utxoIndex) throws Exception{
NetworkParameters params = cryptoService.getNetworkParameters();
// generate transaction with bitcoinj
Transaction transaction = new Transaction(params);
if (nbConfirmations == null) {
nbConfirmations = 1000;
}
if (utxoHash != null) {
transaction.setHash(Sha256Hash.wrap(Hex.decode(utxoHash)));
}
if (utxoIndex != null) {
for (int i=0; i<utxoIndex; i++) {
transaction.addOutput(Coin.valueOf(amount), createSegwitAddress().getAddress());
}
}
String addressBech32 = address.getBech32AsString();
TransactionOutput transactionOutput = bech32Util.getTransactionOutput(addressBech32, amount, params);
transaction.addOutput(transactionOutput);
if (utxoIndex == null) {
utxoIndex = transactionOutput.getIndex();
}
else {
Assert.assertEquals((long)utxoIndex, transactionOutput.getIndex());
}
// mock tx
((MockBlockchainDataService)blockchainDataService).mock(transaction, nbConfirmations);
// verify mock
RpcTransaction rpcTransaction = ((MockBlockchainDataService) blockchainDataService).getRpcTransaction(transaction.getHashAsString());
RpcOut rpcOut = Utils.findTxOutput(rpcTransaction, utxoIndex);
Assert.assertEquals(addressBech32, bech32Util.getAddressFromScript(new Script(rpcOut.getScriptPubKey()), params));
TxOutPoint txOutPoint = new TxOutPoint(rpcTransaction.getHash(), rpcOut.getIndex(), amount);
return txOutPoint;
public String getMockFileName(String txid) {
return "./src/test/resources/mocks/" + txid + ".json";
}
}
{"txid":"3bb546df988d8a577c2b2f216a18b7e337ebaf759187ae88e0eee01829f04eb1","confirmations":120581,"ins":[{"originHash":"781bc448f381e160d014f5515daf8a175bb689112c7755c70c6bbdbb32af56cc","originIndex":5},{"originHash":"c1da465e30f3a7d19d3f3d254f387782247ea48cf22b832c474c37d17394cae6","originIndex":1},{"originHash":"1d8a370ded61c81c925151ba7112d61d1535f7035756c43d2d5a77903afddd40","originIndex":3},{"originHash":"8d0bf279b4a7fe4ad27c49a7546cab1c10201ee3a1105e502afb5c31908f4771","originIndex":4},{"originHash":"1d8a370ded61c81c925151ba7112d61d1535f7035756c43d2d5a77903afddd40","originIndex":2}],"outs":[{"hash":"3bb546df988d8a577c2b2f216a18b7e337ebaf759187ae88e0eee01829f04eb1","index":0,"value":10000000,"scriptPubKey":"ABQmd96kaVPR7koQ6uGY8riWflTyzw==","toAddress":"tb1qyemaafrf20g7ujssatse3u4cjel9fuk0nxa8v8"},{"hash":"3bb546df988d8a577c2b2f216a18b7e337ebaf759187ae88e0eee01829f04eb1","index":1,"value":10000000,"scriptPubKey":"ABQ/9sVk9N9YN5Ykdcl8SMPQDsh+Ag==","toAddress":"tb1q8lmv2e85mavr093ywhyhcjxr6q8vslsz0f8964"},{"hash":"3bb546df988d8a577c2b2f216a18b7e337ebaf759187ae88e0eee01829f04eb1","index":2,"value":10000000,"scriptPubKey":"ABQ/9sVk9N9YN5Ykdcl8SMPQDsh+Ag==","toAddress":"tb1q8lmv2e85mavr093ywhyhcjxr6q8vslsz0f8964"},{"hash":"3bb546df988d8a577c2b2f216a18b7e337ebaf759187ae88e0eee01829f04eb1","index":3,"value":10000000,"scriptPubKey":"ABRLVEUi2oTrke96FOypU6AlehMugA==","toAddress":"tb1qfd2y2gk6sn4ermm6znk2j5aqy4apxt5qd7fdn3"},{"hash":"3bb546df988d8a577c2b2f216a18b7e337ebaf759187ae88e0eee01829f04eb1","index":4,"value":10000000,"scriptPubKey":"ABRWbQYMmIRNoAbS6fbg6ppOMIz+FQ==","toAddress":"tb1q2eksvrycs3x6qpkja8mwp656fccgels448zzde"}]}
\ No newline at end of file
{"txid":"5369dfb71b36ed2b91ca43f388b869e617558165e4f8306b80857d88bdd624f2","confirmations":112273,"ins":[{"originHash":"419b92f7de21733f531f0623c0f9b7ceaab396f894881bf4b6d193b27ffefc3d","originIndex":1},{"originHash":"65e004c693a33eed47af6a0dd4c720e0011afdeff95887de8b87c57176f583e3","originIndex":0},{"originHash":"7ea75da574ebabf8d17979615b059ab53aae3011926426204e730d164a0d0f16","originIndex":0},{"originHash":"7ea75da574ebabf8d17979615b059ab53aae3011926426204e730d164a0d0f16","originIndex":3}],"outs":[{"hash":"5369dfb71b36ed2b91ca43f388b869e617558165e4f8306b80857d88bdd624f2","index":0,"value":971950,"scriptPubKey":"ABTeJUptOyMz7Nj0aPYDlZEZmZK8kA==","toAddress":"tb1qmcj55mfmyve7ek85drmq89v3rxve90ysxn6cdf"},{"hash":"5369dfb71b36ed2b91ca43f388b869e617558165e4f8306b80857d88bdd624f2","index":1,"value":39305908,"scriptPubKey":"qRS7DPiS7PZYn1DAUHmhakMa8ZtqaYc=","toAddress":"2NAJFtPxGwctDDgNCRhwcQxbyfGbGUHZukP"},{"hash":"5369dfb71b36ed2b91ca43f388b869e617558165e4f8306b80857d88bdd624f2","index":2,"value":100010000,"scriptPubKey":"ABQ7ltZzSCovYkEUf+CS8OHeWUclFQ==","toAddress":"tb1q8wtdvu6g9ghkysg50lsf9u8pmev5wfg4lehh9c"},{"hash":"5369dfb71b36ed2b91ca43f388b869e617558165e4f8306b80857d88bdd624f2","index":3,"value":100010000,"scriptPubKey":"ABR9ZnT1kqdMHm5j0TqNPCNbSi4UqA==","toAddress":"tb1q04n8favj5axpumnr6yag60prtd9zu99gc6z4k2"}]}
\ No newline at end of file
{"txid":"7ea75da574ebabf8d17979615b059ab53aae3011926426204e730d164a0d0f16","confirmations":112274,"ins":[{"originHash":"419b92f7de21733f531f0623c0f9b7ceaab396f894881bf4b6d193b27ffefc3d","originIndex":2},{"originHash":"7c73ef7e21cd4c8d87c944f2d49f9110105d7bf1bd391b3ec2e345d290dc402b","originIndex":0},{"originHash":"84da039c7509689e84c9b06033427d71936275729424f759d6da0a7ae63254c4","originIndex":2}],"outs":[{"hash":"7ea75da574ebabf8d17979615b059ab53aae3011926426204e730d164a0d0f16","index":0,"value":48318441,"scriptPubKey":"qRSCSUCKYp5w5CNJrd0+NoiKDqFXgoc=","toAddress":"2N587asHhA9WSE8L7aQXAnYkkdc1cDQdGHk"},{"hash":"7ea75da574ebabf8d17979615b059ab53aae3011926426204e730d164a0d0f16","index":1,"value":99994570,"scriptPubKey":"dqkUPP9divJk3LvIS66HognT784xc0OIrA==","toAddress":"mm5UkfQZgCmfZznNQ3HEnLdyDZ3xZRFCp6"},{"hash":"7ea75da574ebabf8d17979615b059ab53aae3011926426204e730d164a0d0f16","index":2,"value":100010000,"scriptPubKey":"ABSTBFSVvGnA1qPJ5ShciWnyPHnPlQ==","toAddress":"tb1qjvz9f9dud8qddg7fu559eztf7g78nnu4c3yclu"},{"hash":"7ea75da574ebabf8d17979615b059ab53aae3011926426204e730d164a0d0f16","index":3,"value":100010000,"scriptPubKey":"ABTXmMqcfnZPUYaIfws4GlC3Eixmiw==","toAddress":"tb1q67vv48r7we84rp5g0u9nsxjskufzce5t2955cp"}]}
\ No newline at end of file
{"txid":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","confirmations":117094,"ins":[{"originHash":"0bcde72d31c8bf0fb7752fafb22462d94bbc5d6f86e174f0a05005258518a6d9","originIndex":0}],"outs":[{"hash":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","index":0,"value":0,"scriptPubKey":"agQAAAAB","toAddress":null},{"hash":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","index":1,"value":975000,"scriptPubKey":"ABQR677HxIt9QsGk9tgI8qyBvoUDtw==","toAddress":"tb1qz84ma37y3d759sdy7mvq3u4vsxlg2qahw3lm23"},{"hash":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","index":2,"value":10001000,"scriptPubKey":"ABQqZPjqF+v2xVAb0PlvfPQxFOJoAQ==","toAddress":"tb1q9fj036sha0mv25qm6ruk7l85xy2wy6qp853yx0"},{"hash":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","index":3,"value":10001000,"scriptPubKey":"ABSXR9erx2DgM6GdR30gkVgvdrQwiw==","toAddress":"tb1qjara0278vrsr8gvaga7jpy2c9amtgvytr44xym"},{"hash":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","index":4,"value":10001000,"scriptPubKey":"ABScH/1ympXuA06O/FXhAibsF66HqA==","toAddress":"tb1qns0l6u56jhhqxn5wl327zq3xast6apagm6xudc"},{"hash":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","index":5,"value":10001000,"scriptPubKey":"ABTqbU6CRB0+mbIRl5ZLXoFK0uZDDA==","toAddress":"tb1qafk5aqjyr5lfnvs3j7tykh5pftfwvscvar3307"},{"hash":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","index":6,"value":10001000,"scriptPubKey":"ABT520jaTeo9UwToxlFs0inyCgGImQ==","toAddress":"tb1ql8d53kjdag74xp8gcegke53f7g9qrzyem8ca62"},{"hash":"cb2fad88ae75fdabb2bcc131b2f4f0ff2c82af22b6dd804dc341900195fb6187","index":7,"value":24019100,"scriptPubKey":"ABTQinxwdXKs6PzsvGIQ4xwXe9+APg==","toAddress":"tb1q6z98cur4w2kw3l8vh33ppccuzaaalqp7s4plwy"}]}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment