Merge branch 'master_upstream' into dispute-agent-branch

# Conflicts:
#	desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java
This commit is contained in:
chimp1984 2020-09-20 13:23:13 -05:00
commit c1850cb47b
No known key found for this signature in database
GPG key ID: 9801B4EC591F90E3
153 changed files with 1214 additions and 1202 deletions

View file

@ -17,8 +17,8 @@
package bisq.asset;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.MainNetParams;
@ -27,7 +27,7 @@ import org.bitcoinj.params.MainNetParams;
*
* @author Chris Beams
* @since 0.7.0
* @see org.bitcoinj.core.Address#fromBase58(NetworkParameters, String)
* @see org.bitcoinj.core.LegacyAddress#fromBase58(NetworkParameters, String)
*/
public class Base58BitcoinAddressValidator implements AddressValidator {
@ -44,7 +44,7 @@ public class Base58BitcoinAddressValidator implements AddressValidator {
@Override
public AddressValidationResult validate(String address) {
try {
Address.fromBase58(networkParameters, address);
LegacyAddress.fromBase58(networkParameters, address);
} catch (AddressFormatException ex) {
return AddressValidationResult.invalidAddress(ex);
}

View file

@ -33,7 +33,6 @@ public class Actinium extends Coin {
public ActiniumParams() {
addressHeader = 53;
p2shHeader = 55;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class Adeptio extends Coin {
public AdeptioParams() {
addressHeader = 23;
p2shHeader = 16;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Animecoin extends Coin {
public AnimecoinMainNetParams() {
this.addressHeader = 23;
this.p2shHeader = 9;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Australiacash extends Coin {
public AustraliacashParams() {
addressHeader = 23;
p2shHeader = 5;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -32,7 +32,6 @@ public class BitcoinRhodium extends Coin {
public BitcoinRhodiumParams() {
addressHeader = 61;
p2shHeader = 123;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -27,7 +27,6 @@ public class Bitmark extends Coin {
public BitmarkParams() {
addressHeader = 85;
p2shHeader = 5;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}

View file

@ -30,7 +30,6 @@ public class CTSCoin extends Coin {
public CtscMainNetParams() {
this.addressHeader = 66;
this.p2shHeader = 16;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -32,7 +32,6 @@ public class Chaucha extends Coin {
public ChauchaParams() {
addressHeader = 88;
p2shHeader = 50;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class Credits extends Coin {
public CreditsParams() {
addressHeader = 28;
p2shHeader = 5;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class DSTRA extends Coin {
public DSTRAParams() {
addressHeader = 30;
p2shHeader = 33;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class DarkPay extends Coin {
public DarkPayMainNetParams() {
this.addressHeader = 31;
this.p2shHeader = 60;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Dash extends Coin {
public DashMainNetParams() {
this.addressHeader = 76;
this.p2shHeader = 16;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -48,7 +48,6 @@ public class DeepOnion extends Coin {
super();
addressHeader = 31;
p2shHeader = 78;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -51,7 +51,6 @@ public class Dextro extends Coin {
super();
addressHeader = 30;
p2shHeader = 90;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -31,7 +31,6 @@ public class Dogecoin extends Coin {
public DogecoinMainNetParams() {
this.addressHeader = 30;
this.p2shHeader = 22;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -31,7 +31,6 @@ public class Doichain extends Coin {
public DoichainParams() {
addressHeader = 52;
p2shHeader = 13;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class Donu extends Coin {
public DonuParams() {
addressHeader = 53;
p2shHeader = 5;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -31,7 +31,6 @@ public class Emercoin extends Coin {
public EmercoinMainNetParams() {
this.addressHeader = 33;
this.p2shHeader = 92;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -32,7 +32,6 @@ public class Faircoin extends Coin {
public FaircoinParams() {
addressHeader = 95;
p2shHeader = 36;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}

View file

@ -30,7 +30,6 @@ public class Fujicoin extends Coin {
public FujicoinParams() {
addressHeader = 36;
p2shHeader = 16;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Galilel extends Coin {
public GalilelMainNetParams() {
this.addressHeader = 68;
this.p2shHeader = 16;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -51,7 +51,6 @@ public class GambleCoin extends Coin {
super();
addressHeader = 28;
p2shHeader = 18;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -51,7 +51,6 @@ public class Genesis extends Coin {
public GenesisParams() {
addressHeader = 28;
p2shHeader = 63;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Hatch extends Coin {
public HatchMainNetParams() {
this.addressHeader = 76;
this.p2shHeader = 16;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -33,7 +33,6 @@ public class Helium extends Coin {
public HeliumParams() {
addressHeader = 63;
p2shHeader = 5;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -51,7 +51,6 @@ public class IdaPay extends Coin {
super();
addressHeader = 29;
p2shHeader = 36;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -34,7 +34,6 @@ public class Kekcoin extends Coin {
super();
addressHeader = 45;
p2shHeader = 88;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class KnowYourDeveloper extends Coin {
public KydMainNetParams() {
this.addressHeader = 78;
this.p2shHeader = 85;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Kore extends Coin {
public KoreMainNetParams() {
this.addressHeader = 45;
this.p2shHeader = 85;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -31,7 +31,6 @@ public class LBRYCredits extends Coin {
public LBRYCreditsMainNetParams() {
this.addressHeader = 0x55;
this.p2shHeader = 0x7a;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Litecoin extends Coin {
public LitecoinMainNetParams() {
this.addressHeader = 48;
this.p2shHeader = 5;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -31,7 +31,6 @@ public class LitecoinPlus extends Coin {
public LitecoinPlusMainNetParams() {
this.addressHeader = 75;
this.p2shHeader = 8;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -33,7 +33,6 @@ public class Lytix extends Coin {
public LytixParams() {
addressHeader = 19;
p2shHeader = 11;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class MobitGlobal extends Coin {
public MobitGlobalParams() {
addressHeader = 50;
p2shHeader = 110;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class MonetaryUnit extends Coin {
public MonetaryUnitParams() {
addressHeader = 16;
p2shHeader = 76;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -31,7 +31,6 @@ public class Myce extends Coin {
public MyceParams() {
addressHeader = 50;
p2shHeader = 85;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Navcoin extends Coin {
public NavcoinParams() {
this.addressHeader = 53;
this.p2shHeader = 85;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class PIVX extends Coin {
public PIVXParams() {
addressHeader = 30;
p2shHeader = 13;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class PZDC extends Coin {
public PZDCParams() {
addressHeader = 55;
p2shHeader = 13;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -32,7 +32,6 @@ public class Particl extends Coin {
public ParticlMainNetParams() {
this.addressHeader = 56;
this.p2shHeader = 60;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
public static class ParticlMainNetAddressValidator extends Base58BitcoinAddressValidator {

View file

@ -33,7 +33,6 @@ public class Pinkcoin extends Coin {
public PinkcoinParams() {
addressHeader = 3;
p2shHeader = 28;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class QMCoin extends Coin {
public QMCoinParams() {
addressHeader = 58;
p2shHeader = 120;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -32,7 +32,6 @@ public class Qbase extends Coin {
public QbaseParams() {
addressHeader = 25;
p2shHeader = 5;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -34,7 +34,6 @@ public class Radium extends Coin {
super();
addressHeader = 76;
p2shHeader = 58;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class SUB1X extends Coin {
public SUB1XParams() {
addressHeader = 80;
p2shHeader = 13;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -17,6 +17,7 @@
package bisq.asset.coins;
import bisq.asset.AddressValidationResult;
import bisq.asset.Base58BitcoinAddressValidator;
import bisq.asset.Coin;
import bisq.asset.NetworkParametersAdapter;
@ -24,13 +25,27 @@ import bisq.asset.NetworkParametersAdapter;
public class SixEleven extends Coin {
public SixEleven() {
super("SixEleven", "SIL", new Base58BitcoinAddressValidator(new SixElevenChainParams()));
super("SixEleven", "SIL", new SixElevenAddressValidator());
}
public static class SixElevenAddressValidator extends Base58BitcoinAddressValidator {
public SixElevenAddressValidator() {
super(new SixEleven.SixElevenChainParams());
}
@Override
public AddressValidationResult validate(String address) {
if (!address.matches("^[MN][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{33}$"))
return AddressValidationResult.invalidStructure();
return super.validate(address);
}
}
public static class SixElevenChainParams extends NetworkParametersAdapter {
public SixElevenChainParams() {
addressHeader = 52;
acceptableAddressCodes = new int[]{addressHeader};
}
}
}

View file

@ -33,7 +33,6 @@ public class Spectrecoin extends Coin {
public SpectrecoinParams() {
addressHeader = 63;
p2shHeader = 136;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -51,7 +51,6 @@ public class UnitedCommunityCoin extends Coin {
super();
addressHeader = 68;
p2shHeader = 18;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -50,7 +50,6 @@ public class Veil extends Coin {
public VeilParams() {
addressHeader = 70;
p2shHeader = 5;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}
}
}

View file

@ -30,7 +30,6 @@ public class Vertcoin extends Coin {
public VertcoinMainNetParams() {
this.addressHeader = 71;
this.p2shHeader = 5;
this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
}
}
}

View file

@ -27,9 +27,9 @@ configure(subprojects) {
sourceCompatibility = 1.10
ext { // in alphabetical order
bcVersion = '1.56'
bitcoinjVersion = 'a88d36d'
btcdCli4jVersion = '975ff5d4'
bcVersion = '1.63'
bitcoinjVersion = '0d98efb'
btcdCli4jVersion = '27b94333'
codecVersion = '1.13'
easybindVersion = '1.0.3'
easyVersion = '4.0.1'
@ -40,7 +40,7 @@ configure(subprojects) {
fontawesomefxMaterialdesignfontVersion = '2.0.26-9.1.2'
grpcVersion = '1.25.0'
gsonVersion = '2.8.5'
guavaVersion = '20.0'
guavaVersion = '28.2-jre'
guiceVersion = '4.2.2'
hamcrestVersion = '1.3'
httpclientVersion = '4.5.12'
@ -69,7 +69,7 @@ configure(subprojects) {
pushyVersion = '0.13.2'
qrgenVersion = '1.3'
sarxosVersion = '0.3.12'
slf4jVersion = '1.7.25'
slf4jVersion = '1.7.30'
sparkVersion = '2.5.2'
springBootVersion = '1.5.10.RELEASE'
@ -211,11 +211,14 @@ configure(project(':proto')) {
configure(project(':assets')) {
dependencies {
compile("com.github.bisq-network.bitcoinj:bitcoinj-core:$bitcoinjVersion") {
compile("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
exclude(module: 'jsr305')
exclude(module: 'slf4j-api')
exclude(module: 'guava')
exclude(module: 'protobuf-java')
exclude(module: 'bcprov-jdk15on')
exclude(module: 'okhttp')
exclude(module: 'okio')
}
compile "com.google.guava:guava:$guavaVersion"
compile "org.slf4j:slf4j-api:$slf4jVersion"
@ -241,11 +244,14 @@ configure(project(':common')) {
compile("com.google.inject:guice:$guiceVersion") {
exclude(module: 'guava')
}
compile("com.github.bisq-network.bitcoinj:bitcoinj-core:$bitcoinjVersion") {
compile("com.github.bisq-network:bitcoinj:$bitcoinjVersion") {
exclude(module: 'jsr305')
exclude(module: 'slf4j-api')
exclude(module: 'guava')
exclude(module: 'protobuf-java')
exclude(module: 'bcprov-jdk15on')
exclude(module: 'okhttp')
exclude(module: 'okio')
}
runtimeOnly("io.grpc:grpc-netty-shaded:$grpcVersion") {
exclude(module: 'guava')
@ -306,7 +312,9 @@ configure(project(':core')) {
implementation("org.apache.httpcomponents:httpclient:$httpclientVersion") {
exclude(module: 'commons-codec')
}
compile "com.google.guava:guava:$guavaVersion"
compile("network.bisq.btcd-cli4j:btcd-cli4j-core:$btcdCli4jVersion") {
exclude(module: 'guava')
exclude(module: 'slf4j-api')
exclude(module: 'httpclient')
exclude(module: 'commons-lang3')
@ -315,6 +323,7 @@ configure(project(':core')) {
exclude(module: 'jackson-databind')
}
compile("network.bisq.btcd-cli4j:btcd-cli4j-daemon:$btcdCli4jVersion") {
exclude(module: 'guava')
exclude(module: 'slf4j-api')
exclude(module: 'httpclient')
exclude(module: 'commons-lang3')

View file

@ -21,7 +21,7 @@ import org.bitcoinj.core.Utils;
import com.google.common.base.Charsets;
import org.spongycastle.crypto.digests.RIPEMD160Digest;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

View file

@ -33,7 +33,7 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.KeyParameter;
import java.util.List;
import java.util.Optional;

View file

@ -0,0 +1,46 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.app;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class AsciiLogo {
public static void showAsciiLogo() {
log.info("\n\n" +
" ........ ...... \n" +
" .............. ...... \n" +
" ................. ...... \n" +
" ...... .......... .. ...... \n" +
" ...... ...... ...... ............... ..... ......... .......... \n" +
" ....... ........ .................. ..... ............. ............... \n" +
" ...... ........ .......... ....... ..... ...... ... ........ ....... \n" +
" ...... ..... ....... ..... ..... ..... ..... ...... \n" +
" ...... ... ... ...... ...... ..... ........... ...... ...... \n" +
" ...... ..... .... ...... ...... ..... ............ ..... ...... \n" +
" ...... ..... ...... ..... ........ ...... ...... \n" +
" ...... .... ... ...... ...... ..... .. ...... ...... ........ \n" +
" ........ .. ....... ................. ..... .............. ................... \n" +
" .......... ......... ............. ..... ............ ................. \n" +
" ...................... ..... .... .... ...... \n" +
" ................ ...... \n" +
" .... ...... \n" +
" ...... \n" +
"\n\n");
}
}

View file

@ -102,6 +102,7 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
///////////////////////////////////////////////////////////////////////////////////////////
protected void doExecute() {
AsciiLogo.showAsciiLogo();
configUserThread();
CoreSetup.setup(config);
addCapabilities();

View file

@ -103,7 +103,7 @@ import javafx.beans.value.ChangeListener;
import javafx.collections.ListChangeListener;
import javafx.collections.SetChangeListener;
import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.KeyParameter;
import java.io.IOException;

View file

@ -101,7 +101,7 @@ public class WalletAppSetup {
Runnable downloadCompleteHandler,
Runnable walletInitializedHandler) {
log.info("Initialize WalletAppSetup with BitcoinJ version {} and hash of BitcoinJ commit {}",
VersionMessage.BITCOINJ_VERSION, "cd30ad5b");
VersionMessage.BITCOINJ_VERSION, "0d98efb");
ObjectProperty<Throwable> walletServiceException = new SimpleObjectProperty<>();
btcInfoBinding = EasyBind.combine(walletsSetup.downloadPercentageProperty(),

View file

@ -41,7 +41,7 @@ public class TxBroadcastTimeoutException extends TxBroadcastException {
*/
public TxBroadcastTimeoutException(Transaction localTx, int delay, Wallet wallet) {
super("The transaction was not broadcasted in " + delay +
" seconds. txId=" + localTx.getHashAsString());
" seconds. txId=" + localTx.getTxId().toString());
this.localTx = localTx;
this.delay = delay;
this.wallet = wallet;

View file

@ -26,6 +26,7 @@ import com.google.protobuf.ByteString;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.crypto.DeterministicKey;
import java.util.Optional;
@ -174,7 +175,7 @@ public final class AddressEntry implements PersistablePayload {
@Nullable
public Address getAddress() {
if (address == null && keyPair != null)
address = keyPair.toAddress(Config.baseCurrencyNetworkParameters());
address = LegacyAddress.fromKey(Config.baseCurrencyNetworkParameters(), keyPair);
return address;
}

View file

@ -25,8 +25,10 @@ import bisq.common.storage.Storage;
import com.google.protobuf.Message;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.script.Script;
import org.bitcoinj.wallet.Wallet;
import com.google.inject.Inject;
@ -105,9 +107,12 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
if (!entrySet.isEmpty()) {
Set<AddressEntry> toBeRemoved = new HashSet<>();
entrySet.forEach(addressEntry -> {
DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubHash(addressEntry.getPubKeyHash());
DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubKeyHash(
addressEntry.getPubKeyHash(),
Script.ScriptType.P2PKH);
if (keyFromPubHash != null) {
Address addressFromKey = keyFromPubHash.toAddress(Config.baseCurrencyNetworkParameters());
Address addressFromKey = LegacyAddress.fromKey(Config.baseCurrencyNetworkParameters(),
keyFromPubHash);
// We want to ensure key and address matches in case we have address in entry available already
if (addressEntry.getAddress() == null || addressFromKey.equals(addressEntry.getAddress())) {
addressEntry.setDeterministicKey(keyFromPubHash);
@ -140,7 +145,7 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
.filter(this::isAddressNotInEntries)
.forEach(address -> {
log.info("Create AddressEntry for IssuedReceiveAddress. address={}", address.toString());
DeterministicKey key = (DeterministicKey) wallet.findKeyFromPubHash(address.getHash160());
DeterministicKey key = (DeterministicKey) wallet.findKeyFromAddress(address);
if (key != null) {
// Address will be derived from key in getAddress method
entrySet.add(new AddressEntry(key, AddressEntry.Context.AVAILABLE));
@ -175,7 +180,8 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
public void swapToAvailable(AddressEntry addressEntry) {
boolean setChangedByRemove = entrySet.remove(addressEntry);
boolean setChangedByAdd = entrySet.add(new AddressEntry(addressEntry.getKeyPair(), AddressEntry.Context.AVAILABLE));
boolean setChangedByAdd = entrySet.add(new AddressEntry(addressEntry.getKeyPair(),
AddressEntry.Context.AVAILABLE));
if (setChangedByRemove || setChangedByAdd) {
persist();
}
@ -208,7 +214,8 @@ public final class AddressEntryList implements UserThreadMappedPersistableEnvelo
.map(output -> output.getAddressFromP2PKHScript(wallet.getNetworkParameters()))
.filter(Objects::nonNull)
.filter(this::isAddressNotInEntries)
.map(address -> (DeterministicKey) wallet.findKeyFromPubHash(address.getHash160()))
.map(address -> (DeterministicKey) wallet.findKeyFromPubKeyHash(address.getHash(),
Script.ScriptType.P2PKH))
.filter(Objects::nonNull)
.map(deterministicKey -> new AddressEntry(deterministicKey, AddressEntry.Context.AVAILABLE))
.forEach(this::addAddressEntry);

View file

@ -55,17 +55,8 @@ class BtcNodeConverter {
PeerAddress convertOnionHost(BtcNode node) {
// no DNS lookup for onion addresses
String onionAddress = Objects.requireNonNull(node.getOnionAddress());
try {
// OnionCatConverter.onionHostToInetAddress converts onion to ipv6 representation
// inetAddress is not used but required for wallet persistence. Throws nullPointer if not set.
InetAddress inetAddress = facade.onionHostToInetAddress(onionAddress);
PeerAddress result = new PeerAddress(onionAddress, node.getPort());
result.setAddr(inetAddress);
return result;
} catch (UnknownHostException e) {
log.error("Failed to convert node", e);
return null;
}
PeerAddress result = new PeerAddress(onionAddress, node.getPort());
return result;
}
@Nullable
@ -107,7 +98,7 @@ class BtcNodeConverter {
// Blocking call. takes about 600 ms ;-(
InetAddress lookupAddress = facade.torLookup(proxy, host);
InetSocketAddress address = new InetSocketAddress(lookupAddress, port);
return new PeerAddress(address.getAddress(), address.getPort());
return new PeerAddress(address);
} catch (Exception e) {
log.error("Failed to create peer address", e);
return null;
@ -118,7 +109,7 @@ class BtcNodeConverter {
private static PeerAddress create(String hostName, int port) {
try {
InetSocketAddress address = new InetSocketAddress(hostName, port);
return new PeerAddress(address.getAddress(), address.getPort());
return new PeerAddress(address);
} catch (Exception e) {
log.error("Failed to create peer address", e);
return null;

View file

@ -1,81 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.btc.setup;
import org.bitcoinj.crypto.ChildNumber;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.KeyCrypter;
import org.bitcoinj.wallet.DeterministicKeyChain;
import org.bitcoinj.wallet.DeterministicSeed;
import com.google.common.collect.ImmutableList;
import org.spongycastle.crypto.params.KeyParameter;
import java.security.SecureRandom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class BisqDeterministicKeyChain extends DeterministicKeyChain {
private static final Logger log = LoggerFactory.getLogger(BisqDeterministicKeyChain.class);
// See https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
// https://github.com/satoshilabs/slips/blob/master/slip-0044.md
// 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),
ChildNumber.ZERO_HARDENED);
public BisqDeterministicKeyChain(SecureRandom random) {
super(random);
}
public BisqDeterministicKeyChain(DeterministicKey accountKey, boolean isFollowingKey) {
super(accountKey, isFollowingKey);
}
public BisqDeterministicKeyChain(DeterministicSeed seed, KeyCrypter crypter) {
super(seed, crypter);
}
public BisqDeterministicKeyChain(DeterministicSeed seed) {
super(seed);
}
@Override
public DeterministicKeyChain toEncrypted(KeyCrypter keyCrypter, KeyParameter aesKey) {
return new BisqDeterministicKeyChain(keyCrypter, aesKey, this);
}
protected DeterministicKeyChain makeKeyChainFromSeed(DeterministicSeed seed) {
return new BisqDeterministicKeyChain(seed);
}
protected BisqDeterministicKeyChain(KeyCrypter crypter, KeyParameter aesKey, DeterministicKeyChain chain) {
super(crypter, aesKey, chain);
}
@Override
protected ImmutableList<ChildNumber> getAccountPath() {
return BIP44_BSQ_ACCOUNT_PATH;
}
}

View file

@ -19,35 +19,56 @@ package bisq.core.btc.setup;
import org.bitcoinj.crypto.ChildNumber;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.HDUtils;
import org.bitcoinj.crypto.KeyCrypter;
import org.bitcoinj.script.Script;
import org.bitcoinj.wallet.DefaultKeyChainFactory;
import org.bitcoinj.wallet.DeterministicKeyChain;
import org.bitcoinj.wallet.DeterministicSeed;
import org.bitcoinj.wallet.KeyChainFactory;
import org.bitcoinj.wallet.KeyChainGroupStructure;
import org.bitcoinj.wallet.Protos;
import org.bitcoinj.wallet.UnreadableWalletException;
import com.google.common.collect.ImmutableList;
class BisqKeyChainFactory implements KeyChainFactory {
private final boolean useBitcoinDeterministicKeyChain;
/**
* Hack to convert bitcoinj 0.14 wallets to bitcoinj 0.15 format.
*
* This code is required to be executed only once per user (actually twice, for btc and bsq wallets).
* Once all users using bitcoinj 0.14 wallets have executed this code, this class will be no longer needed.
*
* Since that is almost impossible to guarantee, this hack will stay until we decide to don't be
* backwards compatible with pre bitcoinj 0.15 wallets.
* In that scenario, users will have to migrate using this procedure:
* 1) Run pre bitcoinj 0.15 bisq and copy their seed words on a piece of paper.
* 2) Run post bitcoinj 0.15 bisq and use recover from seed.
* */
public class BisqKeyChainFactory extends DefaultKeyChainFactory {
public BisqKeyChainFactory(boolean useBitcoinDeterministicKeyChain) {
this.useBitcoinDeterministicKeyChain = useBitcoinDeterministicKeyChain;
private boolean isBsqWallet;
public BisqKeyChainFactory(boolean isBsqWallet) {
this.isBsqWallet = isBsqWallet;
}
@Override
public DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed, KeyCrypter crypter, boolean isMarried) {
return useBitcoinDeterministicKeyChain ? new BtcDeterministicKeyChain(seed, crypter) : new BisqDeterministicKeyChain(seed, crypter);
public DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed, KeyCrypter crypter, boolean isMarried, Script.ScriptType outputScriptType, ImmutableList<ChildNumber> accountPath) {
ImmutableList<ChildNumber> maybeUpdatedAccountPath = accountPath;
if (DeterministicKeyChain.ACCOUNT_ZERO_PATH.equals(accountPath)) {
// This is a bitcoinj 0.14 wallet that has no account path in the serialized mnemonic
KeyChainGroupStructure structure = new BisqKeyChainGroupStructure(isBsqWallet);
maybeUpdatedAccountPath = structure.accountPathFor(outputScriptType);
}
return super.makeKeyChain(key, firstSubKey, seed, crypter, isMarried, outputScriptType, maybeUpdatedAccountPath);
}
@Override
public DeterministicKeyChain makeWatchingKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicKey accountKey,
boolean isFollowingKey, boolean isMarried) throws UnreadableWalletException {
ImmutableList<ChildNumber> accountPath = useBitcoinDeterministicKeyChain ? BtcDeterministicKeyChain.BIP44_BTC_ACCOUNT_PATH : BisqDeterministicKeyChain.BIP44_BSQ_ACCOUNT_PATH;
if (!accountKey.getPath().equals(accountPath))
throw new UnreadableWalletException("Expecting account key but found key with path: " +
HDUtils.formatPath(accountKey.getPath()));
return useBitcoinDeterministicKeyChain ? new BtcDeterministicKeyChain(accountKey, isFollowingKey) : new BisqDeterministicKeyChain(accountKey, isFollowingKey);
public DeterministicKeyChain makeWatchingKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicKey accountKey, boolean isFollowingKey, boolean isMarried, Script.ScriptType outputScriptType) throws UnreadableWalletException {
throw new UnsupportedOperationException("Bisq is not supposed to use this");
}
@Override
public DeterministicKeyChain makeSpendingKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicKey accountKey, boolean isMarried, Script.ScriptType outputScriptType) throws UnreadableWalletException {
throw new UnsupportedOperationException("Bisq is not supposed to use this");
}
}

View file

@ -1,49 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.btc.setup;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.wallet.DeterministicKeyChain;
import org.bitcoinj.wallet.KeyChainGroup;
import java.security.SecureRandom;
class BisqKeyChainGroup extends KeyChainGroup {
private final boolean useBitcoinDeterministicKeyChain;
public boolean isUseBitcoinDeterministicKeyChain() {
return useBitcoinDeterministicKeyChain;
}
public BisqKeyChainGroup(NetworkParameters params, @SuppressWarnings("SameParameterValue") boolean useBitcoinDeterministicKeyChain) {
super(params);
this.useBitcoinDeterministicKeyChain = useBitcoinDeterministicKeyChain;
}
public BisqKeyChainGroup(NetworkParameters params, DeterministicKeyChain chain, boolean useBitcoinDeterministicKeyChain) {
super(params, chain);
this.useBitcoinDeterministicKeyChain = useBitcoinDeterministicKeyChain;
}
@Override
public void createAndActivateNewHDChain() {
DeterministicKeyChain chain = useBitcoinDeterministicKeyChain ? new BtcDeterministicKeyChain(new SecureRandom()) : new BisqDeterministicKeyChain(new SecureRandom());
addAndActivateHDChain(chain);
}
}

View file

@ -0,0 +1,79 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.btc.setup;
import org.bitcoinj.crypto.ChildNumber;
import org.bitcoinj.script.Script;
import org.bitcoinj.wallet.KeyChainGroupStructure;
import com.google.common.collect.ImmutableList;
public class BisqKeyChainGroupStructure implements KeyChainGroupStructure {
// See https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
// https://github.com/satoshilabs/slips/blob/master/slip-0044.md
// We use 0 (0x80000000) as coin_type for BTC
// m / purpose' / coin_type' / account' / change / address_index
public static final ImmutableList<ChildNumber> BIP44_BTC_NON_SEGWIT_ACCOUNT_PATH = ImmutableList.of(
new ChildNumber(44, true),
new ChildNumber(0, true),
ChildNumber.ZERO_HARDENED);
public static final ImmutableList<ChildNumber> BIP44_BTC_SEGWIT_ACCOUNT_PATH = ImmutableList.of(
new ChildNumber(44, true),
new ChildNumber(0, true),
ChildNumber.ONE_HARDENED);
// See https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
// https://github.com/satoshilabs/slips/blob/master/slip-0044.md
// We have registered 142 (0x8000008E) as coin_type for BSQ
public static final ImmutableList<ChildNumber> BIP44_BSQ_NON_SEGWIT_ACCOUNT_PATH = ImmutableList.of(
new ChildNumber(44, true),
new ChildNumber(142, true),
ChildNumber.ZERO_HARDENED);
public static final ImmutableList<ChildNumber> BIP44_BSQ_SEGWIT_ACCOUNT_PATH = ImmutableList.of(
new ChildNumber(44, true),
new ChildNumber(142, true),
ChildNumber.ONE_HARDENED);
private boolean isBsqWallet;
public BisqKeyChainGroupStructure (boolean isBsqWallet) {
this.isBsqWallet = isBsqWallet;
}
@Override
public ImmutableList<ChildNumber> accountPathFor(Script.ScriptType outputScriptType) {
if (!isBsqWallet) {
if (outputScriptType == null || outputScriptType == Script.ScriptType.P2PKH)
return BIP44_BTC_NON_SEGWIT_ACCOUNT_PATH;
else if (outputScriptType == Script.ScriptType.P2WPKH)
return BIP44_BTC_SEGWIT_ACCOUNT_PATH;
else
throw new IllegalArgumentException(outputScriptType.toString());
} else {
if (outputScriptType == null || outputScriptType == Script.ScriptType.P2PKH)
return BIP44_BSQ_NON_SEGWIT_ACCOUNT_PATH;
else if (outputScriptType == Script.ScriptType.P2WPKH)
return BIP44_BSQ_SEGWIT_ACCOUNT_PATH;
else
throw new IllegalArgumentException(outputScriptType.toString());
}
}
}

View file

@ -1,29 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.btc.setup;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.wallet.KeyChainGroup;
import org.bitcoinj.wallet.Wallet;
public class BsqWallet extends Wallet {
public BsqWallet(NetworkParameters params, KeyChainGroup keyChainGroup) {
super(params, keyChainGroup);
}
}

View file

@ -1,82 +0,0 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.core.btc.setup;
import org.bitcoinj.crypto.ChildNumber;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.KeyCrypter;
import org.bitcoinj.wallet.DeterministicKeyChain;
import org.bitcoinj.wallet.DeterministicSeed;
import com.google.common.collect.ImmutableList;
import org.spongycastle.crypto.params.KeyParameter;
import java.security.SecureRandom;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class BtcDeterministicKeyChain extends DeterministicKeyChain {
private static final Logger log = LoggerFactory.getLogger(BtcDeterministicKeyChain.class);
// See https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
// https://github.com/satoshilabs/slips/blob/master/slip-0044.md
// We use 0 (0x80000000) as coin_type for BTC
// m / purpose' / coin_type' / account' / change / address_index
public static final ImmutableList<ChildNumber> BIP44_BTC_ACCOUNT_PATH = ImmutableList.of(
new ChildNumber(44, true),
new ChildNumber(0, true),
ChildNumber.ZERO_HARDENED);
public BtcDeterministicKeyChain(SecureRandom random) {
super(random);
}
public BtcDeterministicKeyChain(DeterministicKey accountKey, boolean isFollowingKey) {
super(accountKey, isFollowingKey);
}
public BtcDeterministicKeyChain(DeterministicSeed seed, KeyCrypter crypter) {
super(seed, crypter);
}
public BtcDeterministicKeyChain(DeterministicSeed seed) {
super(seed);
}
@Override
public DeterministicKeyChain toEncrypted(KeyCrypter keyCrypter, KeyParameter aesKey) {
return new BtcDeterministicKeyChain(keyCrypter, aesKey, this);
}
@Override
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;
}
}

File diff suppressed because it is too large Load diff

View file

@ -35,6 +35,7 @@ import bisq.network.Socks5ProxyProvider;
import bisq.common.Timer;
import bisq.common.UserThread;
import bisq.common.config.Config;
import bisq.common.app.Version;
import bisq.common.handlers.ExceptionHandler;
import bisq.common.handlers.ResultHandler;
import bisq.common.storage.FileUtil;
@ -48,7 +49,9 @@ import org.bitcoinj.core.PeerAddress;
import org.bitcoinj.core.PeerGroup;
import org.bitcoinj.core.RejectMessage;
import org.bitcoinj.core.listeners.DownloadProgressTracker;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.params.RegTestParams;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.utils.Threading;
import org.bitcoinj.wallet.DeterministicSeed;
import org.bitcoinj.wallet.Wallet;
@ -196,15 +199,8 @@ public class WalletsSetup {
log.info("Socks5Proxy for bitcoinj: socks5Proxy=" + socks5Proxy);
walletConfig = new WalletConfig(params,
socks5Proxy,
walletDir,
config,
localBitcoinNode,
userAgent,
numConnectionsForBtc,
btcWalletFileName,
BSQ_WALLET_FILE_NAME,
SPV_CHAIN_FILE_NAME) {
"bisq") {
@Override
protected void onSetupCompleted() {
//We are here in the btcj thread Thread[ STARTING,5,main]
@ -251,7 +247,7 @@ public class WalletsSetup {
// Map to user thread
UserThread.execute(() -> {
addressEntryList.onWalletReady(walletConfig.getBtcWallet());
addressEntryList.onWalletReady(walletConfig.btcWallet());
timeoutTimer.stop();
setupCompletedHandlers.stream().forEach(Runnable::run);
});
@ -260,11 +256,31 @@ public class WalletsSetup {
UserThread.runAfter(resultHandler::handleResult, 100, TimeUnit.MILLISECONDS);
}
};
walletConfig.setSocks5Proxy(socks5Proxy);
walletConfig.setConfig(config);
walletConfig.setLocalBitcoinNode(localBitcoinNode);
walletConfig.setUserAgent(userAgent, Version.VERSION);
walletConfig.setNumConnectionsForBtc(numConnectionsForBtc);
String checkpointsPath = null;
if (params.equals(MainNetParams.get())) {
// Checkpoints are block headers that ship inside our app: for a new user, we pick the last header
// in the checkpoints file and then download the rest from the network. It makes things much faster.
// Checkpoint files are made using the BuildCheckpoints tool and usually we have to download the
// last months worth or more (takes a few seconds).
checkpointsPath = "/wallet/checkpoints.txt";
} else if (params.equals(TestNet3Params.get())) {
checkpointsPath = "/wallet/checkpoints.testnet.txt";
}
if (checkpointsPath != null) {
walletConfig.setCheckpoints(getClass().getResourceAsStream(checkpointsPath));
}
if (params == RegTestParams.get()) {
walletConfig.setMinBroadcastConnections(1);
if (regTestHost == RegTestHost.LOCALHOST) {
walletConfig.setPeerNodesForLocalHost();
walletConfig.connectToLocalHost();
} else if (regTestHost == RegTestHost.REMOTE_HOST) {
configPeerNodesForRegTestServer();
} else {
@ -279,7 +295,7 @@ public class WalletsSetup {
}
} else if (localBitcoinNode.shouldBeUsed()) {
walletConfig.setMinBroadcastConnections(1);
walletConfig.setPeerNodesForLocalHost();
walletConfig.connectToLocalHost();
} else {
try {
configPeerNodes(socks5Proxy);
@ -295,7 +311,7 @@ public class WalletsSetup {
.setBlockingStartup(false);
// If seed is non-null it means we are restoring from backup.
walletConfig.setSeed(seed);
walletConfig.restoreWalletFromSeed(seed);
walletConfig.addListener(new Service.Listener() {
@Override
@ -363,7 +379,7 @@ public class WalletsSetup {
if (RegTestHost.HOST.endsWith(".onion")) {
walletConfig.setPeerNodes(new PeerAddress(RegTestHost.HOST, params.getPort()));
} else {
walletConfig.setPeerNodes(new PeerAddress(InetAddress.getByName(RegTestHost.HOST), params.getPort()));
walletConfig.setPeerNodes(new PeerAddress(params, InetAddress.getByName(RegTestHost.HOST), params.getPort()));
}
} catch (UnknownHostException e) {
log.error(e.toString());
@ -447,12 +463,12 @@ public class WalletsSetup {
///////////////////////////////////////////////////////////////////////////////////////////
public Wallet getBtcWallet() {
return walletConfig.getBtcWallet();
return walletConfig.btcWallet();
}
@Nullable
public Wallet getBsqWallet() {
return walletConfig.getBsqWallet();
return walletConfig.bsqWallet();
}
public NetworkParameters getParams() {

View file

@ -38,12 +38,14 @@ import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.ECKey.ECDSASignature;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.SignatureDecodeException;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutput;
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.script.ScriptChunk;
import org.bitcoinj.script.ScriptPattern;
import org.bitcoinj.wallet.RiskAnalysis;
import org.bitcoinj.wallet.Wallet;
@ -113,6 +115,13 @@ public class BisqRiskAnalysis implements RiskAnalysis {
if (tx.getConfidence().getSource() == TransactionConfidence.Source.SELF)
return Result.OK;
// Commented out to accept replace-by-fee txs.
// // We consider transactions that opt into replace-by-fee at risk of double spending.
// if (tx.isOptInFullRBF()) {
// nonFinal = tx;
// return Result.NON_FINAL;
// }
// Relative time-locked transactions are risky too. We can't check the locks because usually we don't know the
// spent outputs (to know when they were created).
if (tx.hasRelativeLockTime()) {
@ -197,7 +206,7 @@ public class BisqRiskAnalysis implements RiskAnalysis {
*/
public static RuleViolation isOutputStandard(TransactionOutput output) {
// OP_RETURN has usually output value zero, so we exclude that from the MIN_ANALYSIS_NONDUST_OUTPUT check
if (!output.getScriptPubKey().isOpReturn()
if (!ScriptPattern.isOpReturn(output.getScriptPubKey())
&& output.getValue().compareTo(MIN_ANALYSIS_NONDUST_OUTPUT) < 0)
return RuleViolation.DUST;
for (ScriptChunk chunk : output.getScriptPubKey().getChunks()) {
@ -216,7 +225,7 @@ public class BisqRiskAnalysis implements RiskAnalysis {
ECDSASignature signature;
try {
signature = ECKey.ECDSASignature.decodeFromDER(chunk.data);
} catch (RuntimeException x) {
} catch (SignatureDecodeException x) {
// Doesn't look like a signature.
signature = null;
}
@ -269,11 +278,11 @@ public class BisqRiskAnalysis implements RiskAnalysis {
@Override
public String toString() {
if (!analyzed)
return "Pending risk analysis for " + tx.getHashAsString();
return "Pending risk analysis for " + tx.getTxId().toString();
else if (nonFinal != null)
return "Risky due to non-finality of " + nonFinal.getHashAsString();
return "Risky due to non-finality of " + nonFinal.getTxId().toString();
else if (nonStandard != null)
return "Risky due to non-standard tx " + nonStandard.getHashAsString();
return "Risky due to non-standard tx " + nonStandard.getTxId().toString();
else
return "Non-risky";
}

View file

@ -53,12 +53,12 @@ public class BsqCoinSelector extends BisqDefaultCoinSelector {
return false;
// If it is a normal confirmed BSQ output we use the default lookup at the daoState
if (daoStateService.isTxOutputSpendable(new TxOutputKey(parentTransaction.getHashAsString(), output.getIndex())))
if (daoStateService.isTxOutputSpendable(new TxOutputKey(parentTransaction.getTxId().toString(), output.getIndex())))
return true;
// It might be that it is an unconfirmed change output which we allow to be used for spending without requiring a confirmation.
// We check if we have the output in the dao state, if so we have a confirmed but unspendable output (e.g. confiscated).
if (daoStateService.getTxOutput(new TxOutputKey(parentTransaction.getHashAsString(), output.getIndex())).isPresent())
if (daoStateService.getTxOutput(new TxOutputKey(parentTransaction.getTxId().toString(), output.getIndex())).isPresent())
return false;
// Only if it's not existing yet in the dao state (unconfirmed) we use our unconfirmedBsqChangeOutputList to

View file

@ -41,21 +41,19 @@ import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.BlockChain;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.InsufficientMoneyException;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.ScriptException;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.script.ScriptException;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutPoint;
import org.bitcoinj.core.TransactionOutput;
import org.bitcoinj.script.Script;
import org.bitcoinj.wallet.CoinSelection;
import org.bitcoinj.wallet.CoinSelector;
import org.bitcoinj.wallet.SendRequest;
import org.bitcoinj.wallet.Wallet;
import org.bitcoinj.wallet.listeners.AbstractWalletEventListener;
import javax.inject.Inject;
@ -142,54 +140,41 @@ public class BsqWalletService extends WalletService implements DaoStateListener
wallet = walletsSetup.getBsqWallet();
if (wallet != null) {
wallet.setCoinSelector(bsqCoinSelector);
wallet.addEventListener(walletEventListener);
//noinspection deprecation
wallet.addEventListener(new AbstractWalletEventListener() {
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
wallet.addCoinsReceivedEventListener(walletEventListener);
wallet.addCoinsSentEventListener(walletEventListener);
wallet.addReorganizeEventListener(walletEventListener);
wallet.addTransactionConfidenceEventListener(walletEventListener);
wallet.addCoinsReceivedEventListener((wallet, tx, prevBalance, newBalance) -> {
updateBsqWalletTransactions();
});
wallet.addCoinsSentEventListener((wallet, tx, prevBalance, newBalance) -> {
updateBsqWalletTransactions();
});
wallet.addReorganizeEventListener(wallet -> {
log.warn("onReorganize ");
updateBsqWalletTransactions();
unconfirmedBsqChangeOutputListService.onReorganize();
});
wallet.addTransactionConfidenceEventListener((wallet, tx) -> {
// We are only interested in updates from unconfirmed txs and confirmed txs at the
// time when it gets into a block. Otherwise we would get called
// updateBsqWalletTransactions for each tx as the block depth changes for all.
if (tx != null && tx.getConfidence() != null && tx.getConfidence().getDepthInBlocks() <= 1 &&
daoStateService.isParseBlockChainComplete()) {
updateBsqWalletTransactions();
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
updateBsqWalletTransactions();
}
@Override
public void onReorganize(Wallet wallet) {
log.warn("onReorganize ");
updateBsqWalletTransactions();
unconfirmedBsqChangeOutputListService.onReorganize();
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
// We are only interested in updates from unconfirmed txs and confirmed txs at the
// time when it gets into a block. Otherwise we would get called
// updateBsqWalletTransactions for each tx as the block depth changes for all.
if (tx != null && tx.getConfidence() != null && tx.getConfidence().getDepthInBlocks() <= 1 &&
daoStateService.isParseBlockChainComplete()) {
updateBsqWalletTransactions();
}
unconfirmedBsqChangeOutputListService.onTransactionConfidenceChanged(tx);
}
@Override
public void onKeysAdded(List<ECKey> keys) {
updateBsqWalletTransactions();
}
@Override
public void onScriptsChanged(Wallet wallet, List<Script> scripts, boolean isAddingScripts) {
updateBsqWalletTransactions();
}
@Override
public void onWalletChanged(Wallet wallet) {
updateBsqWalletTransactions();
}
unconfirmedBsqChangeOutputListService.onTransactionConfidenceChanged(tx);
});
wallet.addKeyChainEventListener(keys -> {
updateBsqWalletTransactions();
});
wallet.addScriptsChangeEventListener((wallet, scripts, isAddingScripts) -> {
updateBsqWalletTransactions();
});
wallet.addChangeEventListener(wallet -> {
updateBsqWalletTransactions();
});
}
@ -223,7 +208,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
@Override
String getWalletAsString(boolean includePrivKeys) {
return wallet.toString(includePrivKeys, true, true, walletsSetup.getChain()) + "\n\n" +
return wallet.toString(true, includePrivKeys, null, true, true, walletsSetup.getChain()) + "\n\n" +
"All pubKeys as hex:\n" +
wallet.printAllPubKeysAsHex();
}
@ -256,7 +241,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
// TODO SQ
if (parentTransaction != null/* &&
parentTransaction.getConfidence().getConfidenceType() == BUILDING*/) {
TxOutputKey key = new TxOutputKey(parentTransaction.getHashAsString(),
TxOutputKey key = new TxOutputKey(parentTransaction.getTxId().toString(),
connectedOutput.getIndex());
return (connectedOutput.isMine(wallet)
@ -275,7 +260,8 @@ public class BsqWalletService extends WalletService implements DaoStateListener
Set<String> confirmedTxIdSet = getTransactions(false).stream()
.filter(tx -> tx.getConfidence().getConfidenceType() == BUILDING)
.map(Transaction::getHashAsString)
.map(Transaction::getTxId)
.map(Sha256Hash::toString)
.collect(Collectors.toSet());
lockedForVotingBalance = Coin.valueOf(daoStateService.getUnspentBlindVoteStakeTxOutputs().stream()
@ -364,7 +350,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
private Set<Transaction> getBsqWalletTransactions() {
return getTransactions(false).stream()
.filter(transaction -> transaction.getConfidence().getConfidenceType() == PENDING ||
daoStateService.containsTx(transaction.getHashAsString()))
daoStateService.containsTx(transaction.getTxId().toString()))
.collect(Collectors.toSet());
}
@ -378,12 +364,12 @@ public class BsqWalletService extends WalletService implements DaoStateListener
return new HashSet<>();
} else {
Map<String, Transaction> map = walletTxs.stream()
.collect(Collectors.toMap(Transaction::getHashAsString, Function.identity()));
.collect(Collectors.toMap(t -> t.getTxId().toString(), Function.identity()));
Set<String> walletTxIds = walletTxs.stream()
.map(Transaction::getHashAsString).collect(Collectors.toSet());
.map(Transaction::getTxId).map(Sha256Hash::toString).collect(Collectors.toSet());
Set<String> bsqTxIds = bsqWalletTransactions.stream()
.map(Transaction::getHashAsString).collect(Collectors.toSet());
.map(Transaction::getTxId).map(Sha256Hash::toString).collect(Collectors.toSet());
walletTxIds.stream()
.filter(bsqTxIds::contains)
@ -409,7 +395,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
if (isConfirmed) {
// We lookup if we have a BSQ tx matching the parent tx
// We cannot make that findTx call outside of the loop as the parent tx can change at each iteration
Optional<Tx> txOptional = daoStateService.getTx(parentTransaction.getHash().toString());
Optional<Tx> txOptional = daoStateService.getTx(parentTransaction.getTxId().toString());
if (txOptional.isPresent()) {
TxOutput txOutput = txOptional.get().getTxOutputs().get(connectedOutput.getIndex());
if (daoStateService.isBsqTxOutputType(txOutput)) {
@ -438,7 +424,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
@Override
public Coin getValueSentToMeForTransaction(Transaction transaction) throws ScriptException {
Coin result = Coin.ZERO;
final String txId = transaction.getHashAsString();
final String txId = transaction.getTxId().toString();
// We check if we have a matching BSQ tx. We do that call here to avoid repeated calls in the loop.
Optional<Tx> txOptional = daoStateService.getTx(txId);
// We check all the outputs of our tx
@ -475,7 +461,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
}
public Optional<Transaction> isWalletTransaction(String txId) {
return walletTransactions.stream().filter(e -> e.getHashAsString().equals(txId)).findAny();
return walletTransactions.stream().filter(e -> e.getTxId().toString().equals(txId)).findAny();
}
@ -545,7 +531,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
Transaction tx = new Transaction(params);
checkArgument(Restrictions.isAboveDust(receiverAmount),
"The amount is too low (dust limit).");
tx.addOutput(receiverAmount, Address.fromBase58(params, receiverAddress));
tx.addOutput(receiverAmount, LegacyAddress.fromBase58(params, receiverAddress));
SendRequest sendRequest = SendRequest.forTx(tx);
sendRequest.fee = Coin.ZERO;
@ -786,7 +772,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
protected Set<Address> getAllAddressesFromActiveKeys() {
return wallet.getActiveKeyChain().getLeafKeys().stream().
map(key -> Address.fromP2SHHash(params, key.getPubKeyHash())).
map(key -> LegacyAddress.fromScriptHash(params, key.getPubKeyHash())).
collect(Collectors.toSet());
}
@ -802,7 +788,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
}
public String getUnusedBsqAddressAsString() {
return "B" + getUnusedAddress().toBase58();
return "B" + getUnusedAddress().toString();
}
// For BSQ we do not check for dust attack utxos as they are 5.46 BSQ and a considerable value.

View file

@ -33,6 +33,7 @@ import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.InsufficientMoneyException;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
import org.bitcoinj.core.TransactionInput;
@ -49,8 +50,9 @@ import javax.inject.Inject;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.KeyParameter;
import java.util.Arrays;
import java.util.List;
@ -91,7 +93,10 @@ public class BtcWalletService extends WalletService {
walletsSetup.addSetupCompletedHandler(() -> {
wallet = walletsSetup.getBtcWallet();
wallet.addEventListener(walletEventListener);
wallet.addCoinsReceivedEventListener(walletEventListener);
wallet.addCoinsSentEventListener(walletEventListener);
wallet.addReorganizeEventListener(walletEventListener);
wallet.addTransactionConfidenceEventListener(walletEventListener);
walletsSetup.getChain().addNewBestBlockListener(block -> chainHeightProperty.set(block.getHeight()));
chainHeightProperty.set(walletsSetup.getChain().getBestChainHeight());
@ -133,7 +138,7 @@ public class BtcWalletService extends WalletService {
return "Address entry list:\n" +
sb.toString() +
"\n\n" +
wallet.toString(includePrivKeys, true, true, walletsSetup.getChain()) + "\n\n" +
wallet.toString(true, includePrivKeys, null, true, true, walletsSetup.getChain()) + "\n\n" +
"All pubKeys as hex:\n" +
wallet.printAllPubKeysAsHex();
}
@ -743,7 +748,7 @@ public class BtcWalletService extends WalletService {
AddressEntry addressEntry = getFreshAddressEntry();
checkNotNull(addressEntry.getAddress(), "addressEntry.getAddress() must not be null");
Optional<Transaction> transactionOptional = wallet.getTransactions(true).stream()
.filter(t -> t.getHashAsString().equals(txId))
.filter(t -> t.getTxId().toString().equals(txId))
.findAny();
if (transactionOptional.isPresent()) {
Transaction txToDoubleSpend = transactionOptional.get();
@ -864,7 +869,7 @@ public class BtcWalletService extends WalletService {
log.error("Broadcasting double spending transaction failed. " + t.getMessage());
errorMessageHandler.handleErrorMessage(t.getMessage());
}
});
}, MoreExecutors.directExecutor());
}
} catch (InsufficientMoneyException e) {
@ -988,7 +993,7 @@ public class BtcWalletService extends WalletService {
public int getEstimatedFeeTxSize(List<Coin> outputValues, Coin txFee)
throws InsufficientMoneyException, AddressFormatException {
Transaction transaction = new Transaction(params);
Address dummyAddress = wallet.currentReceiveKey().toAddress(params);
Address dummyAddress = LegacyAddress.fromKey(params, wallet.currentReceiveKey());
outputValues.forEach(outputValue -> transaction.addOutput(outputValue, dummyAddress));
SendRequest sendRequest = SendRequest.forTx(transaction);
@ -1019,10 +1024,10 @@ public class BtcWalletService extends WalletService {
AddressEntryException, InsufficientMoneyException {
SendRequest sendRequest = getSendRequest(fromAddress, toAddress, receiverAmount, fee, aesKey, context);
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
Futures.addCallback(sendResult.broadcastComplete, callback);
Futures.addCallback(sendResult.broadcastComplete, callback, MoreExecutors.directExecutor());
printTx("sendFunds", sendResult.tx);
return sendResult.tx.getHashAsString();
return sendResult.tx.getTxId().toString();
}
public String sendFundsForMultipleAddresses(Set<String> fromAddresses,
@ -1036,10 +1041,10 @@ public class BtcWalletService extends WalletService {
SendRequest request = getSendRequestForMultipleAddresses(fromAddresses, toAddress, receiverAmount, fee, changeAddress, aesKey);
Wallet.SendResult sendResult = wallet.sendCoins(request);
Futures.addCallback(sendResult.broadcastComplete, callback);
Futures.addCallback(sendResult.broadcastComplete, callback, MoreExecutors.directExecutor());
printTx("sendFunds", sendResult.tx);
return sendResult.tx.getHashAsString();
return sendResult.tx.getTxId().toString();
}
private SendRequest getSendRequest(String fromAddress,
@ -1053,7 +1058,7 @@ public class BtcWalletService extends WalletService {
final Coin receiverAmount = amount.subtract(fee);
Preconditions.checkArgument(Restrictions.isAboveDust(receiverAmount),
"The amount is too low (dust limit).");
tx.addOutput(receiverAmount, Address.fromBase58(params, toAddress));
tx.addOutput(receiverAmount, LegacyAddress.fromBase58(params, toAddress));
SendRequest sendRequest = SendRequest.forTx(tx);
sendRequest.fee = fee;
@ -1084,7 +1089,7 @@ public class BtcWalletService extends WalletService {
checkArgument(Restrictions.isAboveDust(netValue),
"The amount is too low (dust limit).");
tx.addOutput(netValue, Address.fromBase58(params, toAddress));
tx.addOutput(netValue, LegacyAddress.fromBase58(params, toAddress));
SendRequest sendRequest = SendRequest.forTx(tx);
sendRequest.fee = fee;
@ -1149,14 +1154,14 @@ public class BtcWalletService extends WalletService {
Preconditions.checkArgument(Restrictions.isAboveDust(buyerAmount),
"The buyerAmount is too low (dust limit).");
tx.addOutput(buyerAmount, Address.fromBase58(params, buyerAddressString));
tx.addOutput(buyerAmount, LegacyAddress.fromBase58(params, buyerAddressString));
}
// sellerAmount can be 0
if (sellerAmount.isPositive()) {
Preconditions.checkArgument(Restrictions.isAboveDust(sellerAmount),
"The sellerAmount is too low (dust limit).");
tx.addOutput(sellerAmount, Address.fromBase58(params, sellerAddressString));
tx.addOutput(sellerAmount, LegacyAddress.fromBase58(params, sellerAddressString));
}
SendRequest sendRequest = SendRequest.forTx(tx);

View file

@ -54,7 +54,7 @@ public class NonBsqCoinSelector extends BisqDefaultCoinSelector {
if (parentTransaction.getConfidence().getConfidenceType() != TransactionConfidence.ConfidenceType.BUILDING)
return false;
TxOutputKey key = new TxOutputKey(parentTransaction.getHashAsString(), output.getIndex());
TxOutputKey key = new TxOutputKey(parentTransaction.getTxId().toString(), output.getIndex());
// It might be that we received BTC in a non-BSQ tx so that will not be stored in out state and not found.
// So we consider any txOutput which is not in the state as BTC output.
return !daoStateService.existsTxOutput(key) || daoStateService.isRejectedIssuanceOutput(key);

View file

@ -36,8 +36,10 @@ import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.InsufficientMoneyException;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.SignatureDecodeException;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutPoint;
@ -47,6 +49,7 @@ import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.script.Script;
import org.bitcoinj.script.ScriptBuilder;
import org.bitcoinj.script.ScriptPattern;
import org.bitcoinj.wallet.SendRequest;
import org.bitcoinj.wallet.Wallet;
@ -54,7 +57,7 @@ import javax.inject.Inject;
import com.google.common.collect.ImmutableList;
import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.KeyParameter;
import java.util.ArrayList;
import java.util.List;
@ -151,7 +154,7 @@ public class TradeWalletService {
Transaction tradingFeeTx = new Transaction(params);
SendRequest sendRequest = null;
try {
tradingFeeTx.addOutput(tradingFee, Address.fromBase58(params, feeReceiverAddress));
tradingFeeTx.addOutput(tradingFee, LegacyAddress.fromBase58(params, feeReceiverAddress));
// the reserved amount we need for the trade we send to our trade reservedForTradeAddress
tradingFeeTx.addOutput(reservedFundsForOffer, reservedForTradeAddress);
@ -333,7 +336,7 @@ public class TradeWalletService {
Transaction dummyTX = new Transaction(params);
// The output is just used to get the right inputs and change outputs, so we use an anonymous ECKey, as it will never be used for anything.
// We don't care about fee calculation differences between the real tx and that dummy tx as we use a static tx fee.
TransactionOutput dummyOutput = new TransactionOutput(params, dummyTX, dummyOutputAmount, new ECKey().toAddress(params));
TransactionOutput dummyOutput = new TransactionOutput(params, dummyTX, dummyOutputAmount, LegacyAddress.fromKey(params, new ECKey()));
dummyTX.addOutput(dummyOutput);
// Find the needed inputs to pay the output, optionally add 1 change output.
@ -453,7 +456,7 @@ public class TradeWalletService {
// First we construct a dummy TX to get the inputs and outputs we want to use for the real deposit tx.
// Similar to the way we did in the createTakerDepositTxInputs method.
Transaction dummyTx = new Transaction(params);
TransactionOutput dummyOutput = new TransactionOutput(params, dummyTx, makerInputAmount, new ECKey().toAddress(params));
TransactionOutput dummyOutput = new TransactionOutput(params, dummyTx, makerInputAmount, LegacyAddress.fromKey(params, new ECKey()));
dummyTx.addOutput(dummyOutput);
addAvailableInputsAndChangeOutputs(dummyTx, makerAddress, makerChangeAddress);
// Normally we have only 1 input but we support multiple inputs if the user has paid in with several transactions.
@ -515,7 +518,7 @@ public class TradeWalletService {
TransactionOutput takerTransactionOutput = null;
if (takerChangeOutputValue > 0 && takerChangeAddressString != null) {
takerTransactionOutput = new TransactionOutput(params, preparedDepositTx, Coin.valueOf(takerChangeOutputValue),
Address.fromBase58(params, takerChangeAddressString));
LegacyAddress.fromBase58(params, takerChangeAddressString));
}
if (makerIsBuyer) {
@ -685,7 +688,7 @@ public class TradeWalletService {
delayedPayoutTx.addInput(p2SHMultiSigOutput);
applyLockTime(lockTime, delayedPayoutTx);
Coin outputAmount = p2SHMultiSigOutput.getValue().subtract(minerFee);
delayedPayoutTx.addOutput(outputAmount, Address.fromBase58(params, donationAddressString));
delayedPayoutTx.addOutput(outputAmount, LegacyAddress.fromBase58(params, donationAddressString));
WalletService.printTx("Unsigned delayedPayoutTx ToDonationAddress", delayedPayoutTx);
WalletService.verifyTransaction(delayedPayoutTx);
return delayedPayoutTx;
@ -715,7 +718,7 @@ public class TradeWalletService {
byte[] sellerPubKey,
byte[] buyerSignature,
byte[] sellerSignature)
throws AddressFormatException, TransactionVerificationException, WalletException {
throws AddressFormatException, TransactionVerificationException, WalletException, SignatureDecodeException {
Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
ECKey.ECDSASignature buyerECDSASignature = ECKey.ECDSASignature.decodeFromDER(buyerSignature);
ECKey.ECDSASignature sellerECDSASignature = ECKey.ECDSASignature.decodeFromDER(sellerSignature);
@ -805,7 +808,7 @@ public class TradeWalletService {
DeterministicKey multiSigKeyPair,
byte[] buyerPubKey,
byte[] sellerPubKey)
throws AddressFormatException, TransactionVerificationException, WalletException {
throws AddressFormatException, TransactionVerificationException, WalletException, SignatureDecodeException {
Transaction payoutTx = createPayoutTx(depositTx, buyerPayoutAmount, sellerPayoutAmount, buyerPayoutAddressString, sellerPayoutAddressString);
// MS redeemScript
Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
@ -872,7 +875,7 @@ public class TradeWalletService {
DeterministicKey multiSigKeyPair,
byte[] buyerPubKey,
byte[] sellerPubKey)
throws AddressFormatException, TransactionVerificationException, WalletException {
throws AddressFormatException, TransactionVerificationException, WalletException, SignatureDecodeException {
Transaction payoutTx = createPayoutTx(depositTx, buyerPayoutAmount, sellerPayoutAmount, buyerPayoutAddressString, sellerPayoutAddressString);
// MS redeemScript
Script redeemScript = get2of2MultiSigRedeemScript(buyerPubKey, sellerPubKey);
@ -931,16 +934,16 @@ public class TradeWalletService {
byte[] buyerPubKey,
byte[] sellerPubKey,
byte[] arbitratorPubKey)
throws AddressFormatException, TransactionVerificationException, WalletException {
throws AddressFormatException, TransactionVerificationException, WalletException, SignatureDecodeException {
Transaction depositTx = new Transaction(params, depositTxSerialized);
TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
Transaction payoutTx = new Transaction(params);
payoutTx.addInput(p2SHMultiSigOutput);
if (buyerPayoutAmount.isPositive()) {
payoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
payoutTx.addOutput(buyerPayoutAmount, LegacyAddress.fromBase58(params, buyerAddressString));
}
if (sellerPayoutAmount.isPositive()) {
payoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
payoutTx.addOutput(sellerPayoutAmount, LegacyAddress.fromBase58(params, sellerAddressString));
}
// take care of sorting!
@ -1000,10 +1003,10 @@ public class TradeWalletService {
payoutTx.addInput(new TransactionInput(params, depositTx, p2SHMultiSigOutputScript.getProgram(), new TransactionOutPoint(params, 0, spendTxHash), msOutput));
if (buyerPayoutAmount.isPositive()) {
payoutTx.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
payoutTx.addOutput(buyerPayoutAmount, LegacyAddress.fromBase58(params, buyerAddressString));
}
if (sellerPayoutAmount.isPositive()) {
payoutTx.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
payoutTx.addOutput(sellerPayoutAmount, LegacyAddress.fromBase58(params, sellerAddressString));
}
// take care of sorting!
@ -1145,10 +1148,10 @@ public class TradeWalletService {
Transaction transaction = new Transaction(params);
transaction.addInput(p2SHMultiSigOutput);
if (buyerPayoutAmount.isPositive()) {
transaction.addOutput(buyerPayoutAmount, Address.fromBase58(params, buyerAddressString));
transaction.addOutput(buyerPayoutAmount, LegacyAddress.fromBase58(params, buyerAddressString));
}
if (sellerPayoutAmount.isPositive()) {
transaction.addOutput(sellerPayoutAmount, Address.fromBase58(params, sellerAddressString));
transaction.addOutput(sellerPayoutAmount, LegacyAddress.fromBase58(params, sellerAddressString));
}
checkArgument(transaction.getOutputs().size() >= 1, "We need at least one output.");
return transaction;
@ -1167,9 +1170,9 @@ public class TradeWalletService {
Sha256Hash hash = transaction.hashForSignature(inputIndex, scriptPubKey, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature signature = sigKey.sign(hash, aesKey);
TransactionSignature txSig = new TransactionSignature(signature, Transaction.SigHash.ALL, false);
if (scriptPubKey.isSentToRawPubKey()) {
if (ScriptPattern.isP2PK(scriptPubKey)) {
input.setScriptSig(ScriptBuilder.createInputScript(txSig));
} else if (scriptPubKey.isSentToAddress()) {
} else if (ScriptPattern.isP2PKH(scriptPubKey)) {
input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey));
} else {
throw new SigningException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);

View file

@ -29,6 +29,7 @@ import org.bitcoinj.wallet.Wallet;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.HashMap;
import java.util.Map;
@ -77,22 +78,24 @@ public class TxBroadcaster {
// Wallet.complete() method is called which is the case for all BSQ txs. We will work on a fix for that but that
// will take more time. In the meantime we reduce the timeout to 5 seconds to avoid that the trade protocol runs
// into a timeout when using BSQ for trade fee.
// For trade fee txs we set only 1 sec timeout for now.
// FIXME
private static final int DEFAULT_BROADCAST_TIMEOUT = 5;
private static Map<String, Timer> broadcastTimerMap = new HashMap<>();
private static final Map<String, Timer> broadcastTimerMap = new HashMap<>();
public static void broadcastTx(Wallet wallet, PeerGroup peerGroup, Transaction localTx, Callback callback) {
broadcastTx(wallet, peerGroup, localTx, callback, DEFAULT_BROADCAST_TIMEOUT);
}
public static void broadcastTx(Wallet wallet, PeerGroup peerGroup, Transaction tx, Callback callback, int delayInSec) {
public static void broadcastTx(Wallet wallet, PeerGroup peerGroup, Transaction tx, Callback callback, int timeOut) {
Timer timeoutTimer;
final String txId = tx.getHashAsString();
final String txId = tx.getTxId().toString();
if (!broadcastTimerMap.containsKey(txId)) {
timeoutTimer = UserThread.runAfter(() -> {
log.warn("Broadcast of tx {} not completed after {} sec.", txId, delayInSec);
log.warn("Broadcast of tx {} not completed after {} sec.", txId, timeOut);
stopAndRemoveTimer(txId);
UserThread.execute(() -> callback.onTimeout(new TxBroadcastTimeoutException(tx, delayInSec, wallet)));
}, delayInSec);
UserThread.execute(() -> callback.onTimeout(new TxBroadcastTimeoutException(tx, timeOut, wallet)));
}, timeOut);
broadcastTimerMap.put(txId, timeoutTimer);
} else {
@ -129,7 +132,7 @@ public class TxBroadcaster {
UserThread.execute(() -> callback.onFailure(new TxBroadcastException("We got an onFailure from " +
"the peerGroup.broadcastTransaction callback.", throwable)));
}
});
}, MoreExecutors.directExecutor());
}
private static void stopAndRemoveTimer(String txId) {

View file

@ -37,8 +37,10 @@ import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Context;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.InsufficientMoneyException;
import org.bitcoinj.core.LegacyAddress;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.ScriptException;
import org.bitcoinj.core.listeners.TransactionConfidenceEventListener;
import org.bitcoinj.script.ScriptException;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
@ -52,6 +54,7 @@ import org.bitcoinj.crypto.KeyCrypterScrypt;
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.script.Script;
import org.bitcoinj.script.ScriptChunk;
import org.bitcoinj.script.ScriptPattern;
import org.bitcoinj.signers.TransactionSigner;
import org.bitcoinj.utils.Threading;
import org.bitcoinj.wallet.DecryptingKeyBag;
@ -61,18 +64,23 @@ import org.bitcoinj.wallet.KeyChain;
import org.bitcoinj.wallet.RedeemData;
import org.bitcoinj.wallet.SendRequest;
import org.bitcoinj.wallet.Wallet;
import org.bitcoinj.wallet.listeners.AbstractWalletEventListener;
import org.bitcoinj.wallet.listeners.WalletEventListener;
import org.bitcoinj.wallet.listeners.KeyChainEventListener;
import org.bitcoinj.wallet.listeners.ScriptsChangeEventListener;
import org.bitcoinj.wallet.listeners.WalletChangeEventListener;
import org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener;
import org.bitcoinj.wallet.listeners.WalletCoinsSentEventListener;
import org.bitcoinj.wallet.listeners.WalletReorganizeEventListener;
import javax.inject.Inject;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.KeyParameter;
import java.util.ArrayList;
import java.util.List;
@ -100,7 +108,7 @@ public abstract class WalletService {
protected final FeeService feeService;
protected final NetworkParameters params;
@SuppressWarnings("deprecation")
protected final WalletEventListener walletEventListener = new BisqWalletListener();
protected final BisqWalletListener walletEventListener = new BisqWalletListener();
protected final CopyOnWriteArraySet<AddressConfidenceListener> addressConfidenceListeners = new CopyOnWriteArraySet<>();
protected final CopyOnWriteArraySet<TxConfidenceListener> txConfidenceListeners = new CopyOnWriteArraySet<>();
protected final CopyOnWriteArraySet<BalanceListener> balanceListeners = new CopyOnWriteArraySet<>();
@ -133,9 +141,13 @@ public abstract class WalletService {
///////////////////////////////////////////////////////////////////////////////////////////
public void shutDown() {
if (wallet != null)
if (wallet != null) {
//noinspection deprecation
wallet.removeEventListener(walletEventListener);
wallet.removeCoinsReceivedEventListener(walletEventListener);
wallet.removeCoinsSentEventListener(walletEventListener);
wallet.removeReorganizeEventListener(walletEventListener);
wallet.removeTransactionConfidenceEventListener(walletEventListener);
}
}
@ -330,11 +342,14 @@ public abstract class WalletService {
// Broadcast tx
///////////////////////////////////////////////////////////////////////////////////////////
public void broadcastTx(Transaction tx, TxBroadcaster.Callback callback) {
TxBroadcaster.broadcastTx(wallet, walletsSetup.getPeerGroup(), tx, callback);
}
public void broadcastTx(Transaction tx, TxBroadcaster.Callback callback, int timeOut) {
TxBroadcaster.broadcastTx(wallet, walletsSetup.getPeerGroup(), tx, callback, timeOut);
}
///////////////////////////////////////////////////////////////////////////////////////////
// TransactionConfidence
@ -358,7 +373,7 @@ public abstract class WalletService {
if (wallet != null) {
Set<Transaction> transactions = wallet.getTransactions(false);
for (Transaction tx : transactions) {
if (tx.getHashAsString().equals(txId))
if (tx.getTxId().toString().equals(txId))
return tx.getConfidence();
}
}
@ -489,7 +504,7 @@ public abstract class WalletService {
ResultHandler resultHandler,
ErrorMessageHandler errorMessageHandler)
throws InsufficientMoneyException, AddressFormatException {
SendRequest sendRequest = SendRequest.emptyWallet(Address.fromBase58(params, toAddress));
SendRequest sendRequest = SendRequest.emptyWallet(LegacyAddress.fromBase58(params, toAddress));
sendRequest.fee = Coin.ZERO;
sendRequest.feePerKb = getTxFeeForWithdrawalPerByte().multiply(1000);
sendRequest.aesKey = aesKey;
@ -507,7 +522,7 @@ public abstract class WalletService {
log.error("emptyWallet onFailure " + t.toString());
errorMessageHandler.handleErrorMessage(t.getMessage());
}
});
}, MoreExecutors.directExecutor());
}
@ -537,16 +552,60 @@ public abstract class WalletService {
// Wallet delegates to avoid direct access to wallet outside the service class
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("deprecation")
public void addEventListener(WalletEventListener listener) {
//noinspection deprecation
wallet.addEventListener(listener, Threading.USER_THREAD);
public void addCoinsReceivedEventListener(WalletCoinsReceivedEventListener listener) {
wallet.addCoinsReceivedEventListener(Threading.USER_THREAD, listener);
}
@SuppressWarnings("deprecation")
public boolean removeEventListener(WalletEventListener listener) {
//noinspection deprecation
return wallet.removeEventListener(listener);
public void addCoinsSentEventListener(WalletCoinsSentEventListener listener) {
wallet.addCoinsSentEventListener(Threading.USER_THREAD, listener);
}
public void addReorganizeEventListener(WalletReorganizeEventListener listener) {
wallet.addReorganizeEventListener(Threading.USER_THREAD, listener);
}
public void addTransactionConfidenceEventListener(TransactionConfidenceEventListener listener) {
wallet.addTransactionConfidenceEventListener(Threading.USER_THREAD, listener);
}
public void addKeyChainEventListener(KeyChainEventListener listener) {
wallet.addKeyChainEventListener(Threading.USER_THREAD, listener);
}
public void addScriptChangeEventListener(ScriptsChangeEventListener listener) {
wallet.addScriptChangeEventListener(Threading.USER_THREAD, listener);
}
public void addChangeEventListener(WalletChangeEventListener listener) {
wallet.addChangeEventListener(Threading.USER_THREAD, listener);
}
public void removeCoinsReceivedEventListener(WalletCoinsReceivedEventListener listener) {
wallet.removeCoinsReceivedEventListener(listener);
}
public void removeCoinsSentEventListener(WalletCoinsSentEventListener listener) {
wallet.removeCoinsSentEventListener(listener);
}
public void removeReorganizeEventListener(WalletReorganizeEventListener listener) {
wallet.removeReorganizeEventListener(listener);
}
public void removeTransactionConfidenceEventListener(TransactionConfidenceEventListener listener) {
wallet.removeTransactionConfidenceEventListener(listener);
}
public void removeKeyChainEventListener(KeyChainEventListener listener) {
wallet.removeKeyChainEventListener(listener);
}
public void removeScriptChangeEventListener(ScriptsChangeEventListener listener) {
wallet.removeScriptChangeEventListener(listener);
}
public void removeChangeEventListener(WalletChangeEventListener listener) {
wallet.removeChangeEventListener(listener);
}
@SuppressWarnings("deprecation")
@ -679,8 +738,8 @@ public abstract class WalletService {
}
public static boolean isOutputScriptConvertibleToAddress(TransactionOutput output) {
return output.getScriptPubKey().isSentToAddress() ||
output.getScriptPubKey().isPayToScriptHash();
return ScriptPattern.isP2PKH(output.getScriptPubKey()) ||
ScriptPattern.isP2SH(output.getScriptPubKey());
}
@Nullable
@ -705,7 +764,7 @@ public abstract class WalletService {
Wallet wallet,
TransactionConfidence.Source source) throws VerificationException {
Transaction tx = new Transaction(wallet.getParams(), serializedTransaction);
Transaction walletTransaction = wallet.getTransaction(tx.getHash());
Transaction walletTransaction = wallet.getTransaction(tx.getTxId());
if (walletTransaction == null) {
// We need to recreate the transaction otherwise we get a null pointer...
@ -740,7 +799,7 @@ public abstract class WalletService {
///////////////////////////////////////////////////////////////////////////////////////////
@SuppressWarnings("deprecation")
public class BisqWalletListener extends AbstractWalletEventListener {
public class BisqWalletListener implements WalletCoinsReceivedEventListener, WalletCoinsSentEventListener, WalletReorganizeEventListener, TransactionConfidenceEventListener {
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
notifyBalanceListeners(tx);
@ -767,9 +826,9 @@ public abstract class WalletService {
}
txConfidenceListeners.stream()
.filter(txConfidenceListener -> tx != null &&
tx.getHashAsString() != null &&
tx.getTxId().toString() != null &&
txConfidenceListener != null &&
tx.getHashAsString().equals(txConfidenceListener.getTxID()))
tx.getTxId().toString().equals(txConfidenceListener.getTxID()))
.forEach(txConfidenceListener ->
txConfidenceListener.onTransactionConfidenceChanged(tx.getConfidence()));
}

View file

@ -34,7 +34,7 @@ import org.bitcoinj.wallet.Wallet;
import com.google.inject.Inject;
import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.KeyParameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -154,9 +154,11 @@ public class WalletsManager {
// We need to create another instance, otherwise the tx would trigger an invalid state exception
// if it gets committed 2 times
// We clone before commit to avoid unwanted side effects
final Transaction clonedTx = btcWalletService.getClonedTransaction(tx);
Transaction clonedTx = btcWalletService.getClonedTransaction(tx);
btcWalletService.commitTx(clonedTx);
bsqWalletService.commitTx(tx, txType);
bsqWalletService.broadcastTx(tx, callback);
// We use a short timeout as there are issues with BSQ txs. See comment in TxBroadcaster
bsqWalletService.broadcastTx(tx, callback, 1);
}
}

View file

@ -25,7 +25,7 @@ import com.google.protobuf.ByteString;
import org.bitcoinj.crypto.KeyCrypterScrypt;
import org.bitcoinj.wallet.Protos;
import org.spongycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.KeyParameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -222,7 +222,7 @@ public class AssetService implements DaoSetupService, DaoStateListener {
walletsManager.publishAndCommitBsqTx(transaction, TxType.ASSET_LISTING_FEE, new TxBroadcaster.Callback() {
@Override
public void onSuccess(Transaction transaction) {
log.info("Asset listing fee tx has been published. TxId={}", transaction.getHashAsString());
log.info("Asset listing fee tx has been published. TxId={}", transaction.getTxId().toString());
resultHandler.handleResult();
}

View file

@ -203,7 +203,7 @@ public class MyBlindVoteListService implements PersistedDataHost, DaoStateListen
byte[] opReturnData = getOpReturnData(encryptedVotes);
Coin blindVoteFee = BlindVoteConsensus.getFee(daoStateService, daoStateService.getChainHeight());
Transaction blindVoteTx = getBlindVoteTx(stake, blindVoteFee, opReturnData);
String blindVoteTxId = blindVoteTx.getHashAsString();
String blindVoteTxId = blindVoteTx.getTxId().toString();
byte[] encryptedMeritList = getEncryptedMeritList(blindVoteTxId, secretKey);
@ -337,7 +337,7 @@ public class MyBlindVoteListService implements PersistedDataHost, DaoStateListen
walletsManager.publishAndCommitBsqTx(blindVoteTx, TxType.BLIND_VOTE, new TxBroadcaster.Callback() {
@Override
public void onSuccess(Transaction transaction) {
log.info("BlindVote tx published. txId={}", transaction.getHashAsString());
log.info("BlindVote tx published. txId={}", transaction.getTxId().toString());
resultHandler.handleResult();
}

View file

@ -35,6 +35,7 @@ import javax.inject.Inject;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.util.ArrayList;
@ -135,7 +136,7 @@ public final class RepublishGovernanceDataHandler {
"Might be caused by an previous timeout.");
}
}
});
}, MoreExecutors.directExecutor());
}
private void connectToNextNode() {

View file

@ -28,9 +28,11 @@ import bisq.core.dao.state.model.blockchain.Tx;
import bisq.core.dao.state.model.blockchain.TxOutput;
import bisq.core.dao.state.model.blockchain.TxType;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutput;
import org.bitcoinj.script.ScriptPattern;
import javax.inject.Inject;
@ -101,7 +103,7 @@ public abstract class BondRepository<T extends Bond, R extends BondedAsset> impl
public static boolean isLockupTxUnconfirmed(BsqWalletService bsqWalletService, BondedAsset bondedAsset) {
return bsqWalletService.getPendingWalletTransactionsStream()
.map(transaction -> transaction.getOutputs().get(transaction.getOutputs().size() - 1))
.filter(lastOutput -> lastOutput.getScriptPubKey().isOpReturn())
.filter(lastOutput -> ScriptPattern.isOpReturn(lastOutput.getScriptPubKey()))
.map(lastOutput -> lastOutput.getScriptPubKey().getChunks())
.filter(chunks -> chunks.size() > 1)
.map(chunks -> chunks.get(1).data)
@ -117,7 +119,8 @@ public abstract class BondRepository<T extends Bond, R extends BondedAsset> impl
.filter(transactionOutput -> transactionOutput.getIndex() == 0) // The output at the lockupTx must be index 0
.map(TransactionOutput::getParentTransaction)
.filter(Objects::nonNull)
.map(Transaction::getHashAsString)
.map(Transaction::getTxId)
.map(Sha256Hash::toString)
.map(lockupTxId -> daoStateService.getLockupOpReturnTxOutput(lockupTxId).orElse(null))
.filter(Objects::nonNull)
.map(BaseTxOutput::getOpReturnData)

View file

@ -76,7 +76,7 @@ public class LockupTxService {
walletsManager.publishAndCommitBsqTx(lockupTx, TxType.LOCKUP, new TxBroadcaster.Callback() {
@Override
public void onSuccess(Transaction transaction) {
resultHandler.accept(transaction.getHashAsString());
resultHandler.accept(transaction.getTxId().toString());
}
@Override

View file

@ -27,6 +27,7 @@ import bisq.core.dao.state.model.governance.Proposal;
import bisq.core.dao.state.model.governance.Role;
import bisq.core.dao.state.model.governance.RoleProposal;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
import javax.inject.Inject;
@ -62,7 +63,8 @@ public class BondedRolesRepository extends BondRepository<BondedRole, Role> {
public boolean isMyRole(Role role) {
Set<String> myWalletTransactionIds = bsqWalletService.getClonedWalletTransactions().stream()
.map(Transaction::getHashAsString)
.map(Transaction::getTxId)
.map(Sha256Hash::toString)
.collect(Collectors.toSet());
return getAcceptedBondedRoleProposalStream()
.filter(roleProposal -> roleProposal.getRole().equals(role))

View file

@ -76,7 +76,7 @@ public class UnlockTxService {
walletsManager.publishAndCommitBsqTx(unlockTx, TxType.UNLOCK, new TxBroadcaster.Callback() {
@Override
public void onSuccess(Transaction transaction) {
resultHandler.accept(transaction.getHashAsString());
resultHandler.accept(transaction.getTxId().toString());
}
@Override

View file

@ -153,7 +153,7 @@ public class ProofOfBurnService implements DaoSetupService, DaoStateListener {
walletsManager.publishAndCommitBsqTx(transaction, TxType.PROOF_OF_BURN, new TxBroadcaster.Callback() {
@Override
public void onSuccess(Transaction transaction) {
log.info("Proof of burn tx has been published. TxId={}", transaction.getHashAsString());
log.info("Proof of burn tx has been published. TxId={}", transaction.getTxId().toString());
resultHandler.handleResult();
}
@ -163,7 +163,7 @@ public class ProofOfBurnService implements DaoSetupService, DaoStateListener {
}
});
MyProofOfBurn myProofOfBurn = new MyProofOfBurn(transaction.getHashAsString(), preImageAsString);
MyProofOfBurn myProofOfBurn = new MyProofOfBurn(transaction.getTxId().toString(), preImageAsString);
myProofOfBurnListService.addMyProofOfBurn(myProofOfBurn);
}

View file

@ -74,7 +74,7 @@ public abstract class BaseProposalFactory<R extends Proposal> {
R proposal = createProposalWithoutTxId();
proposalValidator.validateDataFields(proposal);
Transaction transaction = createTransaction(proposal);
final Proposal proposalWithTxId = proposal.cloneProposalAndAddTxId(transaction.getHashAsString());
final Proposal proposalWithTxId = proposal.cloneProposalAndAddTxId(transaction.getTxId().toString());
return new ProposalWithTransaction(proposalWithTxId, transaction);
}

View file

@ -137,7 +137,7 @@ public class MyProposalListService implements PersistedDataHost, DaoStateListene
walletsManager.publishAndCommitBsqTx(transaction, proposal.getTxType(), new TxBroadcaster.Callback() {
@Override
public void onSuccess(Transaction transaction) {
log.info("Proposal tx has been published. TxId={}", transaction.getHashAsString());
log.info("Proposal tx has been published. TxId={}", transaction.getTxId().toString());
resultHandler.handleResult();
}

View file

@ -239,7 +239,7 @@ public class VoteRevealService implements DaoStateListener, DaoSetupService {
// We don't want to wait for a successful broadcast to avoid issues if the broadcast succeeds delayed or at
// next startup but the tx was actually broadcast.
myVoteListService.applyRevealTxId(myVote, voteRevealTx.getHashAsString());
myVoteListService.applyRevealTxId(myVote, voteRevealTx.getTxId().toString());
} catch (IOException | WalletException | TransactionVerificationException
| InsufficientMoneyException e) {
voteRevealExceptions.add(new VoteRevealException("Exception at calling revealVote.",
@ -254,7 +254,7 @@ public class VoteRevealService implements DaoStateListener, DaoSetupService {
@Override
public void onSuccess(Transaction transaction) {
log.info("voteRevealTx successfully broadcast.");
voteRevealTxPublishedListeners.forEach(l -> l.onVoteRevealTxPublished(transaction.getHashAsString()));
voteRevealTxPublishedListeners.forEach(l -> l.onVoteRevealTxPublished(transaction.getTxId().toString()));
}
@Override

View file

@ -33,6 +33,7 @@ import bisq.common.proto.network.NetworkEnvelope;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.util.Optional;
@ -151,7 +152,7 @@ abstract class RequestStateHashesHandler<Req extends GetStateHashesRequest, Res
"Might be caused by an previous timeout.");
}
}
});
}, MoreExecutors.directExecutor());
} else {
log.warn("We have stopped already. We ignore that requestProposalsHash call.");
}

View file

@ -41,6 +41,7 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.nio.file.Paths;
@ -167,7 +168,7 @@ public class ExportJsonFilesService implements DaoSetupService {
log.error(throwable.toString());
throwable.printStackTrace();
}
});
}, MoreExecutors.directExecutor());
}
}

View file

@ -52,6 +52,7 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.List;
import java.util.Properties;
@ -175,7 +176,7 @@ public class RpcService {
public void onFailure(@NotNull Throwable throwable) {
UserThread.execute(() -> errorHandler.accept(throwable));
}
});
}, MoreExecutors.directExecutor());
}
void addNewBtcBlockHandler(Consumer<RawBlock> btcBlockHandler,
@ -217,7 +218,7 @@ public class RpcService {
public void onFailure(@NotNull Throwable throwable) {
UserThread.execute(() -> errorHandler.accept(throwable));
}
});
}, MoreExecutors.directExecutor());
}
void requestBtcBlock(int blockHeight,
@ -250,7 +251,7 @@ public class RpcService {
log.error("Error at requestBtcBlock: blockHeight={}", blockHeight);
UserThread.execute(() -> errorHandler.accept(throwable));
}
});
}, MoreExecutors.directExecutor());
}

View file

@ -32,6 +32,7 @@ import bisq.common.UserThread;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.util.LinkedList;
@ -130,7 +131,7 @@ class GetBlocksRequestHandler {
log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call.");
}
}
});
}, MoreExecutors.directExecutor());
}
public void stop() {

View file

@ -33,6 +33,7 @@ import bisq.common.proto.network.NetworkEnvelope;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.util.Random;
@ -153,7 +154,7 @@ public class RequestBlocksHandler implements MessageListener {
"Might be caused by a previous timeout.");
}
}
});
}, MoreExecutors.directExecutor());
} else {
log.warn("We have stopped already. We ignore that requestData call.");
}

View file

@ -30,6 +30,7 @@ import bisq.common.util.CollectionUtils;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.LegacyAddress;
import java.util.Date;
import java.util.Map;
@ -120,7 +121,7 @@ public final class CompensationProposal extends Proposal implements IssuanceProp
public Address getAddress() throws AddressFormatException {
// Remove leading 'B'
String underlyingBtcAddress = bsqAddress.substring(1, bsqAddress.length());
return Address.fromBase58(Config.baseCurrencyNetworkParameters(), underlyingBtcAddress);
return LegacyAddress.fromBase58(Config.baseCurrencyNetworkParameters(), underlyingBtcAddress);
}

View file

@ -30,6 +30,7 @@ import bisq.common.util.CollectionUtils;
import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.LegacyAddress;
import java.util.Date;
import java.util.Map;
@ -120,7 +121,7 @@ public final class ReimbursementProposal extends Proposal implements IssuancePro
public Address getAddress() throws AddressFormatException {
// Remove leading 'B'
String underlyingBtcAddress = bsqAddress.substring(1, bsqAddress.length());
return Address.fromBase58(Config.baseCurrencyNetworkParameters(), underlyingBtcAddress);
return LegacyAddress.fromBase58(Config.baseCurrencyNetworkParameters(), underlyingBtcAddress);
}

View file

@ -47,7 +47,7 @@ public final class UnconfirmedTxOutput implements PersistablePayload, ImmutableD
if (parentTransaction != null) {
return new UnconfirmedTxOutput(transactionOutput.getIndex(),
transactionOutput.getValue().value,
parentTransaction.getHashAsString());
parentTransaction.getTxId().toString());
} else {
log.warn("parentTransaction of transactionOutput is null. " +
"This must not happen. " +

View file

@ -45,7 +45,7 @@ import javax.inject.Named;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import org.spongycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Base64;
import java.security.PublicKey;

Some files were not shown because too many files have changed in this diff Show more