mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 23:18:17 +01:00
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:
commit
c1850cb47b
153 changed files with 1214 additions and 1202 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ public class Actinium extends Coin {
|
|||
public ActiniumParams() {
|
||||
addressHeader = 53;
|
||||
p2shHeader = 55;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class Adeptio extends Coin {
|
|||
public AdeptioParams() {
|
||||
addressHeader = 23;
|
||||
p2shHeader = 16;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ public class Australiacash extends Coin {
|
|||
public AustraliacashParams() {
|
||||
addressHeader = 23;
|
||||
p2shHeader = 5;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ public class BitcoinRhodium extends Coin {
|
|||
public BitcoinRhodiumParams() {
|
||||
addressHeader = 61;
|
||||
p2shHeader = 123;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ public class Bitmark extends Coin {
|
|||
public BitmarkParams() {
|
||||
addressHeader = 85;
|
||||
p2shHeader = 5;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ public class Chaucha extends Coin {
|
|||
public ChauchaParams() {
|
||||
addressHeader = 88;
|
||||
p2shHeader = 50;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class Credits extends Coin {
|
|||
public CreditsParams() {
|
||||
addressHeader = 28;
|
||||
p2shHeader = 5;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,7 +50,6 @@ public class DSTRA extends Coin {
|
|||
public DSTRAParams() {
|
||||
addressHeader = 30;
|
||||
p2shHeader = 33;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ public class DeepOnion extends Coin {
|
|||
super();
|
||||
addressHeader = 31;
|
||||
p2shHeader = 78;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ public class Dextro extends Coin {
|
|||
super();
|
||||
addressHeader = 30;
|
||||
p2shHeader = 90;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ public class Doichain extends Coin {
|
|||
public DoichainParams() {
|
||||
addressHeader = 52;
|
||||
p2shHeader = 13;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class Donu extends Coin {
|
|||
public DonuParams() {
|
||||
addressHeader = 53;
|
||||
p2shHeader = 5;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ public class Faircoin extends Coin {
|
|||
public FaircoinParams() {
|
||||
addressHeader = 95;
|
||||
p2shHeader = 36;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ public class Fujicoin extends Coin {
|
|||
public FujicoinParams() {
|
||||
addressHeader = 36;
|
||||
p2shHeader = 16;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ public class GambleCoin extends Coin {
|
|||
super();
|
||||
addressHeader = 28;
|
||||
p2shHeader = 18;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ public class Genesis extends Coin {
|
|||
public GenesisParams() {
|
||||
addressHeader = 28;
|
||||
p2shHeader = 63;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ public class Helium extends Coin {
|
|||
public HeliumParams() {
|
||||
addressHeader = 63;
|
||||
p2shHeader = 5;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ public class IdaPay extends Coin {
|
|||
super();
|
||||
addressHeader = 29;
|
||||
p2shHeader = 36;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ public class Kekcoin extends Coin {
|
|||
super();
|
||||
addressHeader = 45;
|
||||
p2shHeader = 88;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ public class Lytix extends Coin {
|
|||
public LytixParams() {
|
||||
addressHeader = 19;
|
||||
p2shHeader = 11;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class MobitGlobal extends Coin {
|
|||
public MobitGlobalParams() {
|
||||
addressHeader = 50;
|
||||
p2shHeader = 110;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class MonetaryUnit extends Coin {
|
|||
public MonetaryUnitParams() {
|
||||
addressHeader = 16;
|
||||
p2shHeader = 76;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ public class Myce extends Coin {
|
|||
public MyceParams() {
|
||||
addressHeader = 50;
|
||||
p2shHeader = 85;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class PIVX extends Coin {
|
|||
public PIVXParams() {
|
||||
addressHeader = 30;
|
||||
p2shHeader = 13;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class PZDC extends Coin {
|
|||
public PZDCParams() {
|
||||
addressHeader = 55;
|
||||
p2shHeader = 13;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -33,7 +33,6 @@ public class Pinkcoin extends Coin {
|
|||
public PinkcoinParams() {
|
||||
addressHeader = 3;
|
||||
p2shHeader = 28;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class QMCoin extends Coin {
|
|||
public QMCoinParams() {
|
||||
addressHeader = 58;
|
||||
p2shHeader = 120;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ public class Qbase extends Coin {
|
|||
public QbaseParams() {
|
||||
addressHeader = 25;
|
||||
p2shHeader = 5;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ public class Radium extends Coin {
|
|||
super();
|
||||
addressHeader = 76;
|
||||
p2shHeader = 58;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,7 +50,6 @@ public class SUB1X extends Coin {
|
|||
public SUB1XParams() {
|
||||
addressHeader = 80;
|
||||
p2shHeader = 13;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ public class Spectrecoin extends Coin {
|
|||
public SpectrecoinParams() {
|
||||
addressHeader = 63;
|
||||
p2shHeader = 136;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ public class UnitedCommunityCoin extends Coin {
|
|||
super();
|
||||
addressHeader = 68;
|
||||
p2shHeader = 18;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public class Veil extends Coin {
|
|||
public VeilParams() {
|
||||
addressHeader = 70;
|
||||
p2shHeader = 5;
|
||||
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
23
build.gradle
23
build.gradle
|
@ -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')
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
46
core/src/main/java/bisq/core/app/AsciiLogo.java
Normal file
46
core/src/main/java/bisq/core/app/AsciiLogo.java
Normal 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");
|
||||
}
|
||||
}
|
|
@ -102,6 +102,7 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected void doExecute() {
|
||||
AsciiLogo.showAsciiLogo();
|
||||
configUserThread();
|
||||
CoreSetup.setup(config);
|
||||
addCapabilities();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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() {
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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. " +
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue