Commit 85fcfb00 authored by zeroleak's avatar zeroleak
Browse files

new server parameter "server.rpc-client.mock-tx-broadcast" for testing purpose...

new server parameter "server.rpc-client.mock-tx-broadcast" for testing purpose (mock txs instead of broadcasting it)
parent e3f7fc2e
......@@ -39,13 +39,20 @@ UTXO for liquidities should be founded with *server.round.denomination*+*server.
server.round.anonymity-set-target = 10
server.round.anonymity-set-min = 6
server.round.anonymity-set-max = 20
server.round.anonymity-set-adjust-timeout
server.round.anonymity-set-adjust-timeout = 120
server.round.must-mix-min
server.round.liquidity-timeout
server.round.must-mix-min = 1
server.round.liquidity-timeout = 60
```
Round will start when *server.round.anonymity-set-target* (mustMix + liquidities) are registered.<br/>
If this target is not met after *server.round.anonymity-set-adjust-timeout*, it will be gradually decreased to *server.round.anonymity-set-min*.<br/>
At the beginning of the round, only mustMix can register and liquidities are placed on a waiting pool.<br/>
After *server.round.liquidity-timeout*, liquidities are added as soon as *server.round.must-mix-min* is reached, up to *server.round.anonymity-set-max* inputs (mustMix + liquidities).
### Testing
```
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.<br/>
When enabled, server will keep whirlpool txs in memory until server restart and act as if these txs are confirmed in blockchain.
......@@ -4,7 +4,11 @@ import com.samourai.wallet.bip47.BIP47Util;
import com.samourai.wallet.segwit.bech32.Bech32Util;
import com.samourai.wallet.util.FormatsUtil;
import com.samourai.whirlpool.protocol.WhirlpoolProtocol;
import com.samourai.whirlpool.server.services.BlockchainDataService;
import com.samourai.whirlpool.server.services.CryptoService;
import com.samourai.whirlpool.server.services.MockBlockchainDataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -12,8 +16,12 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import wf.bitcoin.javabitcoindrpcclient.BitcoinJSONRPCClient;
import java.lang.invoke.MethodHandles;
@Configuration
public class ServicesConfig {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Autowired
private WhirlpoolServerConfig whirlpoolServerConfig;
......@@ -52,4 +60,13 @@ public class ServicesConfig {
BIP47Util bip47Util() {
return BIP47Util.getInstance();
}
@Bean
public BlockchainDataService blockchainDataService(BitcoinJSONRPCClient rpcClient, CryptoService cryptoService, Bech32Util bech32Util, WhirlpoolServerConfig whirlpoolServerConfig) {
if (whirlpoolServerConfig.getRpcClient().isMockTxBroadcast()) {
log.warn("server.rpc-client.mock-tx-broadcast=TRUE, tx WON'T be broadcasted by server");
return new MockBlockchainDataService(rpcClient, cryptoService, bech32Util, whirlpoolServerConfig);
}
return new BlockchainDataService(rpcClient, whirlpoolServerConfig);
}
}
......@@ -242,6 +242,7 @@ public class WhirlpoolServerConfig {
@NotBlank
private String user;
private String password;
private boolean mockTxBroadcast;
public String getProtocol() {
return protocol;
......@@ -282,6 +283,14 @@ public class WhirlpoolServerConfig {
public void setPassword(String password) {
this.password = password;
}
public boolean isMockTxBroadcast() {
return mockTxBroadcast;
}
public void setMockTxBroadcast(boolean mockTxBroadcast) {
this.mockTxBroadcast = mockTxBroadcast;
}
}
public static class SamouraiFeeConfig {
......
......@@ -12,6 +12,7 @@ server.rpc-client.port = 18332
server.rpc-client.host = CONFIGURE-ME
server.rpc-client.user = CONFIGURE-ME
server.rpc-client.password = CONFIGURE-ME
server.rpc-client.mock-tx-broadcast = true
server.register-input.min-confirmations = 1
......
package com.samourai.whirlpool.server.config;
import com.samourai.wallet.segwit.bech32.Bech32Util;
import com.samourai.whirlpool.server.services.BlockchainDataService;
import com.samourai.whirlpool.server.services.CryptoService;
import com.samourai.whirlpool.server.services.TestBlockchainDataService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import wf.bitcoin.javabitcoindrpcclient.BitcoinJSONRPCClient;
@Configuration
public class TestServicesConfig extends ServicesConfig {
@Bean
public BlockchainDataService blockchainDataService(BitcoinJSONRPCClient rpcClient, CryptoService cryptoService, Bech32Util bech32Util, WhirlpoolServerConfig whirlpoolServerConfig) {
return new TestBlockchainDataService(rpcClient, cryptoService, bech32Util, whirlpoolServerConfig);
}
}
......@@ -76,7 +76,7 @@ public abstract class AbstractIntegrationTest {
dbService.__reset();
roundService.__nextRound();
roundService.__setUseDeterministPaymentCodeMatching(true);
((TestBlockchainDataService)blockchainDataService).resetMock();
((MockBlockchainDataService)blockchainDataService).resetMock();
roundLimitsManager = roundService.__getRoundLimitsManager();
}
......
package com.samourai.whirlpool.server.services;
import com.samourai.wallet.segwit.bech32.Bech32Util;
import com.samourai.whirlpool.server.beans.RpcIn;
import com.samourai.whirlpool.server.beans.RpcOut;
import com.samourai.whirlpool.server.beans.RpcTransaction;
import com.samourai.whirlpool.server.config.WhirlpoolServerConfig;
import org.bitcoinj.core.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import wf.bitcoin.javabitcoindrpcclient.BitcoinJSONRPCClient;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Service
public class TestBlockchainDataService extends BlockchainDataService {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private CryptoService cryptoService;
private Bech32Util bech32Util;
private Map<String,RpcTransaction> mockTransactions;
public TestBlockchainDataService(BitcoinJSONRPCClient rpcClient, CryptoService cryptoService, Bech32Util bech32Util, WhirlpoolServerConfig whirlpoolServerConfig) {
super(rpcClient, whirlpoolServerConfig);
this.cryptoService = cryptoService;
this.bech32Util = bech32Util;
this.mockTransactions = new HashMap<>();
}
@Override
public RpcTransaction getRpcTransaction(String hash) {
RpcTransaction rpcTransaction = mockTransactions.get(hash);
if (rpcTransaction != null) {
return rpcTransaction;
}
return super.getRpcTransaction(hash);
}
@Override
public void broadcastTransaction(Transaction tx) throws Exception {
// mock result TX to simulate broadcast
int confirmations = 3;
RpcTransaction rpcTransaction = newRpcTransaction(tx, confirmations);
mock(rpcTransaction);
}
public void mock(RpcTransaction rpcTransaction) {
log.info("mock tx: " + rpcTransaction.getHash());
this.mockTransactions.put(rpcTransaction.getHash(), rpcTransaction);
}
public void mock(Transaction tx, int nbConfirmations) throws Exception {
RpcTransaction rpcTransaction = newRpcTransaction(tx, nbConfirmations);
mock(rpcTransaction);
}
public void resetMock() {
this.mockTransactions = new HashMap<>();
}
private RpcTransaction newRpcTransaction(Transaction tx, int nbConfirmations) throws Exception {
NetworkParameters params = cryptoService.getNetworkParameters();
RpcTransaction rpcTransaction = new RpcTransaction(tx.getHashAsString(), nbConfirmations);
for (TransactionInput in : tx.getInputs()) {
TransactionOutPoint outPoint = in.getOutpoint();
RpcOut fromOut = new RpcOut(outPoint.getIndex(), outPoint.getValue().getValue(), null, null); // TODO toAdresses & scriptPubKey & manque hash de l'outpoint pour pouvoir en faire qqch à la verif des inputs en chaine?
RpcIn rpcIn = new RpcIn(fromOut, rpcTransaction);
rpcTransaction.addRpcIn(rpcIn);
}
for (TransactionOutput out : tx.getOutputs()) {
String toAddressBech32 = bech32Util.getAddressFromScript(out.getScriptPubKey(), params);
RpcOut rpcOut = new RpcOut(out.getIndex(), out.getValue().getValue(), out.getScriptPubKey().getProgram(), Arrays.asList(toAddressBech32));
rpcTransaction.addRpcOut(rpcOut);
}
return rpcTransaction;
}
}
......@@ -10,7 +10,7 @@ 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.TestBlockchainDataService;
import com.samourai.whirlpool.server.services.MockBlockchainDataService;
import org.bitcoinj.core.*;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.MnemonicCode;
......@@ -121,10 +121,10 @@ public class TestUtils {
}
// mock tx
((TestBlockchainDataService)blockchainDataService).mock(transaction, nbConfirmations);
((MockBlockchainDataService)blockchainDataService).mock(transaction, nbConfirmations);
// verify mock
RpcTransaction rpcTransaction = ((TestBlockchainDataService) blockchainDataService).getRpcTransaction(transaction.getHashAsString());
RpcTransaction rpcTransaction = ((MockBlockchainDataService) blockchainDataService).getRpcTransaction(transaction.getHashAsString());
RpcOut rpcOut = Utils.findTxOutput(rpcTransaction, utxoIndex);
Assert.assertEquals(addressBech32, bech32Util.getAddressFromScript(new Script(rpcOut.getScriptPubKey()), params));
......
# mock tx broadcast for tests
server.rpc-client.mock-tx-broadcast = true
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