mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 15:00:30 +01:00
Adjust code to work with BitcoinJ 0.14.4.1
This commit is contained in:
parent
9ab7cff156
commit
b805a795dd
32 changed files with 227 additions and 352 deletions
|
@ -395,13 +395,6 @@ public class Utilities {
|
|||
Thread.currentThread().setName(name + "-" + new Random().nextInt(10000));
|
||||
}
|
||||
|
||||
public static void overwriteWithRandomBytes(byte[] bytes) {
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
bytes[i] = (byte) random.nextInt(Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDirectory(String path) {
|
||||
return new File(path).isDirectory();
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bitcoinj.core.Wallet;
|
||||
import org.bitcoinj.crypto.DeterministicKey;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
|
@ -110,7 +110,9 @@ public class SeedPeersSocks5Dns implements PeerDiscovery {
|
|||
* Returns an array containing all the Bitcoin nodes within the list.
|
||||
*/
|
||||
@Override
|
||||
public InetSocketAddress[] getPeers(long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
public InetSocketAddress[] getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
if (services != 0)
|
||||
throw new PeerDiscoveryException("DNS seeds cannot filter by services: " + services);
|
||||
try {
|
||||
return allPeers();
|
||||
} catch (UnknownHostException e) {
|
||||
|
|
|
@ -22,11 +22,7 @@ import org.bitcoinj.crypto.ChildNumber;
|
|||
import org.bitcoinj.crypto.DeterministicKey;
|
||||
import org.bitcoinj.crypto.HDUtils;
|
||||
import org.bitcoinj.crypto.KeyCrypter;
|
||||
import org.bitcoinj.store.UnreadableWalletException;
|
||||
import org.bitcoinj.wallet.DeterministicKeyChain;
|
||||
import org.bitcoinj.wallet.DeterministicSeed;
|
||||
import org.bitcoinj.wallet.KeyChainFactory;
|
||||
import org.bitcoinj.wallet.Protos;
|
||||
import org.bitcoinj.wallet.*;
|
||||
|
||||
class BisqKeyChainFactory implements KeyChainFactory {
|
||||
private final boolean useBitcoinDeterministicKeyChain;
|
||||
|
|
|
@ -25,23 +25,20 @@ import java.security.SecureRandom;
|
|||
|
||||
class BisqKeyChainGroup extends KeyChainGroup {
|
||||
private final boolean useBitcoinDeterministicKeyChain;
|
||||
private final int lookaheadSize;
|
||||
|
||||
public boolean isUseBitcoinDeterministicKeyChain() {
|
||||
return useBitcoinDeterministicKeyChain;
|
||||
}
|
||||
|
||||
public BisqKeyChainGroup(NetworkParameters params, boolean useBitcoinDeterministicKeyChain, int lookaheadSize) {
|
||||
public BisqKeyChainGroup(NetworkParameters params, boolean useBitcoinDeterministicKeyChain) {
|
||||
super(params);
|
||||
this.useBitcoinDeterministicKeyChain = useBitcoinDeterministicKeyChain;
|
||||
this.lookaheadSize = lookaheadSize;
|
||||
}
|
||||
|
||||
public BisqKeyChainGroup(NetworkParameters params, DeterministicKeyChain chain, boolean useBitcoinDeterministicKeyChain, int lookaheadSize) {
|
||||
public BisqKeyChainGroup(NetworkParameters params, DeterministicKeyChain chain, boolean useBitcoinDeterministicKeyChain) {
|
||||
super(params, chain);
|
||||
|
||||
this.useBitcoinDeterministicKeyChain = useBitcoinDeterministicKeyChain;
|
||||
this.lookaheadSize = lookaheadSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,7 +49,6 @@ class BisqKeyChainGroup extends KeyChainGroup {
|
|||
@Override
|
||||
public void createAndActivateNewHDChain() {
|
||||
DeterministicKeyChain chain = useBitcoinDeterministicKeyChain ? new BtcDeterministicKeyChain(new SecureRandom()) : new BsqDeterministicKeyChain(new SecureRandom());
|
||||
chain.setLookaheadSize(lookaheadSize);
|
||||
addAndActivateHDChain(chain);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.bitcoinj.wallet.DeterministicKeyChain;
|
|||
import org.bitcoinj.wallet.DeterministicSeed;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
|
@ -33,8 +34,7 @@ class BsqDeterministicKeyChain extends DeterministicKeyChain {
|
|||
|
||||
// See https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
|
||||
// https://github.com/satoshilabs/slips/blob/master/slip-0044.md
|
||||
// We use 142 (0x8000008E) as coin_type for BSQ
|
||||
// TODO register
|
||||
// We have registered 142 (0x8000008E) as coin_type for BSQ
|
||||
public static final ImmutableList<ChildNumber> BIP44_BSQ_ACCOUNT_PATH = ImmutableList.of(
|
||||
new ChildNumber(44, true),
|
||||
new ChildNumber(142, true),
|
||||
|
@ -56,6 +56,20 @@ class BsqDeterministicKeyChain extends DeterministicKeyChain {
|
|||
super(seed);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DeterministicKeyChain toEncrypted(KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
return new BsqDeterministicKeyChain(keyCrypter, aesKey, this);
|
||||
}
|
||||
|
||||
protected DeterministicKeyChain makeKeyChainFromSeed(DeterministicSeed seed) {
|
||||
return new BsqDeterministicKeyChain(seed);
|
||||
}
|
||||
|
||||
protected BsqDeterministicKeyChain(KeyCrypter crypter, KeyParameter aesKey, DeterministicKeyChain chain) {
|
||||
super(crypter, aesKey, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ImmutableList<ChildNumber> getAccountPath() {
|
||||
return BIP44_BSQ_ACCOUNT_PATH;
|
||||
|
|
|
@ -17,71 +17,13 @@
|
|||
|
||||
package io.bisq.core.btc.wallet;
|
||||
|
||||
import org.bitcoinj.core.*;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.wallet.KeyChainGroup;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
|
||||
public class BsqWallet extends Wallet {
|
||||
private static final Logger log = LoggerFactory.getLogger(BsqWallet.class);
|
||||
|
||||
public BsqWallet(NetworkParameters params, KeyChainGroup keyChainGroup) {
|
||||
super(params, keyChainGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the spendable candidates from the {@link UTXOProvider} based on keys that the wallet contains.
|
||||
*
|
||||
* @return The list of candidates.
|
||||
*/
|
||||
@Override
|
||||
protected List<TransactionOutput> calculateAllSpendCandidatesFromUTXOProvider(boolean excludeImmatureCoinbases) {
|
||||
checkState(lock.isHeldByCurrentThread());
|
||||
UTXOProvider utxoProvider = checkNotNull(vUTXOProvider, "No UTXO provider has been set");
|
||||
// We might get duplicate outputs from the provider and from our pending tx outputs
|
||||
// To avoid duplicate entries we use a set.
|
||||
Set<TransactionOutput> candidates = new HashSet<>();
|
||||
try {
|
||||
int chainHeight = utxoProvider.getChainHeadHeight();
|
||||
for (UTXO output : getStoredOutputsFromUTXOProvider()) {
|
||||
boolean coinbase = output.isCoinbase();
|
||||
int depth = chainHeight - output.getHeight() + 1; // the current depth of the output (1 = same as head).
|
||||
// Do not try and spend coinbases that were mined too recently, the protocol forbids it.
|
||||
if (!excludeImmatureCoinbases || !coinbase || depth >= params.getSpendableCoinbaseDepth()) {
|
||||
candidates.add(new FreeStandingTransactionOutput(params, output, chainHeight));
|
||||
}
|
||||
}
|
||||
} catch (UTXOProviderException e) {
|
||||
throw new RuntimeException("UTXO provider error", e);
|
||||
}
|
||||
// We need to handle the pending transactions that we know about.
|
||||
for (Transaction tx : pending.values()) {
|
||||
// Remove the spent outputs.
|
||||
for (TransactionInput input : tx.getInputs()) {
|
||||
TransactionOutput connectedOutput = input.getConnectedOutput();
|
||||
if (connectedOutput != null && connectedOutput.isMine(this)) {
|
||||
candidates.remove(connectedOutput);
|
||||
}
|
||||
}
|
||||
// Add change outputs. Do not try and spend coinbases that were mined too recently, the protocol forbids it.
|
||||
|
||||
// We might get outputs from pending tx which we already got form the UTXP provider.
|
||||
// As we use a set it will not lead to duplicate entries.
|
||||
if (!excludeImmatureCoinbases || tx.isMature()) {
|
||||
candidates.addAll(tx.getOutputs().stream()
|
||||
.filter(output -> output.isAvailableForSpending() && output.isMine(this))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(candidates);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.bitcoinj.core.*;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.wallet.CoinSelection;
|
||||
import org.bitcoinj.wallet.SendRequest;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.bitcoinj.wallet.listeners.AbstractWalletEventListener;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.HashSet;
|
||||
|
@ -275,9 +278,10 @@ public class BsqWalletService extends WalletService {
|
|||
"The amount is too low (dust limit).");
|
||||
tx.addOutput(receiverAmount, new Address(params, receiverAddress));
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
SendRequest sendRequest = SendRequest.forTx(tx);
|
||||
sendRequest.fee = Coin.ZERO;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
sendRequest.shuffleOutputs = false;
|
||||
sendRequest.signInputs = false;
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting;
|
|||
import org.bitcoinj.core.*;
|
||||
import org.bitcoinj.params.RegTestParams;
|
||||
import org.bitcoinj.wallet.CoinSelection;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.bitcoinj.wallet.DeterministicKeyChain;
|
|||
import org.bitcoinj.wallet.DeterministicSeed;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
|
@ -56,6 +57,19 @@ class BtcDeterministicKeyChain extends DeterministicKeyChain {
|
|||
super(seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeterministicKeyChain toEncrypted(KeyCrypter keyCrypter, KeyParameter aesKey) {
|
||||
return new BtcDeterministicKeyChain(keyCrypter, aesKey, this);
|
||||
}
|
||||
|
||||
protected DeterministicKeyChain makeKeyChainFromSeed(DeterministicSeed seed) {
|
||||
return new BtcDeterministicKeyChain(seed);
|
||||
}
|
||||
|
||||
protected BtcDeterministicKeyChain(KeyCrypter crypter, KeyParameter aesKey, DeterministicKeyChain chain) {
|
||||
super(crypter, aesKey, chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ImmutableList<ChildNumber> getAccountPath() {
|
||||
return BIP44_BTC_ACCOUNT_PATH;
|
||||
|
|
|
@ -31,6 +31,8 @@ import org.bitcoinj.core.*;
|
|||
import org.bitcoinj.crypto.DeterministicKey;
|
||||
import org.bitcoinj.crypto.KeyCrypterScrypt;
|
||||
import org.bitcoinj.script.ScriptBuilder;
|
||||
import org.bitcoinj.wallet.SendRequest;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -201,14 +203,16 @@ public class BtcWalletService extends WalletService {
|
|||
tx.addOutput(forcedChangeValue, changeAddress);
|
||||
}
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
SendRequest sendRequest = SendRequest.forTx(tx);
|
||||
sendRequest.shuffleOutputs = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
// signInputs needs to be false as it would try to sign all inputs (BSQ inputs are not in this wallet)
|
||||
sendRequest.signInputs = false;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
|
||||
sendRequest.fee = txFeePerByte.multiply(txSizeWithUnsignedInputs + sigSizePerInput * numInputs);
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
|
||||
sendRequest.coinSelector = coinSelector;
|
||||
sendRequest.changeAddress = changeAddress;
|
||||
wallet.completeTx(sendRequest);
|
||||
|
@ -461,7 +465,7 @@ public class BtcWalletService extends WalletService {
|
|||
int counter = 0;
|
||||
int txSize = 0;
|
||||
Transaction tx;
|
||||
Wallet.SendRequest sendRequest;
|
||||
SendRequest sendRequest;
|
||||
Coin txFeeForWithdrawalPerByte = getTxFeeForWithdrawalPerByte();
|
||||
do {
|
||||
counter++;
|
||||
|
@ -472,9 +476,10 @@ public class BtcWalletService extends WalletService {
|
|||
newTransaction.clearOutputs();
|
||||
newTransaction.addOutput(amount.subtract(fee), toAddress);
|
||||
|
||||
sendRequest = Wallet.SendRequest.forTx(newTransaction);
|
||||
sendRequest = SendRequest.forTx(newTransaction);
|
||||
sendRequest.fee = fee;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
sendRequest.coinSelector = new BtcCoinSelector(toAddress);
|
||||
sendRequest.changeAddress = toAddress;
|
||||
|
@ -491,9 +496,10 @@ public class BtcWalletService extends WalletService {
|
|||
|
||||
Wallet.SendResult sendResult = null;
|
||||
try {
|
||||
sendRequest = Wallet.SendRequest.forTx(newTransaction);
|
||||
sendRequest = SendRequest.forTx(newTransaction);
|
||||
sendRequest.fee = fee;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
sendRequest.coinSelector = new BtcCoinSelector(toAddress);
|
||||
sendRequest.changeAddress = toAddress;
|
||||
|
@ -506,9 +512,10 @@ public class BtcWalletService extends WalletService {
|
|||
newTransaction.clearOutputs();
|
||||
newTransaction.addOutput(amount, toAddress);
|
||||
|
||||
sendRequest = Wallet.SendRequest.forTx(newTransaction);
|
||||
sendRequest = SendRequest.forTx(newTransaction);
|
||||
sendRequest.fee = fee;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
sendRequest.coinSelector = new BtcCoinSelector(toAddress, false);
|
||||
sendRequest.changeAddress = toAddress;
|
||||
|
@ -584,7 +591,7 @@ public class BtcWalletService extends WalletService {
|
|||
if (fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0)
|
||||
fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||
|
||||
Wallet.SendRequest sendRequest = getSendRequest(fromAddress, toAddress, amount, fee, aesKey, context);
|
||||
SendRequest sendRequest = getSendRequest(fromAddress, toAddress, amount, fee, aesKey, context);
|
||||
wallet.completeTx(sendRequest);
|
||||
tx = sendRequest.tx;
|
||||
txSize = tx.bitcoinSerialize().length;
|
||||
|
@ -634,7 +641,7 @@ public class BtcWalletService extends WalletService {
|
|||
fee = txFeeForWithdrawalPerByte.multiply(txSize);
|
||||
if (fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0)
|
||||
fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||
Wallet.SendRequest sendRequest = getSendRequestForMultipleAddresses(fromAddresses, toAddress, amount, fee, null, aesKey);
|
||||
SendRequest sendRequest = getSendRequestForMultipleAddresses(fromAddresses, toAddress, amount, fee, null, aesKey);
|
||||
wallet.completeTx(sendRequest);
|
||||
tx = sendRequest.tx;
|
||||
txSize = tx.bitcoinSerialize().length;
|
||||
|
@ -664,7 +671,7 @@ public class BtcWalletService extends WalletService {
|
|||
AddressEntry.Context context,
|
||||
FutureCallback<Transaction> callback) throws AddressFormatException,
|
||||
AddressEntryException, InsufficientMoneyException {
|
||||
Wallet.SendRequest sendRequest = getSendRequest(fromAddress, toAddress, receiverAmount, fee, aesKey, context);
|
||||
SendRequest sendRequest = getSendRequest(fromAddress, toAddress, receiverAmount, fee, aesKey, context);
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
|
||||
|
@ -681,7 +688,7 @@ public class BtcWalletService extends WalletService {
|
|||
FutureCallback<Transaction> callback) throws AddressFormatException,
|
||||
AddressEntryException, InsufficientMoneyException {
|
||||
|
||||
Wallet.SendRequest request = getSendRequestForMultipleAddresses(fromAddresses, toAddress, receiverAmount, fee, changeAddress, aesKey);
|
||||
SendRequest request = getSendRequestForMultipleAddresses(fromAddresses, toAddress, receiverAmount, fee, changeAddress, aesKey);
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(request);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
|
||||
|
@ -689,21 +696,22 @@ public class BtcWalletService extends WalletService {
|
|||
return sendResult.tx.getHashAsString();
|
||||
}
|
||||
|
||||
private Wallet.SendRequest getSendRequest(String fromAddress,
|
||||
String toAddress,
|
||||
Coin amount,
|
||||
Coin fee,
|
||||
@Nullable KeyParameter aesKey,
|
||||
AddressEntry.Context context) throws AddressFormatException,
|
||||
private SendRequest getSendRequest(String fromAddress,
|
||||
String toAddress,
|
||||
Coin amount,
|
||||
Coin fee,
|
||||
@Nullable KeyParameter aesKey,
|
||||
AddressEntry.Context context) throws AddressFormatException,
|
||||
AddressEntryException {
|
||||
Transaction tx = new Transaction(params);
|
||||
Preconditions.checkArgument(Restrictions.isAboveDust(amount, fee),
|
||||
"The amount is too low (dust limit).");
|
||||
tx.addOutput(amount.subtract(fee), new Address(params, toAddress));
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
SendRequest sendRequest = SendRequest.forTx(tx);
|
||||
sendRequest.fee = fee;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
sendRequest.shuffleOutputs = false;
|
||||
Optional<AddressEntry> addressEntry = findAddressEntry(fromAddress, context);
|
||||
|
@ -717,21 +725,22 @@ public class BtcWalletService extends WalletService {
|
|||
return sendRequest;
|
||||
}
|
||||
|
||||
private Wallet.SendRequest getSendRequestForMultipleAddresses(Set<String> fromAddresses,
|
||||
String toAddress,
|
||||
Coin amount,
|
||||
Coin fee,
|
||||
@Nullable String changeAddress,
|
||||
@Nullable KeyParameter aesKey) throws
|
||||
private SendRequest getSendRequestForMultipleAddresses(Set<String> fromAddresses,
|
||||
String toAddress,
|
||||
Coin amount,
|
||||
Coin fee,
|
||||
@Nullable String changeAddress,
|
||||
@Nullable KeyParameter aesKey) throws
|
||||
AddressFormatException, AddressEntryException {
|
||||
Transaction tx = new Transaction(params);
|
||||
checkArgument(Restrictions.isAboveDust(amount),
|
||||
"The amount is too low (dust limit).");
|
||||
tx.addOutput(amount.subtract(fee), new Address(params, toAddress));
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
SendRequest sendRequest = SendRequest.forTx(tx);
|
||||
sendRequest.fee = fee;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
sendRequest.shuffleOutputs = false;
|
||||
Set<AddressEntry> addressEntries = fromAddresses.stream()
|
||||
|
|
|
@ -22,7 +22,6 @@ import com.google.common.util.concurrent.FutureCallback;
|
|||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import io.bisq.common.app.Log;
|
||||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.core.btc.AddressEntry;
|
||||
import io.bisq.core.btc.InsufficientFundsException;
|
||||
import io.bisq.core.btc.data.InputsAndChangeOutput;
|
||||
|
@ -37,6 +36,8 @@ import org.bitcoinj.crypto.DeterministicKey;
|
|||
import org.bitcoinj.crypto.TransactionSignature;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.script.ScriptBuilder;
|
||||
import org.bitcoinj.wallet.SendRequest;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -125,10 +126,6 @@ public class TradeWalletService {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setAesKey(@Nullable KeyParameter newAesKey) {
|
||||
// Overwrite first with random bytes before setting to null
|
||||
if (newAesKey == null && this.aesKey != null)
|
||||
Utilities.overwriteWithRandomBytes(this.aesKey.getKey());
|
||||
|
||||
this.aesKey = newAesKey;
|
||||
}
|
||||
|
||||
|
@ -176,7 +173,7 @@ public class TradeWalletService {
|
|||
// we allow spending of unconfirmed tx (double spend risk is low and usability would suffer if we need to
|
||||
// wait for 1 confirmation)
|
||||
// In case of double spend we will detect later in the trade process and use a ban score to penalize bad behaviour (not impl. yet)
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tradingFeeTx);
|
||||
SendRequest sendRequest = SendRequest.forTx(tradingFeeTx);
|
||||
sendRequest.shuffleOutputs = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
if (useSavingsWallet)
|
||||
|
@ -184,8 +181,10 @@ public class TradeWalletService {
|
|||
else
|
||||
sendRequest.coinSelector = new BtcCoinSelector(fundingAddress);
|
||||
// We use a fixed fee
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
|
||||
sendRequest.fee = txFee;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
|
||||
// Change is optional in case of overpay or use of funds from savings wallet
|
||||
sendRequest.changeAddress = changeAddress;
|
||||
|
@ -243,7 +242,7 @@ public class TradeWalletService {
|
|||
// In case of double spend we will detect later in the trade process and use a ban score to penalize bad behaviour (not impl. yet)
|
||||
|
||||
// WalletService.printTx("preparedBsqTx", preparedBsqTx);
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(preparedBsqTx);
|
||||
SendRequest sendRequest = SendRequest.forTx(preparedBsqTx);
|
||||
sendRequest.shuffleOutputs = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
if (useSavingsWallet)
|
||||
|
@ -251,8 +250,10 @@ public class TradeWalletService {
|
|||
else
|
||||
sendRequest.coinSelector = new BtcCoinSelector(fundingAddress);
|
||||
// We use a fixed fee
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.fee = txFee;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
|
||||
sendRequest.signInputs = false;
|
||||
|
||||
// Change is optional in case of overpay or use of funds from savings wallet
|
||||
|
@ -1166,12 +1167,13 @@ public class TradeWalletService {
|
|||
private void addAvailableInputsAndChangeOutputs(Transaction transaction, Address address, Address changeAddress, Coin txFee) throws WalletException {
|
||||
try {
|
||||
// Lets let the framework do the work to find the right inputs
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(transaction);
|
||||
SendRequest sendRequest = SendRequest.forTx(transaction);
|
||||
sendRequest.shuffleOutputs = false;
|
||||
sendRequest.aesKey = aesKey;
|
||||
// We use a fixed fee
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.fee = txFee;
|
||||
sendRequest.feePerKb = Coin.ZERO;
|
||||
sendRequest.ensureMinRequiredFee = false;
|
||||
// we allow spending of unconfirmed tx (double spend risk is low and usability would suffer if we need to wait for 1 confirmation)
|
||||
sendRequest.coinSelector = new BtcCoinSelector(address);
|
||||
// We use always the same address in a trade for all transactions
|
||||
|
|
|
@ -24,6 +24,8 @@ import com.google.common.util.concurrent.Futures;
|
|||
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
|
||||
import io.bisq.core.btc.ProxySocketFactory;
|
||||
import org.bitcoinj.core.*;
|
||||
import org.bitcoinj.core.listeners.DownloadProgressTracker;
|
||||
import org.bitcoinj.core.listeners.PeerDataEventListener;
|
||||
import org.bitcoinj.net.BlockingClientManager;
|
||||
import org.bitcoinj.net.discovery.DnsDiscovery;
|
||||
import org.bitcoinj.net.discovery.PeerDiscovery;
|
||||
|
@ -33,11 +35,7 @@ import org.bitcoinj.params.TestNet3Params;
|
|||
import org.bitcoinj.store.BlockStore;
|
||||
import org.bitcoinj.store.BlockStoreException;
|
||||
import org.bitcoinj.store.SPVBlockStore;
|
||||
import org.bitcoinj.store.WalletProtobufSerializer;
|
||||
import org.bitcoinj.wallet.DeterministicKeyChain;
|
||||
import org.bitcoinj.wallet.DeterministicSeed;
|
||||
import org.bitcoinj.wallet.KeyChainGroup;
|
||||
import org.bitcoinj.wallet.Protos;
|
||||
import org.bitcoinj.wallet.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -91,15 +89,13 @@ public class WalletConfig extends AbstractIdleService {
|
|||
private volatile File vBsqWalletFile;
|
||||
@Nullable
|
||||
private DeterministicSeed seed;
|
||||
private int btcWalletLookaheadSize = -1;
|
||||
private int bsqWalletLookaheadSize = -1;
|
||||
|
||||
private volatile BlockChain vChain;
|
||||
private volatile BlockStore vStore;
|
||||
private volatile PeerGroup vPeerGroup;
|
||||
private boolean useAutoSave = true;
|
||||
private PeerAddress[] peerAddresses;
|
||||
private PeerEventListener downloadListener;
|
||||
private PeerDataEventListener downloadListener;
|
||||
private boolean autoStop = true;
|
||||
private InputStream checkpoints;
|
||||
private boolean blockingStartup = true;
|
||||
|
@ -108,8 +104,6 @@ public class WalletConfig extends AbstractIdleService {
|
|||
private String version;
|
||||
@Nullable
|
||||
private PeerDiscovery discovery;
|
||||
private long bloomFilterTweak = 0;
|
||||
private double bloomFilterFPRate = -1;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -226,12 +220,7 @@ public class WalletConfig extends AbstractIdleService {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If you want to learn about the sync process, you can provide a listener here. For instance, a
|
||||
* {@link org.bitcoinj.core.DownloadProgressTracker} is a good choice. This has no effect unless setBlockingStartup(false) has been called
|
||||
* too, due to some missing implementation code.
|
||||
*/
|
||||
public WalletConfig setDownloadListener(PeerEventListener listener) {
|
||||
public WalletConfig setDownloadListener(PeerDataEventListener listener) {
|
||||
this.downloadListener = listener;
|
||||
return this;
|
||||
}
|
||||
|
@ -298,26 +287,6 @@ public class WalletConfig extends AbstractIdleService {
|
|||
return this;
|
||||
}
|
||||
|
||||
public WalletConfig setBloomFilterFalsePositiveRate(double bloomFilterFPRate) {
|
||||
this.bloomFilterFPRate = bloomFilterFPRate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WalletConfig setBloomFilterTweak(long bloomFilterTweak) {
|
||||
this.bloomFilterTweak = bloomFilterTweak;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WalletConfig setBtcWalletLookaheadSize(int lookaheadSize) {
|
||||
this.btcWalletLookaheadSize = lookaheadSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public WalletConfig setBsqWalletLookaheadSize(int lookaheadSize) {
|
||||
this.bsqWalletLookaheadSize = lookaheadSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Override this to return wallet extensions if any are necessary.</p>
|
||||
* <p>
|
||||
|
@ -388,18 +357,18 @@ public class WalletConfig extends AbstractIdleService {
|
|||
boolean shouldReplayWallet = (vBtcWalletFile.exists() && !chainFileExists) || seed != null;
|
||||
BisqKeyChainGroup keyChainGroup;
|
||||
if (seed != null)
|
||||
keyChainGroup = new BisqKeyChainGroup(params, new BtcDeterministicKeyChain(seed), true, btcWalletLookaheadSize);
|
||||
keyChainGroup = new BisqKeyChainGroup(params, new BtcDeterministicKeyChain(seed), true);
|
||||
else
|
||||
keyChainGroup = new BisqKeyChainGroup(params, true, btcWalletLookaheadSize);
|
||||
vBtcWallet = createOrLoadWallet(vBtcWalletFile, shouldReplayWallet, keyChainGroup, false);
|
||||
keyChainGroup = new BisqKeyChainGroup(params, true);
|
||||
vBtcWallet = createOrLoadWallet(vBtcWalletFile, shouldReplayWallet, keyChainGroup, false, seed);
|
||||
|
||||
// BSQ walelt
|
||||
vBsqWalletFile = new File(directory, bsqWalletFileName);
|
||||
if (seed != null)
|
||||
keyChainGroup = new BisqKeyChainGroup(params, new BsqDeterministicKeyChain(seed), false, bsqWalletLookaheadSize);
|
||||
keyChainGroup = new BisqKeyChainGroup(params, new BsqDeterministicKeyChain(seed), false);
|
||||
else
|
||||
keyChainGroup = new BisqKeyChainGroup(params, new BsqDeterministicKeyChain(vBtcWallet.getKeyChainSeed()), false, bsqWalletLookaheadSize);
|
||||
vBsqWallet = createOrLoadWallet(vBsqWalletFile, shouldReplayWallet, keyChainGroup, true);
|
||||
keyChainGroup = new BisqKeyChainGroup(params, new BsqDeterministicKeyChain(vBtcWallet.getKeyChainSeed()), false);
|
||||
vBsqWallet = createOrLoadWallet(vBsqWalletFile, shouldReplayWallet, keyChainGroup, true, seed);
|
||||
|
||||
// Initiate Bitcoin network objects (block store, blockchain and peer group)
|
||||
vStore = provideBlockStore(chainFile);
|
||||
|
@ -438,12 +407,6 @@ public class WalletConfig extends AbstractIdleService {
|
|||
vChain = new BlockChain(params, vStore);
|
||||
vPeerGroup = createPeerGroup();
|
||||
|
||||
if (bloomFilterFPRate != -1)
|
||||
vPeerGroup.setBloomFilterFalsePositiveRate(bloomFilterFPRate);
|
||||
|
||||
if (bloomFilterTweak != 0)
|
||||
vPeerGroup.setBloomFilterTweak(bloomFilterTweak);
|
||||
|
||||
if (this.userAgent != null)
|
||||
vPeerGroup.setUserAgent(userAgent, version);
|
||||
|
||||
|
@ -475,7 +438,7 @@ public class WalletConfig extends AbstractIdleService {
|
|||
Futures.addCallback(vPeerGroup.startAsync(), new FutureCallback() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable Object result) {
|
||||
final PeerEventListener listener = downloadListener == null ?
|
||||
final PeerDataEventListener listener = downloadListener == null ?
|
||||
new DownloadProgressTracker() : downloadListener;
|
||||
vPeerGroup.startBlockChainDownload(listener);
|
||||
}
|
||||
|
@ -493,8 +456,11 @@ public class WalletConfig extends AbstractIdleService {
|
|||
}
|
||||
|
||||
private Wallet createOrLoadWallet(File walletFile, boolean shouldReplayWallet,
|
||||
BisqKeyChainGroup keyChainGroup, boolean isBsqWallet)
|
||||
BisqKeyChainGroup keyChainGroup, boolean isBsqWallet, DeterministicSeed seed)
|
||||
throws Exception {
|
||||
|
||||
maybeMoveOldWalletOutOfTheWay(walletFile, seed);
|
||||
|
||||
Wallet wallet;
|
||||
if (walletFile.exists()) {
|
||||
wallet = loadWallet(walletFile, shouldReplayWallet, keyChainGroup.isUseBitcoinDeterministicKeyChain());
|
||||
|
@ -509,6 +475,22 @@ public class WalletConfig extends AbstractIdleService {
|
|||
return wallet;
|
||||
}
|
||||
|
||||
private void maybeMoveOldWalletOutOfTheWay(File vWalletFile, DeterministicSeed restoreFromSeed) {
|
||||
if (restoreFromSeed == null) return;
|
||||
if (!vWalletFile.exists()) return;
|
||||
int counter = 1;
|
||||
File newName;
|
||||
do {
|
||||
newName = new File(vWalletFile.getParent(), "Backup " + counter + " for " + vWalletFile.getName());
|
||||
counter++;
|
||||
} while (newName.exists());
|
||||
log.info("Renaming old wallet file {} to {}", vWalletFile, newName);
|
||||
if (!vWalletFile.renameTo(newName)) {
|
||||
// This should not happen unless something is really messed up.
|
||||
throw new RuntimeException("Failed to rename wallet for restore");
|
||||
}
|
||||
}
|
||||
|
||||
private Wallet loadWallet(File walletFile, boolean shouldReplayWallet, boolean useBitcoinDeterministicKeyChain) throws Exception {
|
||||
Wallet wallet;
|
||||
FileInputStream walletStream = new FileInputStream(walletFile);
|
||||
|
|
|
@ -21,7 +21,6 @@ import com.google.common.util.concurrent.FutureCallback;
|
|||
import com.google.common.util.concurrent.Futures;
|
||||
import io.bisq.common.handlers.ErrorMessageHandler;
|
||||
import io.bisq.common.handlers.ResultHandler;
|
||||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.core.btc.exceptions.TransactionVerificationException;
|
||||
import io.bisq.core.btc.exceptions.WalletException;
|
||||
import io.bisq.core.btc.listeners.AddressConfidenceListener;
|
||||
|
@ -38,6 +37,8 @@ import org.bitcoinj.script.Script;
|
|||
import org.bitcoinj.signers.TransactionSigner;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.*;
|
||||
import org.bitcoinj.wallet.listeners.AbstractWalletEventListener;
|
||||
import org.bitcoinj.wallet.listeners.WalletEventListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -104,8 +105,6 @@ public abstract class WalletService {
|
|||
|
||||
void decryptWallet(@NotNull KeyParameter key) {
|
||||
wallet.decrypt(key);
|
||||
// Overwrite first with random bytes before setting to null
|
||||
Utilities.overwriteWithRandomBytes(key.getKey());
|
||||
aesKey = null;
|
||||
}
|
||||
|
||||
|
@ -313,7 +312,7 @@ public abstract class WalletService {
|
|||
List<TransactionConfidence> transactionConfidenceList = getOutputsWithConnectedOutputs(tx)
|
||||
.stream()
|
||||
.filter(WalletUtils::isOutputScriptConvertableToAddress)
|
||||
.filter(output -> address.equals(WalletUtils.getAddressFromOutput(output)))
|
||||
.filter(output -> address != null && address.equals(WalletUtils.getAddressFromOutput(output)))
|
||||
.map(o -> tx.getConfidence())
|
||||
.collect(Collectors.toList());
|
||||
return getMostRecentConfidence(transactionConfidenceList);
|
||||
|
@ -375,6 +374,7 @@ public abstract class WalletService {
|
|||
Coin balance = Coin.ZERO;
|
||||
for (TransactionOutput output : transactionOutputs) {
|
||||
if (WalletUtils.isOutputScriptConvertableToAddress(output) &&
|
||||
address != null &&
|
||||
address.equals(WalletUtils.getAddressFromOutput(output)))
|
||||
balance = balance.add(output.getValue());
|
||||
}
|
||||
|
@ -387,6 +387,7 @@ public abstract class WalletService {
|
|||
int outputs = 0;
|
||||
for (TransactionOutput output : transactionOutputs) {
|
||||
if (WalletUtils.isOutputScriptConvertableToAddress(output) &&
|
||||
address != null &&
|
||||
address.equals(WalletUtils.getAddressFromOutput(output)))
|
||||
outputs++;
|
||||
}
|
||||
|
@ -408,7 +409,8 @@ public abstract class WalletService {
|
|||
|
||||
public void emptyWallet(String toAddress, KeyParameter aesKey, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler)
|
||||
throws InsufficientMoneyException, AddressFormatException {
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.emptyWallet(new Address(params, toAddress));
|
||||
SendRequest sendRequest = SendRequest.emptyWallet(Address.fromBase58(params, toAddress));
|
||||
sendRequest.fee = Coin.ZERO;
|
||||
sendRequest.feePerKb = getTxFeeForWithdrawalPerByte().multiply(1000);
|
||||
sendRequest.aesKey = aesKey;
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
|
@ -550,11 +552,7 @@ public abstract class WalletService {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static void printTx(String tracePrefix, Transaction tx) {
|
||||
int size = tx.bitcoinSerialize().length;
|
||||
log.info("\n" + tracePrefix + ":\n" +
|
||||
tx.toString() +
|
||||
"Satoshi/byte: " + (tx.getFee() != null ? tx.getFee().value / size : "No fee set yet") +
|
||||
" (size: " + size + ")");
|
||||
log.info("\n" + tracePrefix + ":\n" + tx.toString());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@ import com.google.inject.Inject;
|
|||
import io.bisq.common.handlers.ExceptionHandler;
|
||||
import io.bisq.common.handlers.ResultHandler;
|
||||
import io.bisq.core.crypto.ScryptUtil;
|
||||
import org.bitcoinj.core.Wallet;
|
||||
import org.bitcoinj.crypto.KeyCrypter;
|
||||
import org.bitcoinj.crypto.KeyCrypterScrypt;
|
||||
import org.bitcoinj.wallet.DeterministicSeed;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
|
|
|
@ -40,9 +40,11 @@ import io.bisq.network.Socks5ProxyProvider;
|
|||
import javafx.beans.property.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.bitcoinj.core.*;
|
||||
import org.bitcoinj.core.listeners.DownloadProgressTracker;
|
||||
import org.bitcoinj.params.RegTestParams;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.DeterministicSeed;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -105,7 +107,6 @@ public class WalletsSetup {
|
|||
PersistenceProtoResolver persistenceProtoResolver,
|
||||
@Named(BtcOptionKeys.WALLET_DIR) File appDir,
|
||||
@Named(BtcOptionKeys.SOCKS5_DISCOVER_MODE) String socks5DiscoverModeString) {
|
||||
|
||||
this.regTestHost = regTestHost;
|
||||
this.addressEntryList = addressEntryList;
|
||||
this.userAgent = userAgent;
|
||||
|
@ -117,6 +118,7 @@ public class WalletsSetup {
|
|||
WalletUtils.setBitcoinNetwork(bisqEnvironment.getBitcoinNetwork());
|
||||
params = WalletUtils.getParameters();
|
||||
walletDir = new File(appDir, "bitcoin");
|
||||
PeerGroup.setIgnoreHttpSeeds(true);
|
||||
|
||||
storage = new Storage<>(walletDir, persistenceProtoResolver);
|
||||
LongPersistable nonce = storage.initAndGetPersistedWithFileName("BloomFilterNonce");
|
||||
|
@ -152,7 +154,8 @@ public class WalletsSetup {
|
|||
final Socks5Proxy socks5Proxy = preferences.getUseTorForBitcoinJ() ? socks5ProxyProvider.getSocks5Proxy() : null;
|
||||
log.debug("Use socks5Proxy for bitcoinj: " + socks5Proxy);
|
||||
|
||||
walletConfig = new WalletConfig(params, socks5Proxy, walletDir, BTC_WALLET_FILE_NAME, BSQ_WALLET_FILE_NAME, SPV_CHAIN_FILE_NAME) {
|
||||
walletConfig = new WalletConfig(params, socks5Proxy, walletDir, BTC_WALLET_FILE_NAME,
|
||||
BSQ_WALLET_FILE_NAME, SPV_CHAIN_FILE_NAME) {
|
||||
@Override
|
||||
protected void onSetupCompleted() {
|
||||
//We are here in the btcj thread Thread[ STARTING,5,main]
|
||||
|
@ -164,47 +167,15 @@ public class WalletsSetup {
|
|||
if (preferences.getBitcoinNodes() != null && !preferences.getBitcoinNodes().isEmpty())
|
||||
peerGroup.setAddPeersFromAddressMessage(false);
|
||||
|
||||
peerGroup.addEventListener(new PeerEventListener() {
|
||||
@Override
|
||||
public void onPeersDiscovered(Set<PeerAddress> peerAddresses) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlocksDownloaded(Peer peer, Block block, FilteredBlock filteredBlock, int blocksLeft) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChainDownloadStarted(Peer peer, int blocksLeft) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPeerConnected(Peer peer, int peerCount) {
|
||||
// We get called here on our user thread
|
||||
numPeers.set(peerCount);
|
||||
connectedPeers.set(peerGroup.getConnectedPeers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPeerDisconnected(Peer peer, int peerCount) {
|
||||
// We get called here on our user thread
|
||||
numPeers.set(peerCount);
|
||||
connectedPeers.set(peerGroup.getConnectedPeers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message onPreMessageReceived(Peer peer, Message m) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransaction(Peer peer, Transaction t) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Message> getData(Peer peer, GetDataMessage m) {
|
||||
return null;
|
||||
}
|
||||
peerGroup.addConnectedEventListener((peer, peerCount) -> {
|
||||
// We get called here on our user thread
|
||||
numPeers.set(peerCount);
|
||||
connectedPeers.set(peerGroup.getConnectedPeers());
|
||||
});
|
||||
peerGroup.addDisconnectedEventListener((peer, peerCount) -> {
|
||||
// We get called here on our user thread
|
||||
numPeers.set(peerCount);
|
||||
connectedPeers.set(peerGroup.getConnectedPeers());
|
||||
});
|
||||
|
||||
// Map to user thread
|
||||
|
@ -219,9 +190,7 @@ public class WalletsSetup {
|
|||
}
|
||||
};
|
||||
|
||||
configBloomfilter();
|
||||
configPeerNodes(socks5Proxy);
|
||||
|
||||
walletConfig.setDownloadListener(downloadListener)
|
||||
.setBlockingStartup(false)
|
||||
.setUserAgent(userAgent.getName(), userAgent.getVersion());
|
||||
|
@ -233,7 +202,7 @@ public class WalletsSetup {
|
|||
@Override
|
||||
public void failed(@NotNull Service.State from, @NotNull Throwable failure) {
|
||||
walletConfig = null;
|
||||
log.error("walletAppKit failed");
|
||||
log.error("Service failure from state: {}; failure={}", from, failure);
|
||||
timeoutTimer.stop();
|
||||
UserThread.execute(() -> exceptionHandler.handleException(failure));
|
||||
}
|
||||
|
@ -296,45 +265,6 @@ public class WalletsSetup {
|
|||
return mode;
|
||||
}
|
||||
|
||||
private void configBloomfilter() {
|
||||
// Bloom filters in BitcoinJ are completely broken
|
||||
// See: https://jonasnick.github.io/blog/2015/02/12/privacy-in-bitcoinj/
|
||||
// Here are a few improvements to fix a few vulnerabilities.
|
||||
|
||||
// bisq's BitcoinJ fork has added a bloomFilterTweak (nonce) setter to reuse the same seed avoiding the trivial vulnerability
|
||||
// by getting the real pub keys by intersections of several filters sent at each startup.
|
||||
walletConfig.setBloomFilterTweak(bloomFilterTweak);
|
||||
|
||||
// Avoid the simple attack (see: https://jonasnick.github.io/blog/2015/02/12/privacy-in-bitcoinj/) due to the
|
||||
// default implementation using both pubkey and hash of pubkey. We have set a insertPubKey flag in BasicKeyChain to default false.
|
||||
|
||||
// Default only 266 keys are generated (2 * 100+33 -> 100 external and 100 internal keys + buffers of 30%). That would trigger new bloom filters when we are reaching
|
||||
// the threshold. To avoid reaching the threshold we create much more keys which are unlikely to cause update of the
|
||||
// filter for most users. With lookaheadSize of 500 we get 1333 keys (500*1.3=666 666 external and 666 internal keys) which should be enough for most users to
|
||||
// never need to update a bloom filter, which would weaken privacy.
|
||||
// As we use 2 wallets (BTC, BSQ) we generate 1333 + 266 keys in total.
|
||||
walletConfig.setBtcWalletLookaheadSize(100);
|
||||
walletConfig.setBsqWalletLookaheadSize(100);
|
||||
|
||||
// Calculation is derived from: https://www.reddit.com/r/Bitcoin/comments/2vrx6n/privacy_in_bitcoinj_android_wallet_multibit_hive/coknjuz
|
||||
// No. of false positives (56M keys in the blockchain):
|
||||
// First attempt for FP rate:
|
||||
// FP rate = 0,0001; No. of false positives: 0,0001 * 56 000 000 = 5600
|
||||
// We have 1333keys: 1333 / (5600 + 1333) = 0.19 -> 19 % probability that a pub key is in our wallet
|
||||
// After tests I found out that the bandwidth consumption varies widely related to the generated filter.
|
||||
// About 20- 40 MB for upload and 30-130 MB for download at first start up (spv chain).
|
||||
// Afterwards its about 1 MB for upload and 20-80 MB for download.
|
||||
// Probably better then a high FP rate would be to include foreign pubKeyHashes which are tested to not be used
|
||||
// in many transactions. If we had a pool of 100 000 such keys (2 MB data dump) to random select 4000 we could mix it with our
|
||||
// 1000 own keys and get a similar probability rate as with the current setup but less variation in bandwidth
|
||||
// consumption.
|
||||
|
||||
// For now to reduce risks with high bandwidth consumption we reduce the FP rate by half.
|
||||
// FP rate = 0,00005; No. of false positives: 0,00005 * 56 000 000 = 2800
|
||||
// 1333 / (2800 + 1333) = 0.32 -> 32 % probability that a pub key is in our wallet
|
||||
walletConfig.setBloomFilterFalsePositiveRate(0.00005);
|
||||
}
|
||||
|
||||
private void configPeerNodes(Socks5Proxy socks5Proxy) {
|
||||
String btcNodes = preferences.getBitcoinNodes();
|
||||
log.debug("btcNodes: " + btcNodes);
|
||||
|
|
|
@ -42,6 +42,7 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -79,9 +80,13 @@ public class ProcessModel implements Model, Serializable {
|
|||
private String accountId;
|
||||
private PubKeyRing pubKeyRing;
|
||||
|
||||
// Mutable
|
||||
// Transient/Mutable
|
||||
transient private Transaction takeOfferFeeTx;
|
||||
@Setter
|
||||
transient private TradeMsg tradeMessage;
|
||||
|
||||
// Mutable
|
||||
private String takeOfferFeeTxId;
|
||||
@Setter
|
||||
private byte[] payoutTxSignature;
|
||||
@Setter
|
||||
|
@ -98,8 +103,6 @@ public class ProcessModel implements Model, Serializable {
|
|||
@Setter
|
||||
private String changeOutputAddress;
|
||||
@Setter
|
||||
private Transaction takeOfferFeeTx;
|
||||
@Setter
|
||||
private boolean useSavingsWallet;
|
||||
@Setter
|
||||
private long fundsNeededForTradeAsLong;
|
||||
|
@ -166,7 +169,6 @@ public class ProcessModel implements Model, Serializable {
|
|||
return paymentAccount != null ? paymentAccount.getPaymentAccountPayload() : null;
|
||||
}
|
||||
|
||||
|
||||
public boolean isPeersPaymentAccountDataAreBanned(PaymentAccountPayload paymentAccountPayload,
|
||||
PaymentAccountFilter[] appliedPaymentAccountFilter) {
|
||||
return filterManager.getFilter() != null &&
|
||||
|
@ -195,4 +197,15 @@ public class ProcessModel implements Model, Serializable {
|
|||
public Coin getFundsNeededForTradeAsLong() {
|
||||
return Coin.valueOf(fundsNeededForTradeAsLong);
|
||||
}
|
||||
|
||||
public Transaction getTakeOfferFeeTx() {
|
||||
if (takeOfferFeeTx == null)
|
||||
takeOfferFeeTx = bsqWalletService.getTransaction(Sha256Hash.wrap(takeOfferFeeTxId));
|
||||
return takeOfferFeeTx;
|
||||
}
|
||||
|
||||
public void setTakeOfferFeeTx(Transaction takeOfferFeeTx) {
|
||||
this.takeOfferFeeTx = takeOfferFeeTx;
|
||||
takeOfferFeeTxId = takeOfferFeeTx.getHashAsString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,9 +137,6 @@
|
|||
<urn>
|
||||
com.google.inject:guice:3.0:jar:null:compile:9d84f15fe35e2c716a02979fb62f50a29f38aefa
|
||||
</urn>
|
||||
<urn>
|
||||
com.google.protobuf:protobuf-java:2.5.0:jar:null:compile:a10732c76bfacdbd633a7eb0f7968b1059a65dfa
|
||||
</urn>
|
||||
<urn>
|
||||
com.google.zxing:core:2.0:jar:null:compile:001a5b8ccf93ca2fb7c40a94417f8485e3c8b4a6
|
||||
</urn>
|
||||
|
@ -265,6 +262,9 @@
|
|||
<urn>
|
||||
org.springframework:spring-test:4.1.1.RELEASE:jar:null:test:406ce9c05253f7dd75ac3f31170c71cca7419d8a
|
||||
</urn>
|
||||
<urn>
|
||||
com.google.protobuf:protobuf-java:3.2.0:jar:null:compile:62ccf171a106ff6791507f2d5364c275f9a3131d
|
||||
</urn>
|
||||
|
||||
<!-- A check for the rules themselves -->
|
||||
<urn>
|
||||
|
|
|
@ -32,7 +32,6 @@ import javafx.scene.control.TextField;
|
|||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.uri.BitcoinURI;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -156,8 +155,7 @@ public class AddressTextField extends AnchorPane {
|
|||
log.warn("Amount must not be negative");
|
||||
setAmountAsCoin(Coin.ZERO);
|
||||
}
|
||||
|
||||
return address.get() != null ? BitcoinURI.convertToBitcoinURI(address.get(), amountAsCoin.get(),
|
||||
paymentLabel.get(), null) : "";
|
||||
return GUIUtil.getBitcoinURI(address.get(), amountAsCoin.get(),
|
||||
paymentLabel.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package io.bisq.gui.main.dao.wallet.receive;
|
||||
|
||||
import io.bisq.common.UserThread;
|
||||
import io.bisq.common.app.DevEnv;
|
||||
import io.bisq.common.locale.Res;
|
||||
import io.bisq.core.btc.wallet.BsqWalletService;
|
||||
|
@ -26,37 +25,21 @@ import io.bisq.gui.common.view.FxmlView;
|
|||
import io.bisq.gui.components.AddressTextField;
|
||||
import io.bisq.gui.components.InputTextField;
|
||||
import io.bisq.gui.main.dao.wallet.BsqBalanceUtil;
|
||||
import io.bisq.gui.main.overlays.windows.QRCodeWindow;
|
||||
import io.bisq.gui.util.BsqFormatter;
|
||||
import io.bisq.gui.util.GUIUtil;
|
||||
import io.bisq.gui.util.Layout;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import net.glxn.qrgen.QRCode;
|
||||
import net.glxn.qrgen.image.ImageType;
|
||||
import org.bitcoinj.core.Address;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.uri.BitcoinURI;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static io.bisq.gui.util.FormBuilder.*;
|
||||
|
||||
@FxmlView
|
||||
public class BsqReceiveView extends ActivatableView<GridPane, Void> {
|
||||
|
||||
private ImageView qrCodeImageView;
|
||||
private AddressTextField addressTextField;
|
||||
private InputTextField amountTextField;
|
||||
private TextField balanceTextField;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final BsqBalanceUtil bsqBalanceUtil;
|
||||
|
@ -84,14 +67,6 @@ public class BsqReceiveView extends ActivatableView<GridPane, Void> {
|
|||
|
||||
addTitledGroupBg(root, ++gridRow, 3, Res.get("dao.wallet.receive.fundYourWallet"), Layout.GROUP_DISTANCE);
|
||||
|
||||
qrCodeImageView = new ImageView();
|
||||
qrCodeImageView.setStyle("-fx-cursor: hand;");
|
||||
Tooltip.install(qrCodeImageView, new Tooltip(Res.get("shared.openLargeQRWindow")));
|
||||
GridPane.setRowIndex(qrCodeImageView, gridRow);
|
||||
GridPane.setColumnIndex(qrCodeImageView, 1);
|
||||
GridPane.setMargin(qrCodeImageView, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 0, 0, 0));
|
||||
root.getChildren().add(qrCodeImageView);
|
||||
|
||||
addressTextField = addLabelAddressTextField(root, ++gridRow, Res.getWithCol("shared.address")).second;
|
||||
addressTextField.setPaymentLabel(paymentLabelString);
|
||||
|
||||
|
@ -106,47 +81,15 @@ public class BsqReceiveView extends ActivatableView<GridPane, Void> {
|
|||
|
||||
amountTextFieldSubscription = EasyBind.subscribe(amountTextField.textProperty(), t -> {
|
||||
addressTextField.setAmountAsCoin(bsqFormatter.parseToCoin(t));
|
||||
updateQRCode();
|
||||
});
|
||||
qrCodeImageView.setOnMouseClicked(e -> GUIUtil.showFeeInfoBeforeExecute(
|
||||
() -> UserThread.runAfter(
|
||||
() -> new QRCodeWindow(getBitcoinURI()).show(),
|
||||
200, TimeUnit.MILLISECONDS)));
|
||||
addressTextField.setAddress(bsqFormatter.getBsqAddressStringFromAddress(bsqWalletService.freshReceiveAddress()));
|
||||
updateQRCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
bsqBalanceUtil.deactivate();
|
||||
|
||||
qrCodeImageView.setOnMouseClicked(null);
|
||||
amountTextFieldSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
private void updateQRCode() {
|
||||
if (addressTextField.getAddress() != null && !addressTextField.getAddress().isEmpty()) {
|
||||
final byte[] imageBytes = QRCode
|
||||
.from(getBitcoinURI())
|
||||
.withSize(150, 150) // code has 41 elements 8 px is border with 150 we get 3x scale and min. border
|
||||
.to(ImageType.PNG)
|
||||
.stream()
|
||||
.toByteArray();
|
||||
Image qrImage = new Image(new ByteArrayInputStream(imageBytes));
|
||||
qrCodeImageView.setImage(qrImage);
|
||||
}
|
||||
}
|
||||
|
||||
private Coin getAmountAsCoin() {
|
||||
return bsqFormatter.parseToCoin(amountTextField.getText());
|
||||
}
|
||||
|
||||
private String getBitcoinURI() {
|
||||
Address addressFromBsqAddress = bsqFormatter.getAddressFromBsqAddress(addressTextField.getAddress());
|
||||
return BitcoinURI.convertToBitcoinURI(addressFromBsqAddress,
|
||||
getAmountAsCoin(),
|
||||
paymentLabelString,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ import net.glxn.qrgen.QRCode;
|
|||
import net.glxn.qrgen.image.ImageType;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.uri.BitcoinURI;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -294,10 +293,9 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
|||
|
||||
@NotNull
|
||||
private String getBitcoinURI() {
|
||||
return BitcoinURI.convertToBitcoinURI(addressTextField.getAddress(),
|
||||
return GUIUtil.getBitcoinURI(addressTextField.getAddress(),
|
||||
getAmountAsCoin(),
|
||||
paymentLabelString,
|
||||
null);
|
||||
paymentLabelString);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -58,8 +58,13 @@ import javafx.scene.input.KeyEvent;
|
|||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Callback;
|
||||
import org.bitcoinj.core.*;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionConfidence;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.bitcoinj.wallet.listeners.WalletEventListener;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
|
|
@ -54,7 +54,11 @@ import javafx.scene.control.*;
|
|||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Callback;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.bitcoinj.core.*;
|
||||
import org.bitcoinj.core.AddressFormatException;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.InsufficientMoneyException;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.spongycastle.crypto.params.KeyParameter;
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ import javafx.stage.Window;
|
|||
import javafx.util.StringConverter;
|
||||
import net.glxn.qrgen.QRCode;
|
||||
import net.glxn.qrgen.image.ImageType;
|
||||
import org.bitcoinj.uri.BitcoinURI;
|
||||
import org.controlsfx.control.PopOver;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
|
@ -1067,8 +1066,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
|||
|
||||
@NotNull
|
||||
private String getBitcoinURI() {
|
||||
return model.getAddressAsString() != null ? BitcoinURI.convertToBitcoinURI(model.getAddressAsString(), model.dataModel.getMissingCoin().get(),
|
||||
model.getPaymentLabel(), null) : "";
|
||||
return GUIUtil.getBitcoinURI(addressTextField.getAddress(), model.dataModel.getMissingCoin().get(),
|
||||
model.getPaymentLabel());
|
||||
}
|
||||
|
||||
private void addAmountPriceFields() {
|
||||
|
|
|
@ -61,7 +61,6 @@ import javafx.util.StringConverter;
|
|||
import net.glxn.qrgen.QRCode;
|
||||
import net.glxn.qrgen.image.ImageType;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.uri.BitcoinURI;
|
||||
import org.controlsfx.control.PopOver;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
|
@ -955,9 +954,9 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
|||
|
||||
@NotNull
|
||||
private String getBitcoinURI() {
|
||||
String addressString = model.dataModel.getAddressEntry().getAddressString();
|
||||
return addressString != null ? BitcoinURI.convertToBitcoinURI(addressString, model.dataModel.missingCoin.get(),
|
||||
model.getPaymentLabel(), null) : "";
|
||||
return GUIUtil.getBitcoinURI(model.dataModel.getAddressEntry().getAddressString(),
|
||||
model.dataModel.missingCoin.get(),
|
||||
model.getPaymentLabel());
|
||||
}
|
||||
|
||||
private void addAmountPriceFields() {
|
||||
|
|
|
@ -31,6 +31,7 @@ import io.bisq.common.persistence.ListPersistable;
|
|||
import io.bisq.common.proto.PersistenceProtoResolver;
|
||||
import io.bisq.common.storage.Storage;
|
||||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.core.btc.wallet.WalletUtils;
|
||||
import io.bisq.core.payment.PaymentAccount;
|
||||
import io.bisq.core.user.DontShowAgainLookup;
|
||||
import io.bisq.core.user.Preferences;
|
||||
|
@ -50,8 +51,10 @@ import javafx.stage.FileChooser;
|
|||
import javafx.stage.Stage;
|
||||
import javafx.util.StringConverter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bitcoinj.core.Address;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.TransactionConfidence;
|
||||
import org.bitcoinj.uri.BitcoinURI;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
|
@ -382,4 +385,11 @@ public class GUIUtil {
|
|||
component.setPrefHeight(available - initialOccupiedHeight.get());
|
||||
}, 100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static String getBitcoinURI(String address, Coin amount, String label) {
|
||||
return address != null ?
|
||||
BitcoinURI.convertToBitcoinURI(Address.fromBase58(WalletUtils.getParameters(),
|
||||
address), amount, label, null) :
|
||||
"";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,4 +75,14 @@ public class IOPParams extends NetworkParameters {
|
|||
public boolean hasMaxMoney() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitcoinSerializer getSerializer(boolean parseRetain) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersionNum(ProtocolVersion version) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,4 +75,14 @@ public class PivxParams extends NetworkParameters {
|
|||
public boolean hasMaxMoney() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitcoinSerializer getSerializer(boolean parseRetain) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProtocolVersionNum(ProtocolVersion version) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,9 @@ public class Socks5DnsDiscovery extends MultiplexingDiscovery {
|
|||
* Returns peer addresses. The actual DNS lookup is performed here.
|
||||
*/
|
||||
@Override
|
||||
public InetSocketAddress[] getPeers(long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
public InetSocketAddress[] getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
if (services != 0)
|
||||
throw new PeerDiscoveryException("DNS seeds cannot filter by services: " + services);
|
||||
try {
|
||||
InetSocketAddress addr = new InetSocketAddress(DnsLookupTor.lookup(proxy, hostname), params.getPort());
|
||||
return new InetSocketAddress[]{addr};
|
||||
|
|
|
@ -69,11 +69,10 @@ public class Socks5MultiDiscovery implements PeerDiscovery {
|
|||
* Returns an array containing all the Bitcoin nodes that have been discovered.
|
||||
*/
|
||||
@Override
|
||||
public InetSocketAddress[] getPeers(long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
public InetSocketAddress[] getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
ArrayList<InetSocketAddress> list = new ArrayList<>();
|
||||
|
||||
for (PeerDiscovery discovery : discoveryList) {
|
||||
list.addAll(Arrays.asList(discovery.getPeers(timeoutValue, timeoutUnit)));
|
||||
list.addAll(Arrays.asList(discovery.getPeers(services, timeoutValue, timeoutUnit)));
|
||||
}
|
||||
|
||||
return list.toArray(new InetSocketAddress[list.size()]);
|
||||
|
|
|
@ -110,7 +110,9 @@ public class Socks5SeedOnionDiscovery implements PeerDiscovery {
|
|||
* Returns an array containing all the Bitcoin nodes within the list.
|
||||
*/
|
||||
@Override
|
||||
public InetSocketAddress[] getPeers(long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
public InetSocketAddress[] getPeers(long services, long timeoutValue, TimeUnit timeoutUnit) throws PeerDiscoveryException {
|
||||
if (services != 0)
|
||||
throw new PeerDiscoveryException("DNS seeds cannot filter by services: " + services);
|
||||
return seedAddrs;
|
||||
}
|
||||
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -97,7 +97,7 @@
|
|||
<dependency>
|
||||
<groupId>org.bitcoinj</groupId>
|
||||
<artifactId>bitcoinj-core</artifactId>
|
||||
<version>0.13.1.11</version>
|
||||
<version>0.14.4.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
|
|
Loading…
Add table
Reference in a new issue