Commit 8665ae9a authored by zeroleak's avatar zeroleak
Browse files

new min-confirmations settings per input type:

- server.register-input.min-confirmations-must-mix = 1
- server.register-input.min-confirmations-liquidity = 1
parent 57222b45
......@@ -38,6 +38,12 @@ UTXO should be founded with:<br/>
for mustMix: (*server.mix.denomination* + *server.mix.miner-fee-min*) to (*server.mix.denomination* + *server.mix.miner-fee-max*)<br/>
for liquidities: (*server.mix.denomination*) to (*server.mix.denomination* + *server.mix.miner-fee-max*)
### UTXO confirmations
```
server.register-input.min-confirmations-must-mix: minimum confirmations for mustMix inputs
server.register-input.min-confirmations-liquidity: minimum confirmations for liquidity inputs
```
### Mix limits
```
server.mix.anonymity-set-target = 10
......
......@@ -111,14 +111,23 @@ public class WhirlpoolServerConfig {
}
public static class RegisterInputConfig {
private int minConfirmations;
private int minConfirmationsMustMix;
private int minConfirmationsLiquidity;
public int getMinConfirmations() {
return minConfirmations;
public int getMinConfirmationsMustMix() {
return minConfirmationsMustMix;
}
public void setMinConfirmations(int minConfirmations) {
this.minConfirmations = minConfirmations;
public void setMinConfirmationsMustMix(int minConfirmationsMustMix) {
this.minConfirmationsMustMix = minConfirmationsMustMix;
}
public int getMinConfirmationsLiquidity() {
return minConfirmationsLiquidity;
}
public void setMinConfirmationsLiquidity(int minConfirmationsLiquidity) {
this.minConfirmationsLiquidity = minConfirmationsLiquidity;
}
}
......
......@@ -5,6 +5,7 @@ import com.samourai.whirlpool.server.beans.rpc.RpcOutWithTx;
import com.samourai.whirlpool.server.beans.rpc.RpcOut;
import com.samourai.whirlpool.server.beans.rpc.RpcTransaction;
import com.samourai.whirlpool.server.beans.TxOutPoint;
import com.samourai.whirlpool.server.config.WhirlpoolServerConfig;
import com.samourai.whirlpool.server.exceptions.IllegalInputException;
import com.samourai.whirlpool.server.exceptions.UnconfirmedInputException;
import org.slf4j.Logger;
......@@ -19,14 +20,18 @@ public class BlockchainService {
private CryptoService cryptoService;
private BlockchainDataService blockchainDataService;
private Tx0Service tx0Service;
private WhirlpoolServerConfig whirlpoolServerConfig;
public BlockchainService(CryptoService cryptoService, BlockchainDataService blockchainDataService, Tx0Service tx0Service) {
public BlockchainService(CryptoService cryptoService, BlockchainDataService blockchainDataService, Tx0Service tx0Service, WhirlpoolServerConfig whirlpoolServerConfig) {
this.cryptoService = cryptoService;
this.blockchainDataService = blockchainDataService;
this.tx0Service = tx0Service;
this.whirlpoolServerConfig = whirlpoolServerConfig;
}
public TxOutPoint validateAndGetPremixInput(String utxoHash, long utxoIndex, byte[] pubkeyHex, int minConfirmations, long samouraiFeesMin, boolean liquidity) throws IllegalInputException, UnconfirmedInputException {
public TxOutPoint validateAndGetPremixInput(String utxoHash, long utxoIndex, byte[] pubkeyHex, boolean liquidity) throws IllegalInputException, UnconfirmedInputException {
long samouraiFeesMin = whirlpoolServerConfig.getSamouraiFees().getAmount();
RpcOutWithTx rpcOutWithTx = blockchainDataService.getRpcOutWithTx(utxoHash, utxoIndex).orElseThrow(
() -> new IllegalInputException("UTXO not found: " + utxoHash + "-" + utxoIndex)
);
......@@ -36,7 +41,7 @@ public class BlockchainService {
checkPubkey(rpcOut, pubkeyHex);
// verify confirmations
checkInputConfirmations(rpcOutWithTx.getTx(), minConfirmations);
checkInputConfirmations(rpcOutWithTx.getTx(), liquidity);
// verify input comes from a valid tx0 (or from a valid mix)
if (samouraiFeesMin > 0) {
......@@ -64,10 +69,22 @@ public class BlockchainService {
}
}
protected void checkInputConfirmations(RpcTransaction tx, int minConfirmations) throws UnconfirmedInputException {
protected void checkInputConfirmations(RpcTransaction tx, boolean liquidity) throws UnconfirmedInputException {
int inputConfirmations = tx.getConfirmations();
if (inputConfirmations < minConfirmations) {
throw new UnconfirmedInputException("Input needs at least "+minConfirmations+" confirmations");
if (liquidity) {
// liquidity
int minConfirmationsMix = whirlpoolServerConfig.getRegisterInput().getMinConfirmationsLiquidity();
if (inputConfirmations < minConfirmationsMix) {
log.warn("input rejected: liquidity needs at least " + minConfirmationsMix + " confirmations: " + tx.getTxid());
throw new UnconfirmedInputException("Input needs at least " + minConfirmationsMix + " confirmations");
}
} else {
// mustMix
int minConfirmationsTx0 = whirlpoolServerConfig.getRegisterInput().getMinConfirmationsMustMix();
if (inputConfirmations < minConfirmationsTx0) {
log.warn("input rejected: mustMix needs at least " + minConfirmationsTx0 + " confirmations: " + tx.getTxid());
throw new UnconfirmedInputException("Input needs at least " + minConfirmationsTx0 + " confirmations");
}
}
}
}
......@@ -8,8 +8,11 @@ import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.signers.PSSSigner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.lang.invoke.MethodHandles;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.SignatureException;
......@@ -17,6 +20,8 @@ import java.security.spec.RSAPublicKeySpec;
@Service
public class CryptoService {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private AsymmetricCipherKeyPair keyPair;
private PublicKey publicKey;
private NetworkParameters networkParameters;
......@@ -42,11 +47,13 @@ public class CryptoService {
try {
ecKeyFromPubkey = ECKey.fromPublicOnly(pubkeyHex);
} catch (Exception e) {
log.error("verifyMessageSignature: couldn't extract eckey", e);
return false;
}
try {
ecKeyFromPubkey.verifyMessage(message, signatureBase64);
} catch (SignatureException e) {
log.error("verifyMessageSignature: invalid signature", e);
return false;
}
return true;
......
......@@ -45,9 +45,7 @@ public class RegisterInputService {
}
// validate input
long samouraiFees = whirlpoolServerConfig.getSamouraiFees().getAmount();
int inputMinConfirmations = whirlpoolServerConfig.getRegisterInput().getMinConfirmations();
TxOutPoint txOutPoint = blockchainService.validateAndGetPremixInput(utxoHash, utxoIndex, pubkey, inputMinConfirmations, samouraiFees, liquidity);
TxOutPoint txOutPoint = blockchainService.validateAndGetPremixInput(utxoHash, utxoIndex, pubkey, liquidity);
// verify signature
checkInputSignature(mixId, pubkey, signature);
......
......@@ -22,7 +22,8 @@ server.rpc-client.user = CONFIGURE-ME
server.rpc-client.password = CONFIGURE-ME
server.rpc-client.mock-tx-broadcast = false
server.register-input.min-confirmations = 1
server.register-input.min-confirmations-must-mix = 1
server.register-input.min-confirmations-liquidity = 1
# 240s = 4min
server.register-output.timeout = 240
......
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