mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 15:00:30 +01:00
Only use accumulated hash in Witness object
This commit is contained in:
parent
a33923cc1e
commit
e56fc44956
43 changed files with 666 additions and 713 deletions
|
@ -248,7 +248,7 @@ public class CurrencyUtil {
|
|||
if (isCryptoCurrency(currencyCode) && cryptoCurrencyOptional.isPresent()) {
|
||||
return Optional.of(cryptoCurrencyOptional.get());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
return Optional.<TradeCurrency>empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import com.google.gson.*;
|
|||
import io.bisq.common.crypto.LimitedKeyStrengthException;
|
||||
import javafx.scene.input.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.bitcoinj.core.Utils;
|
||||
|
@ -56,11 +57,11 @@ public class Utilities {
|
|||
// TODO check out Jackson lib
|
||||
public static String objectToJson(Object object) {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setExclusionStrategies(new AnnotationExclusionStrategy())
|
||||
.setExclusionStrategies(new AnnotationExclusionStrategy())
|
||||
/*.excludeFieldsWithModifiers(Modifier.TRANSIENT)*/
|
||||
/* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)*/
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
return gson.toJson(object);
|
||||
}
|
||||
|
||||
|
@ -76,11 +77,11 @@ public class Utilities {
|
|||
int maximumPoolSize,
|
||||
long keepAliveTimeInSec) {
|
||||
final ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||
.setNameFormat(name)
|
||||
.setDaemon(true)
|
||||
.build();
|
||||
.setNameFormat(name)
|
||||
.setDaemon(true)
|
||||
.build();
|
||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTimeInSec,
|
||||
TimeUnit.SECONDS, new ArrayBlockingQueue<>(maximumPoolSize), threadFactory);
|
||||
TimeUnit.SECONDS, new ArrayBlockingQueue<>(maximumPoolSize), threadFactory);
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
executor.setRejectedExecutionHandler((r, e) -> log.debug("RejectedExecutionHandler called"));
|
||||
return executor;
|
||||
|
@ -93,10 +94,10 @@ public class Utilities {
|
|||
int maximumPoolSize,
|
||||
long keepAliveTimeInSec) {
|
||||
final ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||
.setNameFormat(name)
|
||||
.setDaemon(true)
|
||||
.setPriority(Thread.MIN_PRIORITY)
|
||||
.build();
|
||||
.setNameFormat(name)
|
||||
.setDaemon(true)
|
||||
.setPriority(Thread.MIN_PRIORITY)
|
||||
.build();
|
||||
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
|
||||
executor.setKeepAliveTime(keepAliveTimeInSec, TimeUnit.SECONDS);
|
||||
executor.allowCoreThreadTimeOut(true);
|
||||
|
@ -134,8 +135,8 @@ public class Utilities {
|
|||
String arch = System.getenv("PROCESSOR_ARCHITECTURE");
|
||||
String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432");
|
||||
return arch.endsWith("64")
|
||||
|| wow64Arch != null && wow64Arch.endsWith("64")
|
||||
? "64" : "32";
|
||||
|| wow64Arch != null && wow64Arch.endsWith("64")
|
||||
? "64" : "32";
|
||||
} else if (osArch.contains("arm")) {
|
||||
// armv8 is 64 bit, armv7l is 32 bit
|
||||
return osArch.contains("64") || osArch.contains("v8") ? "64" : "32";
|
||||
|
@ -148,12 +149,12 @@ public class Utilities {
|
|||
|
||||
public static void printSysInfo() {
|
||||
log.info("System info: os.name={}; os.version={}; os.arch={}; sun.arch.data.model={}; JRE={}; JVM={}",
|
||||
System.getProperty("os.name"),
|
||||
System.getProperty("os.version"),
|
||||
System.getProperty("os.arch"),
|
||||
getJVMArchitecture(),
|
||||
(System.getProperty("java.runtime.version", "-") + " (" + System.getProperty("java.vendor", "-") + ")"),
|
||||
(System.getProperty("java.vm.version", "-") + " (" + System.getProperty("java.vm.name", "-") + ")")
|
||||
System.getProperty("os.name"),
|
||||
System.getProperty("os.version"),
|
||||
System.getProperty("os.arch"),
|
||||
getJVMArchitecture(),
|
||||
(System.getProperty("java.runtime.version", "-") + " (" + System.getProperty("java.vendor", "-") + ")"),
|
||||
(System.getProperty("java.vm.version", "-") + " (" + System.getProperty("java.vm.name", "-") + ")")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -175,8 +176,8 @@ public class Utilities {
|
|||
|
||||
public static void openURI(URI uri) throws IOException {
|
||||
if (!isLinux()
|
||||
&& isDesktopSupported()
|
||||
&& getDesktop().isSupported(Action.BROWSE)) {
|
||||
&& isDesktopSupported()
|
||||
&& getDesktop().isSupported(Action.BROWSE)) {
|
||||
getDesktop().browse(uri);
|
||||
} else {
|
||||
// Maybe Application.HostServices works in those cases?
|
||||
|
@ -192,8 +193,8 @@ public class Utilities {
|
|||
|
||||
public static void openFile(File file) throws IOException {
|
||||
if (!isLinux()
|
||||
&& isDesktopSupported()
|
||||
&& getDesktop().isSupported(Action.OPEN)) {
|
||||
&& isDesktopSupported()
|
||||
&& getDesktop().isSupported(Action.OPEN)) {
|
||||
getDesktop().open(file);
|
||||
} else {
|
||||
// Maybe Application.HostServices works in those cases?
|
||||
|
@ -258,7 +259,7 @@ public class Utilities {
|
|||
|
||||
public static <T> T jsonToObject(String jsonString, Class<T> classOfT) {
|
||||
Gson gson =
|
||||
new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting().create();
|
||||
new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).setPrettyPrinting().create();
|
||||
return gson.fromJson(jsonString, classOfT);
|
||||
}
|
||||
|
||||
|
@ -372,13 +373,29 @@ public class Utilities {
|
|||
|
||||
public static boolean isCtrlPressed(KeyCode keyCode, KeyEvent keyEvent) {
|
||||
return new KeyCodeCombination(keyCode, KeyCombination.SHORTCUT_DOWN).match(keyEvent) ||
|
||||
new KeyCodeCombination(keyCode, KeyCombination.CONTROL_DOWN).match(keyEvent);
|
||||
new KeyCodeCombination(keyCode, KeyCombination.CONTROL_DOWN).match(keyEvent);
|
||||
}
|
||||
|
||||
public static boolean isAltPressed(KeyCode keyCode, KeyEvent keyEvent) {
|
||||
return new KeyCodeCombination(keyCode, KeyCombination.ALT_DOWN).match(keyEvent);
|
||||
}
|
||||
|
||||
public static byte[] concatenateByteArrays(byte[] array1, byte[] array2) {
|
||||
return ArrayUtils.addAll(array1, array2);
|
||||
}
|
||||
|
||||
public static byte[] concatenateByteArrays(byte[] array1, byte[] array2, byte[] array3) {
|
||||
return ArrayUtils.addAll(array1, ArrayUtils.addAll(array2, array3));
|
||||
}
|
||||
|
||||
public static byte[] concatenateByteArrays(byte[] array1, byte[] array2, byte[] array3, byte[] array4) {
|
||||
return ArrayUtils.addAll(array1, ArrayUtils.addAll(array2, ArrayUtils.addAll(array3, array4)));
|
||||
}
|
||||
|
||||
public static byte[] concatenateByteArrays(byte[] array1, byte[] array2, byte[] array3, byte[] array4, byte[] array5) {
|
||||
return ArrayUtils.addAll(array1, ArrayUtils.addAll(array2, ArrayUtils.addAll(array3, ArrayUtils.addAll(array4, array5))));
|
||||
}
|
||||
|
||||
private static class AnnotationExclusionStrategy implements ExclusionStrategy {
|
||||
@Override
|
||||
public boolean shouldSkipField(FieldAttributes f) {
|
||||
|
@ -503,6 +520,6 @@ public class Utilities {
|
|||
final String name = System.getProperty("java.runtime.name");
|
||||
final String ver = System.getProperty("java.version");
|
||||
return name != null && name.equals("Java(TM) SE Runtime Environment")
|
||||
&& ver != null && (ver.startsWith("1.7") || ver.startsWith("1.8"));
|
||||
&& ver != null && (ver.startsWith("1.7") || ver.startsWith("1.8"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ message NetworkEnvelope {
|
|||
GetBsqBlocksRequest get_bsq_blocks_request = 28;
|
||||
GetBsqBlocksResponse get_bsq_blocks_response = 29;
|
||||
NewBsqBlockBroadcastMessage new_bsq_block_broadcast_message = 30;
|
||||
|
||||
|
||||
AddPersistableNetworkPayloadMessage add_persistable_network_payload_message = 31;
|
||||
}
|
||||
}
|
||||
|
@ -131,10 +131,10 @@ message OfferAvailabilityResponse {
|
|||
}
|
||||
|
||||
message RefreshOfferMessage {
|
||||
bytes hash_of_data_and_seq_nr = 1;
|
||||
bytes signature = 2;
|
||||
bytes hash_of_payload = 3;
|
||||
int32 sequence_number = 4;
|
||||
bytes hash_of_data_and_seq_nr = 1;
|
||||
bytes signature = 2;
|
||||
bytes hash_of_payload = 3;
|
||||
int32 sequence_number = 4;
|
||||
}
|
||||
|
||||
|
||||
|
@ -195,8 +195,9 @@ message PayDepositRequest {
|
|||
NodeAddress arbitrator_node_address = 19;
|
||||
NodeAddress mediator_node_address = 20;
|
||||
string uid = 21;
|
||||
bytes account_age_witness_nonce = 22;
|
||||
bytes account_age_witness_signature_of_nonce = 23;
|
||||
bytes account_age_witness_signature_of_account_data = 22;
|
||||
bytes account_age_witness_nonce = 23;
|
||||
bytes account_age_witness_signature_of_nonce = 24;
|
||||
}
|
||||
|
||||
message PublishDepositTxRequest {
|
||||
|
@ -211,8 +212,9 @@ message PublishDepositTxRequest {
|
|||
bytes maker_multi_sig_pub_key = 9;
|
||||
NodeAddress sender_node_address = 10;
|
||||
string uid = 11;
|
||||
bytes account_age_witness_nonce = 12;
|
||||
bytes account_age_witness_signature_of_nonce = 13;
|
||||
bytes account_age_witness_signature_of_account_data = 12;
|
||||
bytes account_age_witness_nonce = 13;
|
||||
bytes account_age_witness_signature_of_nonce = 14;
|
||||
}
|
||||
|
||||
message DepositTxPublishedMessage {
|
||||
|
@ -498,7 +500,7 @@ message Tx {
|
|||
int64 burnt_fee = 4;
|
||||
TxType tx_type = 5;
|
||||
}
|
||||
|
||||
|
||||
message BsqBlock {
|
||||
int32 height = 1;
|
||||
string hash = 2;
|
||||
|
@ -560,7 +562,7 @@ message Filter {
|
|||
bytes owner_pub_key_bytes = 5;
|
||||
map<string, string> extra_data = 6;
|
||||
repeated string banned_currencies = 7;
|
||||
repeated string banned_payment_methods = 8;
|
||||
repeated string banned_payment_methods = 8;
|
||||
}
|
||||
|
||||
message TradeStatistics {
|
||||
|
@ -606,7 +608,7 @@ message OfferPayload {
|
|||
double market_price_margin = 7;
|
||||
bool use_market_based_price = 8;
|
||||
int64 amount = 9;
|
||||
int64 min_amount = 10;
|
||||
int64 min_amount = 10;
|
||||
string base_currency_code = 11;
|
||||
string counter_currency_code = 12;
|
||||
repeated NodeAddress arbitrator_node_addresses = 13;
|
||||
|
@ -661,9 +663,7 @@ message CompensationRequestPayload {
|
|||
|
||||
message AccountAgeWitness {
|
||||
bytes hash = 1;
|
||||
bytes sig_pub_key_hash = 2;
|
||||
bytes signature = 3;
|
||||
int64 date = 4;
|
||||
int64 date = 2;
|
||||
}
|
||||
|
||||
|
||||
|
@ -926,20 +926,20 @@ message PersistableEnvelope {
|
|||
PeerList peer_list = 3;
|
||||
AddressEntryList address_entry_list = 4;
|
||||
NavigationPath navigation_path = 5;
|
||||
|
||||
|
||||
TradableList tradable_list = 6;
|
||||
TradeStatisticsList trade_statistics_list = 7;
|
||||
DisputeList dispute_list = 8;
|
||||
|
||||
|
||||
PreferencesPayload preferences_payload = 9;
|
||||
UserPayload user_payload = 10;
|
||||
PaymentAccountList payment_account_list = 11;
|
||||
|
||||
|
||||
// TODO not fully implemented yet
|
||||
CompensationRequestPayload compensation_request_payload = 12;
|
||||
VoteItemsList vote_items_list = 13;
|
||||
BsqChainState bsq_chain_state = 14;
|
||||
|
||||
|
||||
PersistableNetworkPayloadList persistable_network_payload_list = 15;
|
||||
}
|
||||
}
|
||||
|
@ -1198,8 +1198,9 @@ message TradingPeer {
|
|||
repeated RawTransactionInput raw_transaction_inputs = 9;
|
||||
int64 change_output_value = 10;
|
||||
string change_output_address = 11;
|
||||
bytes account_age_witness_nonce = 12;
|
||||
bytes account_age_witness_signature_of_nonce = 13;
|
||||
bytes account_age_witness_signature_of_account_data = 12;
|
||||
bytes account_age_witness_nonce = 13;
|
||||
bytes account_age_witness_signature_of_nonce = 14;
|
||||
}
|
||||
|
||||
message AccountAgeWitnessMap {
|
||||
|
|
35
common/src/test/java/io/bisq/common/util/UtilitiesTest.java
Normal file
35
common/src/test/java/io/bisq/common/util/UtilitiesTest.java
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 io.bisq.common.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class UtilitiesTest {
|
||||
|
||||
@Test
|
||||
public void testConcatenateByteArrays() {
|
||||
assertTrue(Arrays.equals(new byte[]{0x01, 0x02}, Utilities.concatenateByteArrays(new byte[]{0x01}, new byte[]{0x02})));
|
||||
assertTrue(Arrays.equals(new byte[]{0x01, 0x02, 0x03}, Utilities.concatenateByteArrays(new byte[]{0x01}, new byte[]{0x02}, new byte[]{0x03})));
|
||||
assertTrue(Arrays.equals(new byte[]{0x01, 0x02, 0x03, 0x04}, Utilities.concatenateByteArrays(new byte[]{0x01}, new byte[]{0x02}, new byte[]{0x03}, new byte[]{0x04})));
|
||||
assertTrue(Arrays.equals(new byte[]{0x01, 0x02, 0x03, 0x04, 0x05}, Utilities.concatenateByteArrays(new byte[]{0x01}, new byte[]{0x02}, new byte[]{0x03}, new byte[]{0x04}, new byte[]{0x05})));
|
||||
}
|
||||
}
|
|
@ -787,7 +787,7 @@ public class BtcWalletService extends WalletService {
|
|||
throw new AddressEntryException("No Addresses for withdraw found in our wallet");
|
||||
|
||||
sendRequest.coinSelector = new BtcCoinSelector(walletsSetup.getAddressesFromAddressEntries(addressEntries));
|
||||
Optional<AddressEntry> addressEntryOptional = Optional.empty();
|
||||
Optional<AddressEntry> addressEntryOptional = Optional.<AddressEntry>empty();
|
||||
AddressEntry changeAddressAddressEntry = null;
|
||||
if (changeAddress != null)
|
||||
addressEntryOptional = findAddressEntry(changeAddress, AddressEntry.Context.AVAILABLE);
|
||||
|
|
|
@ -105,16 +105,16 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
public void checkOfferAvailability(OfferAvailabilityModel model, ResultHandler resultHandler,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
availabilityProtocol = new OfferAvailabilityProtocol(model,
|
||||
() -> {
|
||||
cancelAvailabilityRequest();
|
||||
resultHandler.handleResult();
|
||||
},
|
||||
(errorMessage) -> {
|
||||
if (availabilityProtocol != null)
|
||||
availabilityProtocol.cancel();
|
||||
log.error(errorMessage);
|
||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
});
|
||||
() -> {
|
||||
cancelAvailabilityRequest();
|
||||
resultHandler.handleResult();
|
||||
},
|
||||
(errorMessage) -> {
|
||||
if (availabilityProtocol != null)
|
||||
availabilityProtocol.cancel();
|
||||
log.error(errorMessage);
|
||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
});
|
||||
availabilityProtocol.sendOfferAvailabilityRequest();
|
||||
}
|
||||
|
||||
|
@ -134,28 +134,28 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
double marketPriceMargin = offerPayload.getMarketPriceMargin();
|
||||
if (CurrencyUtil.isCryptoCurrency(currencyCode)) {
|
||||
factor = getDirection() == OfferPayload.Direction.SELL ?
|
||||
1 - marketPriceMargin : 1 + marketPriceMargin;
|
||||
1 - marketPriceMargin : 1 + marketPriceMargin;
|
||||
} else {
|
||||
factor = getDirection() == OfferPayload.Direction.BUY ?
|
||||
1 - marketPriceMargin : 1 + marketPriceMargin;
|
||||
1 - marketPriceMargin : 1 + marketPriceMargin;
|
||||
}
|
||||
double marketPriceAsDouble = marketPrice.getPrice();
|
||||
double targetPriceAsDouble = marketPriceAsDouble * factor;
|
||||
try {
|
||||
int precision = CurrencyUtil.isCryptoCurrency(currencyCode) ?
|
||||
Altcoin.SMALLEST_UNIT_EXPONENT :
|
||||
Fiat.SMALLEST_UNIT_EXPONENT;
|
||||
Altcoin.SMALLEST_UNIT_EXPONENT :
|
||||
Fiat.SMALLEST_UNIT_EXPONENT;
|
||||
double scaled = MathUtils.scaleUpByPowerOf10(targetPriceAsDouble, precision);
|
||||
final long roundedToLong = MathUtils.roundDoubleToLong(scaled);
|
||||
return Price.valueOf(currencyCode, roundedToLong);
|
||||
} catch (Exception e) {
|
||||
log.error("Exception at getPrice / parseToFiat: " + e.toString() + "\n" +
|
||||
"That case should never happen.");
|
||||
"That case should never happen.");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
log.debug("We don't have a market price.\n" +
|
||||
"That case could only happen if you don't have a price feed.");
|
||||
"That case could only happen if you don't have a price feed.");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
|
@ -164,7 +164,7 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
}
|
||||
|
||||
public void checkTradePriceTolerance(long takersTradePrice) throws TradePriceOutOfToleranceException,
|
||||
MarketPriceNotAvailableException, IllegalArgumentException {
|
||||
MarketPriceNotAvailableException, IllegalArgumentException {
|
||||
Price tradePrice = Price.valueOf(getCurrencyCode(), takersTradePrice);
|
||||
Price offerPrice = getPrice();
|
||||
if (offerPrice == null)
|
||||
|
@ -179,8 +179,8 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
// from one provider.
|
||||
if (Math.abs(1 - factor) > 0.01) {
|
||||
String msg = "Taker's trade price is too far away from our calculated price based on the market price.\n" +
|
||||
"tradePrice=" + tradePrice.getValue() + "\n" +
|
||||
"offerPrice=" + offerPrice.getValue();
|
||||
"tradePrice=" + tradePrice.getValue() + "\n" +
|
||||
"offerPrice=" + offerPrice.getValue();
|
||||
log.warn(msg);
|
||||
throw new TradePriceOutOfToleranceException(msg);
|
||||
}
|
||||
|
@ -270,8 +270,8 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
|
||||
public PaymentMethod getPaymentMethod() {
|
||||
return new PaymentMethod(offerPayload.getPaymentMethodId(),
|
||||
offerPayload.getMaxTradePeriod(),
|
||||
Coin.valueOf(offerPayload.getMaxTradeLimit()));
|
||||
offerPayload.getMaxTradePeriod(),
|
||||
Coin.valueOf(offerPayload.getMaxTradeLimit()));
|
||||
}
|
||||
|
||||
// utils
|
||||
|
@ -302,11 +302,11 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
}
|
||||
|
||||
|
||||
public Optional<String> getAccountAgeWitnessHash() {
|
||||
public Optional<String> getAccountAgeWitnessHashAsHex() {
|
||||
if (getExtraDataMap() != null && getExtraDataMap().containsKey(OfferPayload.ACCOUNT_AGE_WITNESS_HASH))
|
||||
return Optional.of(getExtraDataMap().get(OfferPayload.ACCOUNT_AGE_WITNESS_HASH));
|
||||
else
|
||||
return Optional.empty();
|
||||
return Optional.<String>empty();
|
||||
}
|
||||
|
||||
// domain properties
|
||||
|
@ -365,8 +365,8 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
|
||||
public String getCurrencyCode() {
|
||||
return CurrencyUtil.isCryptoCurrency(offerPayload.getBaseCurrencyCode()) ?
|
||||
offerPayload.getBaseCurrencyCode() :
|
||||
offerPayload.getCounterCurrencyCode();
|
||||
offerPayload.getBaseCurrencyCode() :
|
||||
offerPayload.getCounterCurrencyCode();
|
||||
}
|
||||
|
||||
public long getProtocolVersion() {
|
||||
|
@ -473,9 +473,9 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "Offer{" +
|
||||
"getErrorMessage()='" + getErrorMessage() + '\'' +
|
||||
", state=" + getState() +
|
||||
", offerPayload=" + offerPayload +
|
||||
'}';
|
||||
"getErrorMessage()='" + getErrorMessage() + '\'' +
|
||||
", state=" + getState() +
|
||||
", offerPayload=" + offerPayload +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public final class OfferPayload implements ProtectedStoragePayload, RequiresOwne
|
|||
}
|
||||
|
||||
// Keys for extra map
|
||||
public static final String ACCOUNT_AGE_WITNESS_HASH = "accountAgeWitness";
|
||||
public static final String ACCOUNT_AGE_WITNESS_HASH = "accountAgeWitnessHash";
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -134,11 +134,11 @@ public final class OfferPayload implements ProtectedStoragePayload, RequiresOwne
|
|||
private final boolean isPrivateOffer;
|
||||
@Nullable
|
||||
private final String hashOfChallenge;
|
||||
|
||||
|
||||
// Should be only used in emergency case if we need to add data but do not want to break backward compatibility
|
||||
// at the P2P network storage checks. The hash of the object will be used to verify if the data is valid. Any new
|
||||
// field in a class would break that hash and therefore break the storage mechanism.
|
||||
|
||||
|
||||
// extraDataMap used from v0.6 on for hashOfPaymentAccount
|
||||
// key ACCOUNT_AGE_WITNESS, value: hex string of hashOfPaymentAccount byte array
|
||||
@Nullable
|
||||
|
@ -355,7 +355,7 @@ public final class OfferPayload implements ProtectedStoragePayload, RequiresOwne
|
|||
// In the offer we support base and counter currency
|
||||
// Fiat offers have base currency BTC and counterCurrency Fiat
|
||||
// Altcoins have base currency Altcoin and counterCurrency BTC
|
||||
// The rest of the app does not support yet that concept of base currency and counter currencies
|
||||
// The rest of the app does not support yet that concept of base currency and counter currencies
|
||||
// so we map here for convenience
|
||||
public String getCurrencyCode() {
|
||||
return CurrencyUtil.isCryptoCurrency(getBaseCurrencyCode()) ? getBaseCurrencyCode() : getCounterCurrencyCode();
|
||||
|
|
|
@ -31,31 +31,21 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
// Object has about 94 raw bytes (about 101 bytes is size of PB object)
|
||||
// With 100 000 entries we get 53.5 MB of data. Old entries will be shipped with the MapEntry resource file,
|
||||
// so only the newly added objects since the last release will not be loaded over the P2P network.
|
||||
// TODO Get rid of sigPubKey and replace by hash of sigPubKey. That will reduce the data size to 118 bytes.
|
||||
// Using EC signatures would produce longer signatures (71 bytes)
|
||||
// Object has about 28 raw bytes (29 bytes is size of PB object)
|
||||
// With 1 000 000 entries we get 29 MB of data. Old entries will be shipped with the MapEntry resource file,
|
||||
// so only the newly added objects since the last release will be retrieved over the P2P network.
|
||||
@Slf4j
|
||||
@Value
|
||||
public class AccountAgeWitness implements LazyProcessedPayload, PersistableNetworkPayload, PersistableEnvelope, PublishDateVerifiedPayload {
|
||||
private static final long TOLERANCE = TimeUnit.DAYS.toMillis(1);
|
||||
|
||||
private final byte[] hash; // Ripemd160(Sha256(data)) hash 20 bytes
|
||||
private final byte[] sigPubKeyHash; // Ripemd160(Sha256(sigPubKey)) hash 20 bytes
|
||||
private final byte[] signature; // about 46 bytes
|
||||
private final byte[] hash; // Ripemd160(Sha256(concatenated accountHash, signature and sigPubKey)); 20 bytes
|
||||
private final long date; // 8 byte
|
||||
|
||||
public AccountAgeWitness(byte[] hash,
|
||||
byte[] sigPubKeyHash,
|
||||
byte[] signature,
|
||||
long date) {
|
||||
this.hash = hash;
|
||||
this.sigPubKeyHash = sigPubKeyHash;
|
||||
this.signature = signature;
|
||||
this.date = date;
|
||||
|
||||
log.info("new AccountAgeWitness: hash={}, date={} ", Utilities.bytesAsHexString(hash), new Date(date));
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,10 +57,8 @@ public class AccountAgeWitness implements LazyProcessedPayload, PersistableNetwo
|
|||
@Override
|
||||
public PB.PersistableNetworkPayload toProtoMessage() {
|
||||
final PB.AccountAgeWitness.Builder builder = PB.AccountAgeWitness.newBuilder()
|
||||
.setHash(ByteString.copyFrom(hash))
|
||||
.setSigPubKeyHash(ByteString.copyFrom(sigPubKeyHash))
|
||||
.setSignature(ByteString.copyFrom(signature))
|
||||
.setDate(date);
|
||||
.setHash(ByteString.copyFrom(hash))
|
||||
.setDate(date);
|
||||
return PB.PersistableNetworkPayload.newBuilder().setAccountAgeWitness(builder).build();
|
||||
}
|
||||
|
||||
|
@ -80,10 +68,8 @@ public class AccountAgeWitness implements LazyProcessedPayload, PersistableNetwo
|
|||
|
||||
public static AccountAgeWitness fromProto(PB.AccountAgeWitness proto) {
|
||||
return new AccountAgeWitness(
|
||||
proto.getHash().toByteArray(),
|
||||
proto.getSigPubKeyHash().toByteArray(),
|
||||
proto.getSignature().toByteArray(),
|
||||
proto.getDate());
|
||||
proto.getHash().toByteArray(),
|
||||
proto.getDate());
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,13 +87,6 @@ public class AccountAgeWitness implements LazyProcessedPayload, PersistableNetwo
|
|||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//TODO impl. here or in caller?
|
||||
// We allow max 1 day time difference
|
||||
public boolean isDateValid() {
|
||||
return new Date().getTime() - date < TimeUnit.DAYS.toMillis(1);
|
||||
}
|
||||
|
||||
public P2PDataStorage.ByteArray getHashAsByteArray() {
|
||||
return new P2PDataStorage.ByteArray(hash);
|
||||
}
|
||||
|
@ -115,10 +94,8 @@ public class AccountAgeWitness implements LazyProcessedPayload, PersistableNetwo
|
|||
@Override
|
||||
public String toString() {
|
||||
return "AccountAgeWitness{" +
|
||||
"\n hash=" + Utilities.bytesAsHexString(hash) +
|
||||
",\n sigPubKeyHash=" + Utilities.bytesAsHexString(sigPubKeyHash) +
|
||||
",\n signature=" + Utilities.bytesAsHexString(signature) +
|
||||
",\n date=" + new Date(date) +
|
||||
"\n}";
|
||||
"\n hash=" + Utilities.bytesAsHexString(hash) +
|
||||
",\n date=" + new Date(date) +
|
||||
"\n}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
package io.bisq.core.payment;
|
||||
|
||||
import io.bisq.common.crypto.CryptoException;
|
||||
import io.bisq.common.crypto.Hash;
|
||||
import io.bisq.common.crypto.KeyRing;
|
||||
import io.bisq.common.crypto.PubKeyRing;
|
||||
import io.bisq.common.crypto.Sig;
|
||||
import io.bisq.common.handlers.ErrorMessageHandler;
|
||||
import io.bisq.common.locale.CurrencyUtil;
|
||||
|
@ -31,7 +31,6 @@ import io.bisq.core.payment.payload.PaymentMethod;
|
|||
import io.bisq.network.p2p.P2PService;
|
||||
import io.bisq.network.p2p.storage.P2PDataStorage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -52,12 +51,23 @@ public class AccountAgeWitnessService {
|
|||
private final P2PService p2PService;
|
||||
private final Map<P2PDataStorage.ByteArray, AccountAgeWitness> accountAgeWitnessMap = new HashMap<>();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Inject
|
||||
public AccountAgeWitnessService(KeyRing keyRing, P2PService p2PService) {
|
||||
this.keyRing = keyRing;
|
||||
this.p2PService = p2PService;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onAllServicesInitialized() {
|
||||
p2PService.getP2PDataStorage().addPersistableNetworkPayloadMapListener(payload -> {
|
||||
if (payload instanceof AccountAgeWitness)
|
||||
|
@ -71,49 +81,29 @@ public class AccountAgeWitnessService {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void addToMap(AccountAgeWitness accountAgeWitness) {
|
||||
log.debug("addToMap hash=" + Utilities.bytesAsHexString(accountAgeWitness.getHash()));
|
||||
if (!accountAgeWitnessMap.containsKey(accountAgeWitness.getHashAsByteArray()))
|
||||
accountAgeWitnessMap.put(accountAgeWitness.getHashAsByteArray(), accountAgeWitness);
|
||||
}
|
||||
|
||||
public void publishAccountAgeWitness(PaymentAccountPayload paymentAccountPayload) {
|
||||
try {
|
||||
AccountAgeWitness accountAgeWitness = getAccountAgeWitness(paymentAccountPayload);
|
||||
if (!accountAgeWitnessMap.containsKey(accountAgeWitness.getHashAsByteArray()))
|
||||
p2PService.addPersistableNetworkPayload(accountAgeWitness);
|
||||
} catch (CryptoException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.toString());
|
||||
}
|
||||
public void publishMyAccountAgeWitness(PaymentAccountPayload paymentAccountPayload) {
|
||||
AccountAgeWitness accountAgeWitness = getMyWitness(paymentAccountPayload);
|
||||
if (!accountAgeWitnessMap.containsKey(accountAgeWitness.getHashAsByteArray()))
|
||||
p2PService.addPersistableNetworkPayload(accountAgeWitness);
|
||||
}
|
||||
|
||||
public Optional<AccountAgeWitness> getWitnessByHash(String hashAsHex) {
|
||||
P2PDataStorage.ByteArray hashAsByteArray = new P2PDataStorage.ByteArray(Utilities.decodeFromHex(hashAsHex));
|
||||
return accountAgeWitnessMap.containsKey(hashAsByteArray) ? Optional.of(accountAgeWitnessMap.get(hashAsByteArray)) : Optional.<AccountAgeWitness>empty();
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Generic
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Optional<AccountAgeWitness> getWitnessByPaymentAccountPayload(PaymentAccountPayload paymentAccountPayload) {
|
||||
return getWitnessByHash(getWitnessHashAsHex(paymentAccountPayload));
|
||||
}
|
||||
|
||||
public long getAccountAge(Offer offer) {
|
||||
if (offer.getAccountAgeWitnessHash().isPresent())
|
||||
return getAccountAge(getWitnessByHash(offer.getAccountAgeWitnessHash().get()));
|
||||
else
|
||||
return 0L;
|
||||
}
|
||||
|
||||
public long getAccountAge(PaymentAccountPayload paymentAccountPayload) {
|
||||
return getAccountAge(getWitnessByPaymentAccountPayload(paymentAccountPayload));
|
||||
}
|
||||
|
||||
private long getAccountAge(Optional<AccountAgeWitness> accountAgeWitnessOptional) {
|
||||
if (accountAgeWitnessOptional.isPresent()) {
|
||||
return new Date().getTime() - accountAgeWitnessOptional.get().getDate();
|
||||
} else {
|
||||
return 0L;
|
||||
}
|
||||
public byte[] getAccountInputDataWithSalt(PaymentAccountPayload paymentAccountPayload) {
|
||||
return Utilities.concatenateByteArrays(paymentAccountPayload.getAgeWitnessInputData(), paymentAccountPayload.getSalt());
|
||||
}
|
||||
|
||||
public long getAccountAge(AccountAgeWitness accountAgeWitness) {
|
||||
|
@ -130,65 +120,17 @@ public class AccountAgeWitnessService {
|
|||
}
|
||||
}
|
||||
|
||||
private AccountAgeWitness getAccountAgeWitness(PaymentAccountPayload paymentAccountPayload) throws CryptoException {
|
||||
byte[] hash = getWitnessHash(paymentAccountPayload);
|
||||
byte[] signature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), hash);
|
||||
byte[] sigPubKeyHash = Hash.getSha256Ripemd160hash(keyRing.getPubKeyRing().getSignaturePubKeyBytes());
|
||||
long now = new Date().getTime();
|
||||
|
||||
//TODO
|
||||
// test
|
||||
//now -= TimeUnit.DAYS.toMillis(75);
|
||||
|
||||
return new AccountAgeWitness(hash,
|
||||
sigPubKeyHash,
|
||||
signature,
|
||||
now);
|
||||
}
|
||||
|
||||
public byte[] getWitnessHash(PaymentAccountPayload paymentAccountPayload) {
|
||||
return getWitnessHash(paymentAccountPayload, paymentAccountPayload.getSalt());
|
||||
}
|
||||
|
||||
public String getWitnessHashAsHex(PaymentAccountPayload paymentAccountPayload) {
|
||||
return Utilities.bytesAsHexString(getWitnessHash(paymentAccountPayload));
|
||||
}
|
||||
|
||||
private byte[] getWitnessHash(PaymentAccountPayload paymentAccountPayload, byte[] salt) {
|
||||
byte[] ageWitnessInputData = paymentAccountPayload.getAgeWitnessInputData();
|
||||
final byte[] combined = ArrayUtils.addAll(ageWitnessInputData, salt);
|
||||
final byte[] hash = Hash.getSha256Ripemd160hash(combined);
|
||||
log.debug("getWitnessHash paymentAccountPayload={}, salt={}, ageWitnessInputData={}, combined={}, hash={}",
|
||||
paymentAccountPayload.getPaymentDetails(),
|
||||
Utilities.encodeToHex(salt),
|
||||
Utilities.encodeToHex(ageWitnessInputData),
|
||||
Utilities.encodeToHex(combined),
|
||||
Utilities.encodeToHex(hash));
|
||||
return hash;
|
||||
}
|
||||
|
||||
public long getTradeLimit(PaymentAccount paymentAccount, String currencyCode) {
|
||||
return getTradeLimit(paymentAccount.getPaymentAccountPayload(), currencyCode);
|
||||
}
|
||||
|
||||
public long getTradeLimit(PaymentAccountPayload paymentAccountPayload, String currencyCode) {
|
||||
final long maxTradeLimit = PaymentMethod.getPaymentMethodById(paymentAccountPayload.getPaymentMethodId()).getMaxTradeLimitAsCoin(currencyCode).value;
|
||||
private long getTradeLimit(PaymentMethod paymentMethod, String currencyCode, Optional<AccountAgeWitness> accountAgeWitnessOptional) {
|
||||
final long maxTradeLimit = paymentMethod.getMaxTradeLimitAsCoin(currencyCode).value;
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
double factor;
|
||||
|
||||
// TODO test
|
||||
/*Optional<AccountAgeWitness> accountAgeWitnessOptional = paymentAccount.getName() != null ?
|
||||
getWitnessByHash(getWitnessHashAsHex(paymentAccountPayload)) :
|
||||
Optional.empty();*/
|
||||
|
||||
Optional<AccountAgeWitness> accountAgeWitnessOptional = getWitnessByHash(getWitnessHashAsHex(paymentAccountPayload));
|
||||
|
||||
AccountAge accountAgeCategory = accountAgeWitnessOptional.isPresent() ?
|
||||
getAccountAgeCategory(getAccountAge((accountAgeWitnessOptional.get()))) :
|
||||
AccountAgeWitnessService.AccountAge.LESS_ONE_MONTH;
|
||||
getAccountAgeCategory(getAccountAge((accountAgeWitnessOptional.get()))) :
|
||||
AccountAgeWitnessService.AccountAge.LESS_ONE_MONTH;
|
||||
|
||||
// TODO Fade in by date can be removed after feb 2018
|
||||
// We want to fade in the limit over 2 months to avoid that all users get limited to 25% of the limit when
|
||||
// We want to fade in the limit over 2 months to avoid that all users get limited to 25% of the limit when
|
||||
// we deploy that feature.
|
||||
final Date now = new Date();
|
||||
/* final Date dez = new GregorianCalendar(2017, GregorianCalendar.DECEMBER, 1).getTime();
|
||||
|
@ -236,38 +178,113 @@ public class AccountAgeWitnessService {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean verifyAccountAgeWitness(byte[] peersAgeWitnessInputData,
|
||||
AccountAgeWitness witness,
|
||||
byte[] peersSalt,
|
||||
PublicKey peersPublicKey,
|
||||
byte[] nonce,
|
||||
byte[] signatureOfNonce,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// My witness
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public AccountAgeWitness getMyWitness(PaymentAccountPayload paymentAccountPayload) {
|
||||
try {
|
||||
byte[] accountInputDataWithSalt = getAccountInputDataWithSalt(paymentAccountPayload);
|
||||
byte[] hash = Utilities.concatenateByteArrays(accountInputDataWithSalt,
|
||||
Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), accountInputDataWithSalt),
|
||||
keyRing.getPubKeyRing().getSignaturePubKeyBytes());
|
||||
long date = new Date().getTime();
|
||||
//TODO
|
||||
// test
|
||||
//date -= TimeUnit.DAYS.toMillis(75);
|
||||
return new AccountAgeWitness(hash, date);
|
||||
} catch (CryptoException e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getMyWitnessHash(PaymentAccountPayload paymentAccountPayload) {
|
||||
return getMyWitness(paymentAccountPayload).getHash();
|
||||
}
|
||||
|
||||
public String getMyWitnessHashAsHex(PaymentAccountPayload paymentAccountPayload) {
|
||||
return Utilities.bytesAsHexString(getMyWitnessHash(paymentAccountPayload));
|
||||
}
|
||||
|
||||
public long getMyAccountAge(PaymentAccountPayload paymentAccountPayload) {
|
||||
return getAccountAge(getMyWitness(paymentAccountPayload));
|
||||
}
|
||||
|
||||
public long getMyTradeLimit(PaymentAccount paymentAccount, String currencyCode) {
|
||||
return getTradeLimit(paymentAccount.getPaymentMethod(), currencyCode, Optional.of(getMyWitness(paymentAccount.getPaymentAccountPayload())));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Peers witness
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Optional<AccountAgeWitness> getPeersWitnessByHash(byte[] hash) {
|
||||
P2PDataStorage.ByteArray hashAsByteArray = new P2PDataStorage.ByteArray(hash);
|
||||
return accountAgeWitnessMap.containsKey(hashAsByteArray) ? Optional.of(accountAgeWitnessMap.get(hashAsByteArray)) : Optional.<AccountAgeWitness>empty();
|
||||
}
|
||||
|
||||
public Optional<AccountAgeWitness> getPeersWitnessByHashAsHex(String hashAsHex) {
|
||||
return getPeersWitnessByHash(Utilities.decodeFromHex(hashAsHex));
|
||||
}
|
||||
|
||||
public long getPeersAccountAge(Offer offer) {
|
||||
final Optional<String> accountAgeWitnessHash = offer.getAccountAgeWitnessHashAsHex();
|
||||
final Optional<AccountAgeWitness> witnessByHashAsHex = accountAgeWitnessHash.isPresent() ?
|
||||
getPeersWitnessByHashAsHex(accountAgeWitnessHash.get()) :
|
||||
Optional.<AccountAgeWitness>empty();
|
||||
return witnessByHashAsHex.isPresent() ? getAccountAge(witnessByHashAsHex.get()) : 0L;
|
||||
}
|
||||
|
||||
public long getPeersTradeLimit(PaymentAccountPayload paymentAccountPayload, String currencyCode, Optional<AccountAgeWitness> accountAgeWitnessOptional) {
|
||||
return getTradeLimit(PaymentMethod.getPaymentMethodById(paymentAccountPayload.getPaymentMethodId()), currencyCode, accountAgeWitnessOptional);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Verification
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public boolean verifyPeersAccountAgeWitness(Offer offer,
|
||||
PaymentAccountPayload peersPaymentAccountPayload,
|
||||
AccountAgeWitness witness,
|
||||
PubKeyRing peersPubKeyRing,
|
||||
byte[] peersSignatureOfAccountHash,
|
||||
byte[] nonce,
|
||||
byte[] signatureOfNonce,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
// Check if trade date in witness is not older than the release date of that feature (was added in v0.6)
|
||||
// TODO set date before releasing
|
||||
if (!isTradeDateAfterReleaseDate(witness.getDate(), new GregorianCalendar(2017, GregorianCalendar.OCTOBER, 17).getTime(), errorMessageHandler))
|
||||
return false;
|
||||
|
||||
// Check if peer's pubkey is matching the one from the witness data
|
||||
if (!verifySigPubKeyHash(witness.getSigPubKeyHash(), peersPublicKey, errorMessageHandler))
|
||||
return false;
|
||||
final byte[] peersAccountInputDataWithSalt = Utilities.concatenateByteArrays(peersPaymentAccountPayload.getAgeWitnessInputData(), peersPaymentAccountPayload.getSalt());
|
||||
byte[] hash = Utilities.concatenateByteArrays(peersAccountInputDataWithSalt, peersSignatureOfAccountHash, peersPubKeyRing.getSignaturePubKeyBytes());
|
||||
|
||||
final byte[] combined = ArrayUtils.addAll(peersAgeWitnessInputData, peersSalt);
|
||||
byte[] hash = Hash.getSha256Ripemd160hash(combined);
|
||||
|
||||
// Check if the hash in the witness data matches the peer's payment account input data + salt
|
||||
// Check if the hash in the witness data matches the hash derived from the data provided by the peer
|
||||
if (!verifyWitnessHash(witness.getHash(), hash, errorMessageHandler))
|
||||
return false;
|
||||
|
||||
// Check if the witness signature is correct
|
||||
if (!verifySignature(peersPublicKey, hash, witness.getSignature(), errorMessageHandler))
|
||||
// Check if the witness signature is correct
|
||||
if (!verifyPeersTradeLimit(offer, peersPaymentAccountPayload, errorMessageHandler))
|
||||
return false;
|
||||
|
||||
// Check if the signature of the nonce is correct
|
||||
return verifySignatureOfNonce(peersPublicKey, nonce, signatureOfNonce, errorMessageHandler);
|
||||
// Check if the witness signature is correct
|
||||
if (!verifySignature(peersPubKeyRing.getSignaturePubKey(), peersAccountInputDataWithSalt, peersSignatureOfAccountHash, errorMessageHandler))
|
||||
return false;
|
||||
|
||||
// Check if the signature of the nonce is correct
|
||||
return verifySignatureOfNonce(peersPubKeyRing.getSignaturePubKey(), nonce, signatureOfNonce, errorMessageHandler);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Package scope verification subroutines
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
boolean isTradeDateAfterReleaseDate(long witnessDateAsLong, Date ageWitnessReleaseDate, ErrorMessageHandler errorMessageHandler) {
|
||||
// Release date minus 1 day as tolerance for not synced clocks
|
||||
Date releaseDateWithTolerance = new Date(ageWitnessReleaseDate.getTime() - TimeUnit.DAYS.toMillis(1));
|
||||
|
@ -275,35 +292,38 @@ public class AccountAgeWitnessService {
|
|||
final boolean result = witnessDate.after(releaseDateWithTolerance);
|
||||
if (!result) {
|
||||
final String msg = "Trade date is earlier than release date of ageWitness minus 1 day. " +
|
||||
"ageWitnessReleaseDate=" + ageWitnessReleaseDate + ", witnessDate=" + witnessDate;
|
||||
"ageWitnessReleaseDate=" + ageWitnessReleaseDate + ", witnessDate=" + witnessDate;
|
||||
log.warn(msg);
|
||||
errorMessageHandler.handleErrorMessage(msg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean verifySigPubKeyHash(byte[] sigPubKeyHash,
|
||||
PublicKey peersPublicKey,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
final byte[] peersPublicKeyHash = Hash.getSha256Ripemd160hash(Sig.getPublicKeyBytes(peersPublicKey));
|
||||
final boolean result = Arrays.equals(peersPublicKeyHash, sigPubKeyHash);
|
||||
if (!result) {
|
||||
final String msg = "sigPubKeyHash is not matching peers peersPublicKey. " +
|
||||
"sigPubKeyHash=" + Utilities.bytesAsHexString(sigPubKeyHash) + ", peersPublicKeyHash=" +
|
||||
Utilities.bytesAsHexString(peersPublicKeyHash);
|
||||
log.warn(msg);
|
||||
errorMessageHandler.handleErrorMessage(msg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean verifyWitnessHash(byte[] witnessHash,
|
||||
byte[] hash,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
boolean verifyWitnessHash(byte[] witnessHash,
|
||||
byte[] hash,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
final boolean result = Arrays.equals(witnessHash, hash);
|
||||
if (!result) {
|
||||
final String msg = "witnessHash is not matching peers hash. " +
|
||||
"witnessHash=" + Utilities.bytesAsHexString(witnessHash) + ", hash=" + Utilities.bytesAsHexString(hash);
|
||||
"witnessHash=" + Utilities.bytesAsHexString(witnessHash) + ", hash=" + Utilities.bytesAsHexString(hash);
|
||||
log.warn(msg);
|
||||
errorMessageHandler.handleErrorMessage(msg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean verifyPeersTradeLimit(Offer offer,
|
||||
PaymentAccountPayload paymentAccountPayload,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
final Optional<String> offerHashAsHexOptional = offer.getAccountAgeWitnessHashAsHex();
|
||||
Optional<AccountAgeWitness> accountAgeWitnessOptional = offerHashAsHexOptional.isPresent() ? getPeersWitnessByHashAsHex(offerHashAsHexOptional.get()) : Optional.<AccountAgeWitness>empty();
|
||||
long maxTradeLimit = getPeersTradeLimit(paymentAccountPayload, offer.getCurrencyCode(), accountAgeWitnessOptional);
|
||||
final Coin offerMaxTradeLimit = offer.getMaxTradeLimit();
|
||||
boolean result = offerMaxTradeLimit.value == maxTradeLimit;
|
||||
if (!result) {
|
||||
String msg = "Offers max trade limit does not match with the one based on his account age.\n" +
|
||||
"OfferMaxTradeLimit=" + offerMaxTradeLimit.toFriendlyString() +
|
||||
"; Account age based MaxTradeLimit=" + Coin.valueOf(maxTradeLimit).toFriendlyString();
|
||||
log.warn(msg);
|
||||
errorMessageHandler.handleErrorMessage(msg);
|
||||
}
|
||||
|
@ -323,8 +343,8 @@ public class AccountAgeWitnessService {
|
|||
}
|
||||
if (!result) {
|
||||
final String msg = "Signature of PaymentAccountAgeWitness is not correct. " +
|
||||
"peersPublicKey=" + peersPublicKey + ", data=" + Utilities.bytesAsHexString(data) +
|
||||
", signature=" + Utilities.bytesAsHexString(signature);
|
||||
"peersPublicKey=" + peersPublicKey + ", data=" + Utilities.bytesAsHexString(data) +
|
||||
", signature=" + Utilities.bytesAsHexString(signature);
|
||||
log.warn(msg);
|
||||
errorMessageHandler.handleErrorMessage(msg);
|
||||
}
|
||||
|
@ -344,38 +364,8 @@ public class AccountAgeWitnessService {
|
|||
}
|
||||
if (!result) {
|
||||
final String msg = "Signature of nonce is not correct. " +
|
||||
"peersPublicKey=" + peersPublicKey + ", nonce(hex)=" + Utilities.bytesAsHexString(nonce) +
|
||||
", signature=" + Utilities.bytesAsHexString(signature);
|
||||
log.warn(msg);
|
||||
errorMessageHandler.handleErrorMessage(msg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean verifyOffersAccountAgeWitness(PaymentAccountPayload paymentAccountPayload,
|
||||
byte[] offersWitness,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
byte[] witnessHash = getWitnessHash(paymentAccountPayload, paymentAccountPayload.getSalt());
|
||||
final boolean result = Arrays.equals(witnessHash, offersWitness);
|
||||
if (!result) {
|
||||
final String msg = "witnessHash is not matching peers offersWitness. " +
|
||||
"witnessHash=" + Utilities.bytesAsHexString(witnessHash) + ", offersWitness=" + Utilities.bytesAsHexString(offersWitness);
|
||||
log.warn(msg);
|
||||
errorMessageHandler.handleErrorMessage(msg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean verifyTradeLimit(Offer offer,
|
||||
PaymentAccountPayload paymentAccountPayload,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
long maxTradeLimit = getTradeLimit(paymentAccountPayload, offer.getCurrencyCode());
|
||||
final Coin offerMaxTradeLimit = offer.getMaxTradeLimit();
|
||||
final boolean result = offerMaxTradeLimit.value == maxTradeLimit;
|
||||
if (!result) {
|
||||
String msg = "Offers max trade limit does not match with the one we calculated.\n" +
|
||||
"OfferMaxTradeLimit=" + offerMaxTradeLimit.toFriendlyString() +
|
||||
"; MaxTradeLimit=" + Coin.valueOf(maxTradeLimit).toFriendlyString();
|
||||
"peersPublicKey=" + peersPublicKey + ", nonce(hex)=" + Utilities.bytesAsHexString(nonce) +
|
||||
", signature=" + Utilities.bytesAsHexString(signature);
|
||||
log.warn(msg);
|
||||
errorMessageHandler.handleErrorMessage(msg);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.bisq.core.payment;
|
||||
|
||||
import io.bisq.common.locale.TradeCurrency;
|
||||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.core.offer.Offer;
|
||||
import io.bisq.core.payment.payload.PaymentMethod;
|
||||
import javafx.collections.FXCollections;
|
||||
|
@ -9,7 +8,6 @@ import javafx.collections.ObservableList;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
@ -27,8 +25,8 @@ public class PaymentAccountUtil {
|
|||
public static ObservableList<PaymentAccount> getPossiblePaymentAccounts(Offer offer, Set<PaymentAccount> paymentAccounts) {
|
||||
ObservableList<PaymentAccount> result = FXCollections.observableArrayList();
|
||||
result.addAll(paymentAccounts.stream()
|
||||
.filter(paymentAccount -> isPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
.collect(Collectors.toList()));
|
||||
.filter(paymentAccount -> isPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
.collect(Collectors.toList()));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -36,16 +34,16 @@ public class PaymentAccountUtil {
|
|||
public static String getInfoForMismatchingPaymentMethodLimits(Offer offer, PaymentAccount paymentAccount) {
|
||||
// dont translate atm as it is not used so far in the UI just for logs
|
||||
return "Payment methods have different trade limits or trade periods.\n" +
|
||||
"Our local Payment method: " + paymentAccount.getPaymentMethod().toString() + "\n" +
|
||||
"Payment method from offer: " + offer.getPaymentMethod().toString();
|
||||
"Our local Payment method: " + paymentAccount.getPaymentMethod().toString() + "\n" +
|
||||
"Payment method from offer: " + offer.getPaymentMethod().toString();
|
||||
}
|
||||
|
||||
//TODO not tested with all combinations yet....
|
||||
public static boolean isPaymentAccountValidForOffer(Offer offer, PaymentAccount paymentAccount) {
|
||||
// check if we have a matching currency
|
||||
Set<String> paymentAccountCurrencyCodes = paymentAccount.getTradeCurrencies().stream()
|
||||
.map(TradeCurrency::getCode)
|
||||
.collect(Collectors.toSet());
|
||||
.map(TradeCurrency::getCode)
|
||||
.collect(Collectors.toSet());
|
||||
boolean matchesCurrencyCode = paymentAccountCurrencyCodes.contains(offer.getCurrencyCode());
|
||||
if (!matchesCurrencyCode)
|
||||
return false;
|
||||
|
@ -54,7 +52,7 @@ public class PaymentAccountUtil {
|
|||
final boolean arePaymentMethodsEqual = paymentAccount.getPaymentMethod().equals(offer.getPaymentMethod());
|
||||
|
||||
if (!arePaymentMethodsEqual &&
|
||||
paymentAccount.getPaymentMethod().getId().equals(offer.getPaymentMethod().getId()))
|
||||
paymentAccount.getPaymentMethod().getId().equals(offer.getPaymentMethod().getId()))
|
||||
log.warn(getInfoForMismatchingPaymentMethodLimits(offer, paymentAccount));
|
||||
|
||||
if (paymentAccount instanceof CountryBasedPaymentAccount) {
|
||||
|
@ -62,14 +60,14 @@ public class PaymentAccountUtil {
|
|||
|
||||
// check if we have a matching country
|
||||
boolean matchesCountryCodes = offer.getAcceptedCountryCodes() != null && countryBasedPaymentAccount.getCountry() != null &&
|
||||
offer.getAcceptedCountryCodes().contains(countryBasedPaymentAccount.getCountry().code);
|
||||
offer.getAcceptedCountryCodes().contains(countryBasedPaymentAccount.getCountry().code);
|
||||
if (!matchesCountryCodes)
|
||||
return false;
|
||||
|
||||
if (paymentAccount instanceof SepaAccount || offer.getPaymentMethod().equals(PaymentMethod.SEPA)) {
|
||||
return arePaymentMethodsEqual;
|
||||
} else if (offer.getPaymentMethod().equals(PaymentMethod.SAME_BANK) ||
|
||||
offer.getPaymentMethod().equals(PaymentMethod.SPECIFIC_BANKS)) {
|
||||
offer.getPaymentMethod().equals(PaymentMethod.SPECIFIC_BANKS)) {
|
||||
|
||||
final List<String> acceptedBankIds = offer.getAcceptedBankIds();
|
||||
checkNotNull(acceptedBankIds, "offer.getAcceptedBankIds() must not be null");
|
||||
|
@ -105,30 +103,14 @@ public class PaymentAccountUtil {
|
|||
|
||||
public static Optional<PaymentAccount> getMostMaturePaymentAccountForOffer(Offer offer,
|
||||
Set<PaymentAccount> paymentAccounts,
|
||||
AccountAgeWitnessService accountAgeWitnessService) {
|
||||
AccountAgeWitnessService service) {
|
||||
List<PaymentAccount> list = paymentAccounts.stream()
|
||||
.filter(paymentAccount -> isPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
.sorted((o1, o2) -> {
|
||||
final Optional<AccountAgeWitness> witness1 = accountAgeWitnessService.getWitnessByPaymentAccountPayload(o1.getPaymentAccountPayload());
|
||||
log.debug("witness1 isPresent={}", witness1.isPresent());
|
||||
if (witness1.isPresent())
|
||||
log.debug("witness1 HashAsHex={}, date={}", Utilities.bytesAsHexString(witness1.get().getHash()), new Date(witness1.get().getDate()));
|
||||
long age1 = witness1.isPresent() ? accountAgeWitnessService.getAccountAge(witness1.get()) : 0;
|
||||
|
||||
final Optional<AccountAgeWitness> witness2 = accountAgeWitnessService.getWitnessByPaymentAccountPayload(o2.getPaymentAccountPayload());
|
||||
log.debug("witness2 isPresent={}", witness2.isPresent());
|
||||
if (witness2.isPresent())
|
||||
log.debug("witness2 HashAsHex={}, date={}", Utilities.bytesAsHexString(witness2.get().getHash()), new Date(witness2.get().getDate()));
|
||||
long age2 = witness2.isPresent() ? accountAgeWitnessService.getAccountAge(witness2.get()) : 0;
|
||||
log.debug("AccountName 1 " + o1.getAccountName());
|
||||
log.debug("AccountName 2 " + o2.getAccountName());
|
||||
log.debug("age1 " + age1 / TimeUnit.DAYS.toMillis(1));
|
||||
log.debug("age2 " + age2 / TimeUnit.DAYS.toMillis(1));
|
||||
log.debug("result " + (new Long(age1).compareTo(age2)));
|
||||
log.debug(" ");
|
||||
return new Long(age2).compareTo(age1);
|
||||
}).collect(Collectors.toList());
|
||||
list.stream().forEach(e -> log.error("getMostMaturePaymentAccountForOffer AccountName={}, witnessHashAsHex={}", e.getAccountName(), accountAgeWitnessService.getWitnessHashAsHex(e.getPaymentAccountPayload())));
|
||||
.filter(paymentAccount -> isPaymentAccountValidForOffer(offer, paymentAccount))
|
||||
.sorted((o1, o2) -> {
|
||||
return new Long(service.getAccountAge(service.getMyWitness(o2.getPaymentAccountPayload())))
|
||||
.compareTo(service.getAccountAge(service.getMyWitness(o1.getPaymentAccountPayload())));
|
||||
}).collect(Collectors.toList());
|
||||
list.stream().forEach(e -> log.error("getMostMaturePaymentAccountForOffer AccountName={}, witnessHashAsHex={}", e.getAccountName(), service.getMyWitnessHashAsHex(e.getPaymentAccountPayload())));
|
||||
final Optional<PaymentAccount> first = list.stream().findFirst();
|
||||
if (first.isPresent())
|
||||
log.debug("first={}", first.get().getAccountName());
|
||||
|
|
|
@ -62,6 +62,8 @@ public final class PayDepositRequest extends TradeMessage {
|
|||
|
||||
// added in v 0.6. can be null if we trade with an older peer
|
||||
@Nullable
|
||||
private final byte[] accountAgeWitnessSignatureOfAccountData;
|
||||
@Nullable
|
||||
private final byte[] accountAgeWitnessNonce;
|
||||
@Nullable
|
||||
private final byte[] accountAgeWitnessSignatureOfNonce;
|
||||
|
@ -88,6 +90,7 @@ public final class PayDepositRequest extends TradeMessage {
|
|||
NodeAddress mediatorNodeAddress,
|
||||
String uid,
|
||||
int messageVersion,
|
||||
@Nullable byte[] accountAgeWitnessSignatureOfAccountData,
|
||||
@Nullable byte[] accountAgeWitnessNonce,
|
||||
@Nullable byte[] accountAgeWitnessSignatureOfNonce) {
|
||||
super(messageVersion, tradeId);
|
||||
|
@ -111,6 +114,7 @@ public final class PayDepositRequest extends TradeMessage {
|
|||
this.arbitratorNodeAddress = arbitratorNodeAddress;
|
||||
this.mediatorNodeAddress = mediatorNodeAddress;
|
||||
this.uid = uid;
|
||||
this.accountAgeWitnessSignatureOfAccountData = accountAgeWitnessSignatureOfAccountData;
|
||||
this.accountAgeWitnessNonce = accountAgeWitnessNonce;
|
||||
this.accountAgeWitnessSignatureOfNonce = accountAgeWitnessSignatureOfNonce;
|
||||
}
|
||||
|
@ -123,98 +127,101 @@ public final class PayDepositRequest extends TradeMessage {
|
|||
@Override
|
||||
public PB.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
PB.PayDepositRequest.Builder builder = PB.PayDepositRequest.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setTradeAmount(tradeAmount)
|
||||
.setTradePrice(tradePrice)
|
||||
.setTxFee(txFee)
|
||||
.setTakerFee(takerFee)
|
||||
.setIsCurrencyForTakerFeeBtc(isCurrencyForTakerFeeBtc)
|
||||
.addAllRawTransactionInputs(rawTransactionInputs.stream()
|
||||
.map(RawTransactionInput::toProtoMessage).collect(Collectors.toList()))
|
||||
.setChangeOutputValue(changeOutputValue)
|
||||
.setTakerMultiSigPubKey(ByteString.copyFrom(takerMultiSigPubKey))
|
||||
.setTakerPayoutAddressString(takerPayoutAddressString)
|
||||
.setTakerPubKeyRing(takerPubKeyRing.toProtoMessage())
|
||||
.setTakerPaymentAccountPayload((PB.PaymentAccountPayload) takerPaymentAccountPayload.toProtoMessage())
|
||||
.setTakerAccountId(takerAccountId)
|
||||
.setTakerFeeTxId(takerFeeTxId)
|
||||
.addAllAcceptedArbitratorNodeAddresses(acceptedArbitratorNodeAddresses.stream()
|
||||
.map(NodeAddress::toProtoMessage).collect(Collectors.toList()))
|
||||
.addAllAcceptedMediatorNodeAddresses(acceptedMediatorNodeAddresses.stream()
|
||||
.map(NodeAddress::toProtoMessage).collect(Collectors.toList()))
|
||||
.setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage())
|
||||
.setMediatorNodeAddress(mediatorNodeAddress.toProtoMessage())
|
||||
.setUid(uid);
|
||||
|
||||
.setTradeId(tradeId)
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setTradeAmount(tradeAmount)
|
||||
.setTradePrice(tradePrice)
|
||||
.setTxFee(txFee)
|
||||
.setTakerFee(takerFee)
|
||||
.setIsCurrencyForTakerFeeBtc(isCurrencyForTakerFeeBtc)
|
||||
.addAllRawTransactionInputs(rawTransactionInputs.stream()
|
||||
.map(RawTransactionInput::toProtoMessage).collect(Collectors.toList()))
|
||||
.setChangeOutputValue(changeOutputValue)
|
||||
.setTakerMultiSigPubKey(ByteString.copyFrom(takerMultiSigPubKey))
|
||||
.setTakerPayoutAddressString(takerPayoutAddressString)
|
||||
.setTakerPubKeyRing(takerPubKeyRing.toProtoMessage())
|
||||
.setTakerPaymentAccountPayload((PB.PaymentAccountPayload) takerPaymentAccountPayload.toProtoMessage())
|
||||
.setTakerAccountId(takerAccountId)
|
||||
.setTakerFeeTxId(takerFeeTxId)
|
||||
.addAllAcceptedArbitratorNodeAddresses(acceptedArbitratorNodeAddresses.stream()
|
||||
.map(NodeAddress::toProtoMessage).collect(Collectors.toList()))
|
||||
.addAllAcceptedMediatorNodeAddresses(acceptedMediatorNodeAddresses.stream()
|
||||
.map(NodeAddress::toProtoMessage).collect(Collectors.toList()))
|
||||
.setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage())
|
||||
.setMediatorNodeAddress(mediatorNodeAddress.toProtoMessage())
|
||||
.setUid(uid);
|
||||
|
||||
Optional.ofNullable(changeOutputAddress).ifPresent(builder::setChangeOutputAddress);
|
||||
Optional.ofNullable(accountAgeWitnessNonce).ifPresent(accountAgeWitnessNonce -> builder.setAccountAgeWitnessNonce(ByteString.copyFrom(accountAgeWitnessNonce)));
|
||||
Optional.ofNullable(accountAgeWitnessSignatureOfNonce).ifPresent(accountAgeWitnessSignatureOfNonce -> builder.setAccountAgeWitnessSignatureOfNonce(ByteString.copyFrom(accountAgeWitnessSignatureOfNonce)));
|
||||
Optional.ofNullable(accountAgeWitnessSignatureOfAccountData).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfAccountData(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(accountAgeWitnessNonce).ifPresent(e -> builder.setAccountAgeWitnessNonce(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(accountAgeWitnessSignatureOfNonce).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfNonce(ByteString.copyFrom(e)));
|
||||
|
||||
return getNetworkEnvelopeBuilder().setPayDepositRequest(builder).build();
|
||||
}
|
||||
|
||||
public static PayDepositRequest fromProto(PB.PayDepositRequest proto, CoreProtoResolver coreProtoResolver, int messageVersion) {
|
||||
List<RawTransactionInput> rawTransactionInputs = proto.getRawTransactionInputsList().stream()
|
||||
.map(rawTransactionInput -> new RawTransactionInput(rawTransactionInput.getIndex(),
|
||||
rawTransactionInput.getParentTransaction().toByteArray(), rawTransactionInput.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
.map(rawTransactionInput -> new RawTransactionInput(rawTransactionInput.getIndex(),
|
||||
rawTransactionInput.getParentTransaction().toByteArray(), rawTransactionInput.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
List<NodeAddress> acceptedArbitratorNodeAddresses = proto.getAcceptedArbitratorNodeAddressesList().stream()
|
||||
.map(NodeAddress::fromProto).collect(Collectors.toList());
|
||||
.map(NodeAddress::fromProto).collect(Collectors.toList());
|
||||
List<NodeAddress> acceptedMediatorNodeAddresses = proto.getAcceptedMediatorNodeAddressesList().stream()
|
||||
.map(NodeAddress::fromProto).collect(Collectors.toList());
|
||||
.map(NodeAddress::fromProto).collect(Collectors.toList());
|
||||
|
||||
return new PayDepositRequest(proto.getTradeId(),
|
||||
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
||||
proto.getTradeAmount(),
|
||||
proto.getTradePrice(),
|
||||
proto.getTxFee(),
|
||||
proto.getTakerFee(),
|
||||
proto.getIsCurrencyForTakerFeeBtc(),
|
||||
rawTransactionInputs,
|
||||
proto.getChangeOutputValue(),
|
||||
ProtoUtil.stringOrNullFromProto(proto.getChangeOutputAddress()),
|
||||
proto.getTakerMultiSigPubKey().toByteArray(),
|
||||
proto.getTakerPayoutAddressString(),
|
||||
PubKeyRing.fromProto(proto.getTakerPubKeyRing()),
|
||||
coreProtoResolver.fromProto(proto.getTakerPaymentAccountPayload()),
|
||||
proto.getTakerAccountId(),
|
||||
proto.getTakerFeeTxId(),
|
||||
acceptedArbitratorNodeAddresses,
|
||||
acceptedMediatorNodeAddresses,
|
||||
NodeAddress.fromProto(proto.getArbitratorNodeAddress()),
|
||||
NodeAddress.fromProto(proto.getMediatorNodeAddress()),
|
||||
proto.getUid(),
|
||||
messageVersion,
|
||||
proto.getAccountAgeWitnessNonce().isEmpty() ? null : proto.getAccountAgeWitnessNonce().toByteArray(),
|
||||
proto.getAccountAgeWitnessSignatureOfNonce().isEmpty() ? null : proto.getAccountAgeWitnessSignatureOfNonce().toByteArray());
|
||||
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
||||
proto.getTradeAmount(),
|
||||
proto.getTradePrice(),
|
||||
proto.getTxFee(),
|
||||
proto.getTakerFee(),
|
||||
proto.getIsCurrencyForTakerFeeBtc(),
|
||||
rawTransactionInputs,
|
||||
proto.getChangeOutputValue(),
|
||||
ProtoUtil.stringOrNullFromProto(proto.getChangeOutputAddress()),
|
||||
proto.getTakerMultiSigPubKey().toByteArray(),
|
||||
proto.getTakerPayoutAddressString(),
|
||||
PubKeyRing.fromProto(proto.getTakerPubKeyRing()),
|
||||
coreProtoResolver.fromProto(proto.getTakerPaymentAccountPayload()),
|
||||
proto.getTakerAccountId(),
|
||||
proto.getTakerFeeTxId(),
|
||||
acceptedArbitratorNodeAddresses,
|
||||
acceptedMediatorNodeAddresses,
|
||||
NodeAddress.fromProto(proto.getArbitratorNodeAddress()),
|
||||
NodeAddress.fromProto(proto.getMediatorNodeAddress()),
|
||||
proto.getUid(),
|
||||
messageVersion,
|
||||
ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfAccountData()),
|
||||
ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessNonce()),
|
||||
ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfNonce()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PayDepositRequest{" +
|
||||
"\n senderNodeAddress=" + senderNodeAddress +
|
||||
",\n tradeAmount=" + tradeAmount +
|
||||
",\n tradePrice=" + tradePrice +
|
||||
",\n txFee=" + txFee +
|
||||
",\n takerFee=" + takerFee +
|
||||
",\n isCurrencyForTakerFeeBtc=" + isCurrencyForTakerFeeBtc +
|
||||
",\n rawTransactionInputs=" + rawTransactionInputs +
|
||||
",\n changeOutputValue=" + changeOutputValue +
|
||||
",\n changeOutputAddress='" + changeOutputAddress + '\'' +
|
||||
",\n takerMultiSigPubKey=" + Utilities.bytesAsHexString(takerMultiSigPubKey) +
|
||||
",\n takerPayoutAddressString='" + takerPayoutAddressString + '\'' +
|
||||
",\n takerPubKeyRing=" + takerPubKeyRing +
|
||||
",\n takerPaymentAccountPayload=" + takerPaymentAccountPayload +
|
||||
",\n takerAccountId='" + takerAccountId + '\'' +
|
||||
",\n takerFeeTxId='" + takerFeeTxId + '\'' +
|
||||
",\n acceptedArbitratorNodeAddresses=" + acceptedArbitratorNodeAddresses +
|
||||
",\n acceptedMediatorNodeAddresses=" + acceptedMediatorNodeAddresses +
|
||||
",\n arbitratorNodeAddress=" + arbitratorNodeAddress +
|
||||
",\n mediatorNodeAddress=" + mediatorNodeAddress +
|
||||
",\n uid='" + uid + '\'' +
|
||||
",\n accountAgeWitnessNonce=" + Utilities.bytesAsHexString(accountAgeWitnessNonce) +
|
||||
",\n accountAgeWitnessSignatureOfNonce=" + Utilities.bytesAsHexString(accountAgeWitnessSignatureOfNonce) +
|
||||
"\n} " + super.toString();
|
||||
"\n senderNodeAddress=" + senderNodeAddress +
|
||||
",\n tradeAmount=" + tradeAmount +
|
||||
",\n tradePrice=" + tradePrice +
|
||||
",\n txFee=" + txFee +
|
||||
",\n takerFee=" + takerFee +
|
||||
",\n isCurrencyForTakerFeeBtc=" + isCurrencyForTakerFeeBtc +
|
||||
",\n rawTransactionInputs=" + rawTransactionInputs +
|
||||
",\n changeOutputValue=" + changeOutputValue +
|
||||
",\n changeOutputAddress='" + changeOutputAddress + '\'' +
|
||||
",\n takerMultiSigPubKey=" + Utilities.bytesAsHexString(takerMultiSigPubKey) +
|
||||
",\n takerPayoutAddressString='" + takerPayoutAddressString + '\'' +
|
||||
",\n takerPubKeyRing=" + takerPubKeyRing +
|
||||
",\n takerPaymentAccountPayload=" + takerPaymentAccountPayload +
|
||||
",\n takerAccountId='" + takerAccountId + '\'' +
|
||||
",\n takerFeeTxId='" + takerFeeTxId + '\'' +
|
||||
",\n acceptedArbitratorNodeAddresses=" + acceptedArbitratorNodeAddresses +
|
||||
",\n acceptedMediatorNodeAddresses=" + acceptedMediatorNodeAddresses +
|
||||
",\n arbitratorNodeAddress=" + arbitratorNodeAddress +
|
||||
",\n mediatorNodeAddress=" + mediatorNodeAddress +
|
||||
",\n uid='" + uid + '\'' +
|
||||
",\n accountAgeWitnessSignatureOfAccountData=" + Utilities.bytesAsHexString(accountAgeWitnessSignatureOfAccountData) +
|
||||
",\n accountAgeWitnessNonce=" + Utilities.bytesAsHexString(accountAgeWitnessNonce) +
|
||||
",\n accountAgeWitnessSignatureOfNonce=" + Utilities.bytesAsHexString(accountAgeWitnessSignatureOfNonce) +
|
||||
"\n} " + super.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package io.bisq.core.trade.messages;
|
|||
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.bisq.common.app.Version;
|
||||
import io.bisq.common.proto.ProtoUtil;
|
||||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.core.btc.data.RawTransactionInput;
|
||||
import io.bisq.core.payment.payload.PaymentAccountPayload;
|
||||
|
@ -54,6 +55,8 @@ public final class PublishDepositTxRequest extends TradeMessage implements Mailb
|
|||
|
||||
// added in v 0.6. can be null if we trade with an older peer
|
||||
@Nullable
|
||||
private final byte[] accountAgeWitnessSignatureOfAccountData;
|
||||
@Nullable
|
||||
private final byte[] accountAgeWitnessNonce;
|
||||
@Nullable
|
||||
private final byte[] accountAgeWitnessSignatureOfNonce;
|
||||
|
@ -69,22 +72,24 @@ public final class PublishDepositTxRequest extends TradeMessage implements Mailb
|
|||
List<RawTransactionInput> makerInputs,
|
||||
NodeAddress senderNodeAddress,
|
||||
String uid,
|
||||
@Nullable byte[] accountAgeWitnessSignatureOfAccountData,
|
||||
@Nullable byte[] accountAgeWitnessNonce,
|
||||
@Nullable byte[] accountAgeWitnessSignatureOfNonce) {
|
||||
this(tradeId,
|
||||
makerPaymentAccountPayload,
|
||||
makerAccountId,
|
||||
makerMultiSigPubKey,
|
||||
makerContractAsJson,
|
||||
makerContractSignature,
|
||||
makerPayoutAddressString,
|
||||
preparedDepositTx,
|
||||
makerInputs,
|
||||
senderNodeAddress,
|
||||
uid,
|
||||
Version.getP2PMessageVersion(),
|
||||
accountAgeWitnessNonce,
|
||||
accountAgeWitnessSignatureOfNonce);
|
||||
makerPaymentAccountPayload,
|
||||
makerAccountId,
|
||||
makerMultiSigPubKey,
|
||||
makerContractAsJson,
|
||||
makerContractSignature,
|
||||
makerPayoutAddressString,
|
||||
preparedDepositTx,
|
||||
makerInputs,
|
||||
senderNodeAddress,
|
||||
uid,
|
||||
Version.getP2PMessageVersion(),
|
||||
accountAgeWitnessSignatureOfAccountData,
|
||||
accountAgeWitnessNonce,
|
||||
accountAgeWitnessSignatureOfNonce);
|
||||
}
|
||||
|
||||
|
||||
|
@ -104,6 +109,7 @@ public final class PublishDepositTxRequest extends TradeMessage implements Mailb
|
|||
NodeAddress senderNodeAddress,
|
||||
String uid,
|
||||
int messageVersion,
|
||||
@Nullable byte[] accountAgeWitnessSignatureOfAccountData,
|
||||
@Nullable byte[] accountAgeWitnessNonce,
|
||||
@Nullable byte[] accountAgeWitnessSignatureOfNonce) {
|
||||
super(messageVersion, tradeId);
|
||||
|
@ -117,6 +123,7 @@ public final class PublishDepositTxRequest extends TradeMessage implements Mailb
|
|||
this.makerInputs = makerInputs;
|
||||
this.senderNodeAddress = senderNodeAddress;
|
||||
this.uid = uid;
|
||||
this.accountAgeWitnessSignatureOfAccountData = accountAgeWitnessSignatureOfAccountData;
|
||||
this.accountAgeWitnessNonce = accountAgeWitnessNonce;
|
||||
this.accountAgeWitnessSignatureOfNonce = accountAgeWitnessSignatureOfNonce;
|
||||
}
|
||||
|
@ -124,63 +131,66 @@ public final class PublishDepositTxRequest extends TradeMessage implements Mailb
|
|||
@Override
|
||||
public PB.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
final PB.PublishDepositTxRequest.Builder builder = PB.PublishDepositTxRequest.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setMakerPaymentAccountPayload((PB.PaymentAccountPayload) makerPaymentAccountPayload.toProtoMessage())
|
||||
.setMakerAccountId(makerAccountId)
|
||||
.setMakerMultiSigPubKey(ByteString.copyFrom(makerMultiSigPubKey))
|
||||
.setMakerContractAsJson(makerContractAsJson)
|
||||
.setMakerContractSignature(makerContractSignature)
|
||||
.setMakerPayoutAddressString(makerPayoutAddressString)
|
||||
.setPreparedDepositTx(ByteString.copyFrom(preparedDepositTx))
|
||||
.addAllMakerInputs(makerInputs.stream().map(RawTransactionInput::toProtoMessage).collect(Collectors.toList()))
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setUid(uid);
|
||||
|
||||
Optional.ofNullable(accountAgeWitnessNonce).ifPresent(accountAgeWitnessNonce ->builder.setAccountAgeWitnessNonce(ByteString.copyFrom(accountAgeWitnessNonce)));
|
||||
Optional.ofNullable(accountAgeWitnessSignatureOfNonce).ifPresent(accountAgeWitnessSignatureOfNonce ->builder.setAccountAgeWitnessSignatureOfNonce(ByteString.copyFrom(accountAgeWitnessSignatureOfNonce)));
|
||||
.setTradeId(tradeId)
|
||||
.setMakerPaymentAccountPayload((PB.PaymentAccountPayload) makerPaymentAccountPayload.toProtoMessage())
|
||||
.setMakerAccountId(makerAccountId)
|
||||
.setMakerMultiSigPubKey(ByteString.copyFrom(makerMultiSigPubKey))
|
||||
.setMakerContractAsJson(makerContractAsJson)
|
||||
.setMakerContractSignature(makerContractSignature)
|
||||
.setMakerPayoutAddressString(makerPayoutAddressString)
|
||||
.setPreparedDepositTx(ByteString.copyFrom(preparedDepositTx))
|
||||
.addAllMakerInputs(makerInputs.stream().map(RawTransactionInput::toProtoMessage).collect(Collectors.toList()))
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setUid(uid);
|
||||
|
||||
Optional.ofNullable(accountAgeWitnessSignatureOfAccountData).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfAccountData(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(accountAgeWitnessNonce).ifPresent(e -> builder.setAccountAgeWitnessNonce(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(accountAgeWitnessSignatureOfNonce).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfNonce(ByteString.copyFrom(e)));
|
||||
|
||||
return getNetworkEnvelopeBuilder()
|
||||
.setPublishDepositTxRequest(builder)
|
||||
.build();
|
||||
.setPublishDepositTxRequest(builder)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static PublishDepositTxRequest fromProto(PB.PublishDepositTxRequest proto, CoreProtoResolver coreProtoResolver, int messageVersion) {
|
||||
List<RawTransactionInput> makerInputs = proto.getMakerInputsList().stream()
|
||||
.map(RawTransactionInput::fromProto)
|
||||
.collect(Collectors.toList());
|
||||
.map(RawTransactionInput::fromProto)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new PublishDepositTxRequest(proto.getTradeId(),
|
||||
coreProtoResolver.fromProto(proto.getMakerPaymentAccountPayload()),
|
||||
proto.getMakerAccountId(),
|
||||
proto.getMakerMultiSigPubKey().toByteArray(),
|
||||
proto.getMakerContractAsJson(),
|
||||
proto.getMakerContractSignature(),
|
||||
proto.getMakerPayoutAddressString(),
|
||||
proto.getPreparedDepositTx().toByteArray(),
|
||||
makerInputs,
|
||||
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
||||
proto.getUid(),
|
||||
messageVersion,
|
||||
proto.getAccountAgeWitnessNonce().isEmpty() ? null : proto.getAccountAgeWitnessNonce().toByteArray(),
|
||||
proto.getAccountAgeWitnessSignatureOfNonce().isEmpty() ? null : proto.getAccountAgeWitnessSignatureOfNonce().toByteArray());
|
||||
coreProtoResolver.fromProto(proto.getMakerPaymentAccountPayload()),
|
||||
proto.getMakerAccountId(),
|
||||
proto.getMakerMultiSigPubKey().toByteArray(),
|
||||
proto.getMakerContractAsJson(),
|
||||
proto.getMakerContractSignature(),
|
||||
proto.getMakerPayoutAddressString(),
|
||||
proto.getPreparedDepositTx().toByteArray(),
|
||||
makerInputs,
|
||||
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
||||
proto.getUid(),
|
||||
messageVersion,
|
||||
ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfAccountData()),
|
||||
ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessNonce()),
|
||||
ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfNonce()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PublishDepositTxRequest{" +
|
||||
"\n makerPaymentAccountPayload=" + makerPaymentAccountPayload +
|
||||
",\n makerAccountId='" + makerAccountId + '\'' +
|
||||
",\n makerMultiSigPubKey=" + Utilities.bytesAsHexString(makerMultiSigPubKey) +
|
||||
",\n makerContractAsJson='" + makerContractAsJson + '\'' +
|
||||
",\n makerContractSignature='" + makerContractSignature + '\'' +
|
||||
",\n makerPayoutAddressString='" + makerPayoutAddressString + '\'' +
|
||||
",\n preparedDepositTx=" + Utilities.bytesAsHexString(preparedDepositTx) +
|
||||
",\n makerInputs=" + makerInputs +
|
||||
",\n senderNodeAddress=" + senderNodeAddress +
|
||||
",\n uid='" + uid + '\'' +
|
||||
",\n accountAgeWitnessNonce=" + Utilities.bytesAsHexString(accountAgeWitnessNonce) +
|
||||
",\n accountAgeWitnessSignatureOfNonce=" + Utilities.bytesAsHexString(accountAgeWitnessSignatureOfNonce) +
|
||||
"\n} " + super.toString();
|
||||
"\n makerPaymentAccountPayload=" + makerPaymentAccountPayload +
|
||||
",\n makerAccountId='" + makerAccountId + '\'' +
|
||||
",\n makerMultiSigPubKey=" + Utilities.bytesAsHexString(makerMultiSigPubKey) +
|
||||
",\n makerContractAsJson='" + makerContractAsJson + '\'' +
|
||||
",\n makerContractSignature='" + makerContractSignature + '\'' +
|
||||
",\n makerPayoutAddressString='" + makerPayoutAddressString + '\'' +
|
||||
",\n preparedDepositTx=" + Utilities.bytesAsHexString(preparedDepositTx) +
|
||||
",\n makerInputs=" + makerInputs +
|
||||
",\n senderNodeAddress=" + senderNodeAddress +
|
||||
",\n uid='" + uid + '\'' +
|
||||
",\n accountAgeWitnessSignatureOfAccountData=" + Utilities.bytesAsHexString(accountAgeWitnessSignatureOfAccountData) +
|
||||
",\n accountAgeWitnessNonce=" + Utilities.bytesAsHexString(accountAgeWitnessNonce) +
|
||||
",\n accountAgeWitnessSignatureOfNonce=" + Utilities.bytesAsHexString(accountAgeWitnessSignatureOfNonce) +
|
||||
"\n} " + super.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
|||
TakerProcessPublishDepositTxRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyOffersAccountAgeWitnessHash.class,
|
||||
VerifyPeersAccountAgeWitness.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
TakerVerifyAndSignContract.class,
|
||||
|
|
|
@ -29,7 +29,6 @@ import io.bisq.core.trade.messages.TradeMessage;
|
|||
import io.bisq.core.trade.protocol.tasks.CheckIfPeerIsBanned;
|
||||
import io.bisq.core.trade.protocol.tasks.PublishAccountAgeWitness;
|
||||
import io.bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness;
|
||||
import io.bisq.core.trade.protocol.tasks.taker.TakerVerifyOffersAccountAgeWitnessHash;
|
||||
import io.bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx;
|
||||
import io.bisq.core.trade.protocol.tasks.seller.SellerProcessCounterCurrencyTransferStartedMessage;
|
||||
import io.bisq.core.trade.protocol.tasks.seller.SellerSendPayoutTxPublishedMessage;
|
||||
|
@ -123,7 +122,6 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
|||
TakerProcessPublishDepositTxRequest.class,
|
||||
CheckIfPeerIsBanned.class,
|
||||
TakerVerifyMakerAccount.class,
|
||||
TakerVerifyOffersAccountAgeWitnessHash.class,
|
||||
VerifyPeersAccountAgeWitness.class,
|
||||
TakerVerifyMakerFeePayment.class,
|
||||
TakerVerifyAndSignContract.class,
|
||||
|
|
|
@ -60,6 +60,10 @@ public final class TradingPeer implements PersistablePayload {
|
|||
private long changeOutputValue;
|
||||
@Nullable
|
||||
private String changeOutputAddress;
|
||||
|
||||
// added in v 0.6
|
||||
@Nullable
|
||||
private byte[] accountAgeWitnessSignatureOfAccountData;
|
||||
@Nullable
|
||||
private byte[] accountAgeWitnessNonce;
|
||||
@Nullable
|
||||
|
@ -71,7 +75,7 @@ public final class TradingPeer implements PersistablePayload {
|
|||
@Override
|
||||
public Message toProtoMessage() {
|
||||
final PB.TradingPeer.Builder builder = PB.TradingPeer.newBuilder()
|
||||
.setChangeOutputValue(changeOutputValue);
|
||||
.setChangeOutputValue(changeOutputValue);
|
||||
Optional.ofNullable(accountId).ifPresent(builder::setAccountId);
|
||||
Optional.ofNullable(paymentAccountPayload).ifPresent(e -> builder.setPaymentAccountPayload((PB.PaymentAccountPayload) e.toProtoMessage()));
|
||||
Optional.ofNullable(payoutAddressString).ifPresent(builder::setPayoutAddressString);
|
||||
|
@ -82,6 +86,7 @@ public final class TradingPeer implements PersistablePayload {
|
|||
Optional.ofNullable(multiSigPubKey).ifPresent(e -> builder.setMultiSigPubKey(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(rawTransactionInputs).ifPresent(e -> builder.addAllRawTransactionInputs(ProtoUtil.collectionToProto(e)));
|
||||
Optional.ofNullable(changeOutputAddress).ifPresent(builder::setChangeOutputAddress);
|
||||
Optional.ofNullable(accountAgeWitnessSignatureOfAccountData).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfAccountData(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(accountAgeWitnessNonce).ifPresent(e -> builder.setAccountAgeWitnessNonce(ByteString.copyFrom(e)));
|
||||
Optional.ofNullable(accountAgeWitnessSignatureOfNonce).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfNonce(ByteString.copyFrom(e)));
|
||||
return builder.build();
|
||||
|
@ -102,12 +107,13 @@ public final class TradingPeer implements PersistablePayload {
|
|||
tradingPeer.setPubKeyRing(proto.hasPubKeyRing() ? PubKeyRing.fromProto(proto.getPubKeyRing()) : null);
|
||||
tradingPeer.setMultiSigPubKey(ProtoUtil.byteArrayOrNullFromProto(proto.getMultiSigPubKey()));
|
||||
List<RawTransactionInput> rawTransactionInputs = proto.getRawTransactionInputsList().isEmpty() ?
|
||||
null :
|
||||
proto.getRawTransactionInputsList().stream()
|
||||
.map(RawTransactionInput::fromProto)
|
||||
.collect(Collectors.toList());
|
||||
null :
|
||||
proto.getRawTransactionInputsList().stream()
|
||||
.map(RawTransactionInput::fromProto)
|
||||
.collect(Collectors.toList());
|
||||
tradingPeer.setRawTransactionInputs(rawTransactionInputs);
|
||||
tradingPeer.setChangeOutputAddress(ProtoUtil.stringOrNullFromProto(proto.getChangeOutputAddress()));
|
||||
tradingPeer.setAccountAgeWitnessNonce(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfAccountData()));
|
||||
tradingPeer.setAccountAgeWitnessNonce(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessNonce()));
|
||||
tradingPeer.setAccountAgeWitnessSignatureOfNonce(ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfNonce()));
|
||||
return tradingPeer;
|
||||
|
|
|
@ -32,7 +32,7 @@ public class PublishAccountAgeWitness extends TradeTask {
|
|||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
processModel.getAccountAgeWitnessService().publishAccountAgeWitness(processModel.getPaymentAccountPayload(trade));
|
||||
processModel.getAccountAgeWitnessService().publishMyAccountAgeWitness(processModel.getPaymentAccountPayload(trade));
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
|
|
|
@ -19,10 +19,12 @@ package io.bisq.core.trade.protocol.tasks;
|
|||
|
||||
import io.bisq.common.crypto.PubKeyRing;
|
||||
import io.bisq.common.taskrunner.TaskRunner;
|
||||
import io.bisq.core.offer.Offer;
|
||||
import io.bisq.core.payment.AccountAgeWitness;
|
||||
import io.bisq.core.payment.AccountAgeWitnessService;
|
||||
import io.bisq.core.payment.payload.PaymentAccountPayload;
|
||||
import io.bisq.core.trade.Trade;
|
||||
import io.bisq.core.trade.protocol.TradingPeer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Date;
|
||||
|
@ -45,49 +47,46 @@ public class VerifyPeersAccountAgeWitness extends TradeTask {
|
|||
runInterceptHook();
|
||||
|
||||
final AccountAgeWitnessService accountAgeWitnessService = processModel.getAccountAgeWitnessService();
|
||||
final PaymentAccountPayload peersPaymentAccountPayload = checkNotNull(processModel.getTradingPeer().getPaymentAccountPayload(),
|
||||
"Peers peersPaymentAccountPayload must not be null");
|
||||
|
||||
final String[] errorMsg1 = new String[1];
|
||||
boolean result = accountAgeWitnessService.verifyTradeLimit(trade.getOffer(), peersPaymentAccountPayload, errorMessage -> errorMsg1[0] = errorMessage);
|
||||
if (result) {
|
||||
byte[] nonce = processModel.getTradingPeer().getAccountAgeWitnessNonce();
|
||||
byte[] signatureOfNonce = processModel.getTradingPeer().getAccountAgeWitnessSignatureOfNonce();
|
||||
Optional<AccountAgeWitness> witnessOptional = accountAgeWitnessService.getWitnessByPaymentAccountPayload(peersPaymentAccountPayload);
|
||||
if (witnessOptional.isPresent() && nonce != null && signatureOfNonce != null) {
|
||||
AccountAgeWitness witness = witnessOptional.get();
|
||||
final PubKeyRing pubKeyRing = processModel.getTradingPeer().getPubKeyRing();
|
||||
checkNotNull(pubKeyRing, "processModel.getTradingPeer().getPubKeyRing() must not be null");
|
||||
final String[] errorMsg2 = new String[1];
|
||||
result = accountAgeWitnessService.verifyAccountAgeWitness(peersPaymentAccountPayload.getAgeWitnessInputData(),
|
||||
witness,
|
||||
peersPaymentAccountPayload.getSalt(),
|
||||
pubKeyRing.getSignaturePubKey(),
|
||||
nonce,
|
||||
signatureOfNonce,
|
||||
errorMessage -> errorMsg2[0] = errorMessage);
|
||||
if (result)
|
||||
complete();
|
||||
else
|
||||
failed(errorMsg2[0]);
|
||||
} else {
|
||||
String msg = !witnessOptional.isPresent() ?
|
||||
"Peers AccountAgeWitness is not found." :
|
||||
"Peer seems to uses a pre v0.6 application which does not support sending of account age witness verification nonce and signature.";
|
||||
msg += "\nTrade ID=" + trade.getId();
|
||||
if (new Date().after(new GregorianCalendar(2018, GregorianCalendar.FEBRUARY, 1).getTime())) {
|
||||
msg = "The account age witness verification failed.\nReason: " + msg;
|
||||
log.error(msg);
|
||||
failed(msg);
|
||||
} else {
|
||||
log.warn(msg + "\nWe tolerate that until 1. of Feb. 2018");
|
||||
complete();
|
||||
}
|
||||
}
|
||||
final TradingPeer tradingPeer = processModel.getTradingPeer();
|
||||
final PaymentAccountPayload peersPaymentAccountPayload = checkNotNull(tradingPeer.getPaymentAccountPayload(),
|
||||
"Peers peersPaymentAccountPayload must not be null");
|
||||
final PubKeyRing peersPubKeyRing = checkNotNull(tradingPeer.getPubKeyRing(), "peersPubKeyRing must not be null");
|
||||
final Offer offer = trade.getOffer();
|
||||
final Optional<String> accountAgeWitnessHashAsHex = offer.getAccountAgeWitnessHashAsHex();
|
||||
Optional<AccountAgeWitness> witnessOptional = accountAgeWitnessHashAsHex.isPresent() ?
|
||||
accountAgeWitnessService.getPeersWitnessByHashAsHex(accountAgeWitnessHashAsHex.get())
|
||||
: Optional.<AccountAgeWitness>empty();
|
||||
byte[] nonce = tradingPeer.getAccountAgeWitnessNonce();
|
||||
byte[] signatureOfNonce = tradingPeer.getAccountAgeWitnessSignatureOfNonce();
|
||||
if (witnessOptional.isPresent() && nonce != null && signatureOfNonce != null) {
|
||||
AccountAgeWitness witness = witnessOptional.get();
|
||||
final String[] errorMsg = new String[1];
|
||||
byte[] peersSignatureOfAccountHash = tradingPeer.getAccountAgeWitnessSignatureOfAccountData();
|
||||
boolean result = accountAgeWitnessService.verifyPeersAccountAgeWitness(offer,
|
||||
peersPaymentAccountPayload,
|
||||
witness,
|
||||
peersPubKeyRing,
|
||||
peersSignatureOfAccountHash,
|
||||
nonce,
|
||||
signatureOfNonce,
|
||||
errorMessage -> errorMsg[0] = errorMessage);
|
||||
if (result)
|
||||
complete();
|
||||
else
|
||||
failed(errorMsg[0]);
|
||||
} else {
|
||||
String msg = "The offer verification failed.\nReason: " + errorMsg1[0];
|
||||
log.error(msg);
|
||||
failed(msg);
|
||||
String msg = !witnessOptional.isPresent() ?
|
||||
"Peers AccountAgeWitness is not found." :
|
||||
"Peer seems to uses a pre v0.6 application which does not support sending of account age witness verification nonce and signature.";
|
||||
msg += "\nTrade ID=" + trade.getId();
|
||||
if (new Date().after(new GregorianCalendar(2018, GregorianCalendar.FEBRUARY, 1).getTime())) {
|
||||
msg = "The account age witness verification failed.\nReason: " + msg;
|
||||
log.error(msg);
|
||||
failed(msg);
|
||||
} else {
|
||||
log.warn(msg + "\nWe tolerate offers without account age witness until first of Feb. 2018");
|
||||
complete();
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
|
|
|
@ -66,13 +66,14 @@ public class MakerProcessPayDepositRequest extends TradeTask {
|
|||
if (payDepositRequest.getAcceptedArbitratorNodeAddresses().isEmpty())
|
||||
failed("acceptedArbitratorNames must not be empty");
|
||||
|
||||
processModel.getTradingPeer().setAccountAgeWitnessSignatureOfAccountData(payDepositRequest.getAccountAgeWitnessSignatureOfAccountData());
|
||||
final byte[] accountAgeWitnessNonce = payDepositRequest.getAccountAgeWitnessNonce();
|
||||
processModel.getTradingPeer().setAccountAgeWitnessNonce(accountAgeWitnessNonce);
|
||||
processModel.getTradingPeer().setAccountAgeWitnessSignatureOfNonce(payDepositRequest.getAccountAgeWitnessSignatureOfNonce());
|
||||
// Taker has to use offerId as nonce (he cannot manipulate that - so we avoid to have a challenge protocol for passing the nonce we want to get signed)
|
||||
// He cannot manipulate the offerId - so we avoid to have a challenge protocol for passing the nonce we want to get signed.
|
||||
checkArgument(Arrays.equals(accountAgeWitnessNonce, trade.getOffer().getId().getBytes()));
|
||||
|
||||
|
||||
trade.setArbitratorNodeAddress(checkNotNull(payDepositRequest.getArbitratorNodeAddress()));
|
||||
trade.setMediatorNodeAddress(checkNotNull(payDepositRequest.getMediatorNodeAddress()));
|
||||
|
||||
|
@ -98,4 +99,4 @@ public class MakerProcessPayDepositRequest extends TradeTask {
|
|||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import io.bisq.common.crypto.Sig;
|
|||
import io.bisq.common.taskrunner.TaskRunner;
|
||||
import io.bisq.core.btc.AddressEntry;
|
||||
import io.bisq.core.btc.wallet.BtcWalletService;
|
||||
import io.bisq.core.payment.payload.PaymentAccountPayload;
|
||||
import io.bisq.core.trade.Trade;
|
||||
import io.bisq.core.trade.messages.PublishDepositTxRequest;
|
||||
import io.bisq.core.trade.protocol.tasks.TradeTask;
|
||||
|
@ -32,6 +33,7 @@ import java.util.Optional;
|
|||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@Slf4j
|
||||
public class MakerSendPublishDepositTxRequest extends TradeTask {
|
||||
|
@ -52,60 +54,66 @@ public class MakerSendPublishDepositTxRequest extends TradeTask {
|
|||
AddressEntry makerPayoutAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT);
|
||||
byte[] makerMultiSigPubKey = processModel.getMyMultiSigPubKey();
|
||||
checkArgument(Arrays.equals(makerMultiSigPubKey,
|
||||
addressEntryOptional.get().getPubKey()),
|
||||
"makerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
|
||||
addressEntryOptional.get().getPubKey()),
|
||||
"makerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id);
|
||||
|
||||
final byte[] preparedDepositTx = processModel.getPreparedDepositTx();
|
||||
|
||||
// Maker has to use preparedDepositTx as nonce.
|
||||
|
||||
// Maker has to use preparedDepositTx as nonce.
|
||||
// He cannot manipulate the preparedDepositTx - so we avoid to have a challenge protocol for passing the nonce we want to get signed.
|
||||
final PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade), "processModel.getPaymentAccountPayload(trade) must not be null");
|
||||
byte[] accountAgeWitnessSignatureOfAccountData = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(),
|
||||
processModel.getAccountAgeWitnessService().getAccountInputDataWithSalt(paymentAccountPayload));
|
||||
|
||||
//noinspection UnnecessaryLocalVariable
|
||||
byte[] accountAgeWitnessNonce = preparedDepositTx;
|
||||
byte[] accountAgeWitnessSignatureOfNonce = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), accountAgeWitnessNonce);
|
||||
|
||||
PublishDepositTxRequest message = new PublishDepositTxRequest(
|
||||
processModel.getOfferId(),
|
||||
processModel.getPaymentAccountPayload(trade),
|
||||
processModel.getAccountId(),
|
||||
makerMultiSigPubKey,
|
||||
trade.getContractAsJson(),
|
||||
trade.getMakerContractSignature(),
|
||||
makerPayoutAddressEntry.getAddressString(),
|
||||
preparedDepositTx,
|
||||
processModel.getRawTransactionInputs(),
|
||||
processModel.getMyNodeAddress(),
|
||||
UUID.randomUUID().toString(),
|
||||
accountAgeWitnessNonce,
|
||||
accountAgeWitnessSignatureOfNonce);
|
||||
|
||||
processModel.getOfferId(),
|
||||
paymentAccountPayload,
|
||||
processModel.getAccountId(),
|
||||
makerMultiSigPubKey,
|
||||
trade.getContractAsJson(),
|
||||
trade.getMakerContractSignature(),
|
||||
makerPayoutAddressEntry.getAddressString(),
|
||||
preparedDepositTx,
|
||||
processModel.getRawTransactionInputs(),
|
||||
processModel.getMyNodeAddress(),
|
||||
UUID.randomUUID().toString(),
|
||||
accountAgeWitnessSignatureOfAccountData,
|
||||
accountAgeWitnessNonce,
|
||||
accountAgeWitnessSignatureOfNonce);
|
||||
|
||||
trade.setState(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
|
||||
processModel.getP2PService().sendEncryptedMailboxMessage(
|
||||
trade.getTradingPeerNodeAddress(),
|
||||
processModel.getTradingPeer().getPubKeyRing(),
|
||||
message,
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("Message arrived at peer. tradeId={}", id);
|
||||
trade.setState(Trade.State.MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("Message stored in mailbox. tradeId={}", id);
|
||||
trade.setState(Trade.State.MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMailboxMessage failed. message=" + message);
|
||||
trade.setState(Trade.State.MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
failed(errorMessage);
|
||||
}
|
||||
trade.getTradingPeerNodeAddress(),
|
||||
processModel.getTradingPeer().getPubKeyRing(),
|
||||
message,
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("Message arrived at peer. tradeId={}", id);
|
||||
trade.setState(Trade.State.MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("Message stored in mailbox. tradeId={}", id);
|
||||
trade.setState(Trade.State.MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("sendEncryptedMailboxMessage failed. message=" + message);
|
||||
trade.setState(Trade.State.MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST);
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
failed(errorMessage);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -54,7 +54,7 @@ public class MakerSetupDepositTxListener extends TradeTask {
|
|||
if (walletService.getBalanceForAddress(address).isZero()) {
|
||||
trade.setState(Trade.State.MAKER_SAW_DEPOSIT_TX_IN_NETWORK);
|
||||
swapReservedForTradeEntry();
|
||||
processModel.getAccountAgeWitnessService().publishAccountAgeWitness(processModel.getPaymentAccountPayload(trade));
|
||||
processModel.getAccountAgeWitnessService().publishMyAccountAgeWitness(processModel.getPaymentAccountPayload(trade));
|
||||
} else {
|
||||
listener = new BalanceListener(address) {
|
||||
@Override
|
||||
|
@ -62,7 +62,7 @@ public class MakerSetupDepositTxListener extends TradeTask {
|
|||
if (balance.isZero() && trade.getState().getPhase() == Trade.Phase.TAKER_FEE_PUBLISHED) {
|
||||
trade.setState(Trade.State.MAKER_SAW_DEPOSIT_TX_IN_NETWORK);
|
||||
swapReservedForTradeEntry();
|
||||
processModel.getAccountAgeWitnessService().publishAccountAgeWitness(processModel.getPaymentAccountPayload(trade));
|
||||
processModel.getAccountAgeWitnessService().publishMyAccountAgeWitness(processModel.getPaymentAccountPayload(trade));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -56,10 +56,11 @@ public class TakerProcessPublishDepositTxRequest extends TradeTask {
|
|||
final byte[] preparedDepositTx = publishDepositTxRequest.getPreparedDepositTx();
|
||||
processModel.setPreparedDepositTx(checkNotNull(preparedDepositTx));
|
||||
|
||||
processModel.getTradingPeer().setAccountAgeWitnessSignatureOfAccountData(publishDepositTxRequest.getAccountAgeWitnessSignatureOfAccountData());
|
||||
final byte[] accountAgeWitnessNonce = publishDepositTxRequest.getAccountAgeWitnessNonce();
|
||||
processModel.getTradingPeer().setAccountAgeWitnessNonce(accountAgeWitnessNonce);
|
||||
processModel.getTradingPeer().setAccountAgeWitnessSignatureOfNonce(publishDepositTxRequest.getAccountAgeWitnessSignatureOfNonce());
|
||||
// Maker has to use preparedDepositTx as nonce.
|
||||
// Maker has to use preparedDepositTx as nonce.
|
||||
// He cannot manipulate the preparedDepositTx - so we avoid to have a challenge protocol for passing the nonce we want to get signed.
|
||||
checkArgument(Arrays.equals(accountAgeWitnessNonce, preparedDepositTx));
|
||||
|
||||
|
@ -74,4 +75,4 @@ public class TakerProcessPublishDepositTxRequest extends TradeTask {
|
|||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import io.bisq.common.crypto.Sig;
|
|||
import io.bisq.common.taskrunner.TaskRunner;
|
||||
import io.bisq.core.btc.AddressEntry;
|
||||
import io.bisq.core.btc.wallet.BtcWalletService;
|
||||
import io.bisq.core.payment.payload.PaymentAccountPayload;
|
||||
import io.bisq.core.trade.Trade;
|
||||
import io.bisq.core.trade.messages.PayDepositRequest;
|
||||
import io.bisq.core.trade.protocol.tasks.TradeTask;
|
||||
|
@ -61,7 +62,7 @@ public class TakerSendPayDepositRequest extends TradeTask {
|
|||
String id = processModel.getOffer().getId();
|
||||
|
||||
checkArgument(!walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG).isPresent(),
|
||||
"addressEntry must not be set here.");
|
||||
"addressEntry must not be set here.");
|
||||
AddressEntry addressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG);
|
||||
byte[] takerMultiSigPubKey = addressEntry.getPubKey();
|
||||
processModel.setMyMultiSigPubKey(takerMultiSigPubKey);
|
||||
|
@ -70,55 +71,59 @@ public class TakerSendPayDepositRequest extends TradeTask {
|
|||
String takerPayoutAddressString = takerPayoutAddressEntry.getAddressString();
|
||||
|
||||
final String offerId = processModel.getOfferId();
|
||||
|
||||
|
||||
// Taker has to use offerId as nonce (he cannot manipulate that - so we avoid to have a challenge protocol for passing the nonce we want to get signed)
|
||||
// He cannot manipulate the offerId - so we avoid to have a challenge protocol for passing the nonce we want to get signed.
|
||||
final PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade), "processModel.getPaymentAccountPayload(trade) must not be null");
|
||||
byte[] accountAgeWitnessSignatureOfAccountData = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(),
|
||||
processModel.getAccountAgeWitnessService().getAccountInputDataWithSalt(paymentAccountPayload));
|
||||
byte[] accountAgeWitnessNonce = offerId.getBytes();
|
||||
byte[] accountAgeWitnessSignatureOfNonce = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), accountAgeWitnessNonce);
|
||||
|
||||
|
||||
PayDepositRequest message = new PayDepositRequest(
|
||||
offerId,
|
||||
processModel.getMyNodeAddress(),
|
||||
trade.getTradeAmount().value,
|
||||
trade.getTradePrice().getValue(),
|
||||
trade.getTxFee().getValue(),
|
||||
trade.getTakerFee().getValue(),
|
||||
trade.isCurrencyForTakerFeeBtc(),
|
||||
processModel.getRawTransactionInputs(),
|
||||
processModel.getChangeOutputValue(),
|
||||
processModel.getChangeOutputAddress(),
|
||||
takerMultiSigPubKey,
|
||||
takerPayoutAddressString,
|
||||
processModel.getPubKeyRing(),
|
||||
processModel.getPaymentAccountPayload(trade),
|
||||
processModel.getAccountId(),
|
||||
trade.getTakerFeeTxId(),
|
||||
new ArrayList<>(acceptedArbitratorAddresses),
|
||||
new ArrayList<>(acceptedMediatorAddresses),
|
||||
trade.getArbitratorNodeAddress(),
|
||||
trade.getMediatorNodeAddress(),
|
||||
UUID.randomUUID().toString(),
|
||||
Version.getP2PMessageVersion(),
|
||||
accountAgeWitnessNonce,
|
||||
accountAgeWitnessSignatureOfNonce);
|
||||
offerId,
|
||||
processModel.getMyNodeAddress(),
|
||||
trade.getTradeAmount().value,
|
||||
trade.getTradePrice().getValue(),
|
||||
trade.getTxFee().getValue(),
|
||||
trade.getTakerFee().getValue(),
|
||||
trade.isCurrencyForTakerFeeBtc(),
|
||||
processModel.getRawTransactionInputs(),
|
||||
processModel.getChangeOutputValue(),
|
||||
processModel.getChangeOutputAddress(),
|
||||
takerMultiSigPubKey,
|
||||
takerPayoutAddressString,
|
||||
processModel.getPubKeyRing(),
|
||||
paymentAccountPayload,
|
||||
processModel.getAccountId(),
|
||||
trade.getTakerFeeTxId(),
|
||||
new ArrayList<>(acceptedArbitratorAddresses),
|
||||
new ArrayList<>(acceptedMediatorAddresses),
|
||||
trade.getArbitratorNodeAddress(),
|
||||
trade.getMediatorNodeAddress(),
|
||||
UUID.randomUUID().toString(),
|
||||
Version.getP2PMessageVersion(),
|
||||
accountAgeWitnessSignatureOfAccountData,
|
||||
accountAgeWitnessNonce,
|
||||
accountAgeWitnessSignatureOfNonce);
|
||||
|
||||
processModel.getP2PService().sendEncryptedDirectMessage(
|
||||
trade.getTradingPeerNodeAddress(),
|
||||
processModel.getTradingPeer().getPubKeyRing(),
|
||||
message,
|
||||
new SendDirectMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.debug("Message arrived at peer. tradeId={}, message{}", id, message);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
failed();
|
||||
}
|
||||
trade.getTradingPeerNodeAddress(),
|
||||
processModel.getTradingPeer().getPubKeyRing(),
|
||||
message,
|
||||
new SendDirectMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.debug("Message arrived at peer. tradeId={}, message{}", id, message);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault() {
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
failed();
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
|
|
|
@ -1,75 +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 io.bisq.core.trade.protocol.tasks.taker;
|
||||
|
||||
import io.bisq.common.taskrunner.TaskRunner;
|
||||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.core.offer.OfferPayload;
|
||||
import io.bisq.core.payment.payload.PaymentAccountPayload;
|
||||
import io.bisq.core.trade.Trade;
|
||||
import io.bisq.core.trade.protocol.tasks.TradeTask;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@Slf4j
|
||||
public class TakerVerifyOffersAccountAgeWitnessHash extends TradeTask {
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
public TakerVerifyOffersAccountAgeWitnessHash(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
final PaymentAccountPayload peersPaymentAccountPayload = checkNotNull(processModel.getTradingPeer().getPaymentAccountPayload(),
|
||||
"Peers paymentAccountPayload must not be null");
|
||||
final Map<String, String> extraDataMap = trade.getOffer().getExtraDataMap();
|
||||
if (extraDataMap != null && extraDataMap.containsKey(OfferPayload.ACCOUNT_AGE_WITNESS_HASH)) {
|
||||
final String[] errorMsg2 = new String[1];
|
||||
boolean result = processModel.getAccountAgeWitnessService().verifyOffersAccountAgeWitness(peersPaymentAccountPayload,
|
||||
Utilities.decodeFromHex(extraDataMap.get(OfferPayload.ACCOUNT_AGE_WITNESS_HASH)),
|
||||
errorMessage -> errorMsg2[0] = errorMessage);
|
||||
if (result)
|
||||
complete();
|
||||
else
|
||||
failed(errorMsg2[0]);
|
||||
} else {
|
||||
String msg = "ACCOUNT_AGE_WITNESS_HASH is not found in offer.\nThat is expected for offers created before v.0.6." +
|
||||
"\nTrade ID=" + trade.getId();
|
||||
if (new Date().after(new GregorianCalendar(2018, GregorianCalendar.FEBRUARY, 1).getTime())) {
|
||||
msg = "The offer verification failed.\nReason: " + msg;
|
||||
log.error(msg);
|
||||
failed(msg);
|
||||
} else {
|
||||
log.warn(msg + "\nWe tolerate that until 1. of Feb. 2018");
|
||||
complete();
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -71,14 +71,6 @@ public class AccountAgeWitnessServiceTest {
|
|||
assertFalse(service.isTradeDateAfterReleaseDate(tradeDate.getTime(), ageWitnessReleaseDate, errorMessage -> {}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVerifySigPubKey() {
|
||||
byte[] sigPubKeHash = Hash.getSha256Ripemd160hash(Sig.getPublicKeyBytes(publicKey));
|
||||
assertFalse(service.verifySigPubKeyHash(new byte[0], publicKey, errorMessage -> {}));
|
||||
assertFalse(service.verifySigPubKeyHash(new byte[1], publicKey, errorMessage -> {}));
|
||||
assertTrue(service.verifySigPubKeyHash(sigPubKeHash, publicKey, errorMessage -> {}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVerifySignature() throws CryptoException {
|
||||
byte[] ageWitnessInputData = "test".getBytes(Charset.forName("UTF-8"));
|
||||
|
|
|
@ -50,14 +50,14 @@ public class PeerInfoIcon extends Group {
|
|||
peerTagMap = preferences.getPeerTagMap();
|
||||
|
||||
boolean hasTraded = numTrades > 0;
|
||||
String accountAge = formatter.formatAccountAge(accountAgeWitnessService.getAccountAge(offer));
|
||||
String accountAge = formatter.formatAccountAge(accountAgeWitnessService.getPeersAccountAge(offer));
|
||||
tooltipText = hasTraded ?
|
||||
Res.get("peerInfoIcon.tooltip.trade.traded", role, hostName, numTrades, accountAge) :
|
||||
Res.get("peerInfoIcon.tooltip.trade.notTraded", role, hostName, accountAge);
|
||||
|
||||
// outer circle
|
||||
Color ringColor;
|
||||
switch (accountAgeWitnessService.getAccountAgeCategory(accountAgeWitnessService.getAccountAge(offer))) {
|
||||
switch (accountAgeWitnessService.getAccountAgeCategory(accountAgeWitnessService.getPeersAccountAge(offer))) {
|
||||
case TWO_MONTHS_OR_MORE:
|
||||
ringColor = Color.rgb(0, 225, 0); // > 2 months green
|
||||
break;
|
||||
|
|
|
@ -151,10 +151,10 @@ public abstract class PaymentMethodForm {
|
|||
CurrencyUtil.getDefaultTradeCurrency();
|
||||
|
||||
final boolean isAddAccountScreen = paymentAccount.getAccountName() == null;
|
||||
final long accountAge = !isAddAccountScreen ? accountAgeWitnessService.getAccountAge(paymentAccount.getPaymentAccountPayload()) : 0L;
|
||||
final long accountAge = !isAddAccountScreen ? accountAgeWitnessService.getMyAccountAge(paymentAccount.getPaymentAccountPayload()) : 0L;
|
||||
addLabelTextField(gridPane, ++gridRow, Res.get("payment.limitations"), Res.get("payment.maxPeriodAndLimit",
|
||||
getTimeText(hours),
|
||||
formatter.formatCoinWithCode(Coin.valueOf(accountAgeWitnessService.getTradeLimit(paymentAccount, tradeCurrency.getCode()))),
|
||||
formatter.formatCoinWithCode(Coin.valueOf(accountAgeWitnessService.getMyTradeLimit(paymentAccount, tradeCurrency.getCode()))),
|
||||
formatter.formatAccountAge(accountAge)));
|
||||
|
||||
if (isAddAccountScreen) {
|
||||
|
@ -165,7 +165,7 @@ public abstract class PaymentMethodForm {
|
|||
try {
|
||||
// test if input is hex
|
||||
Utilities.decodeFromHex(newValue);
|
||||
|
||||
|
||||
paymentAccount.setSaltAsHex(newValue);
|
||||
} catch (Throwable t) {
|
||||
new Popup().warning(Res.get("payment.error.noHexSalt")).show();
|
||||
|
|
|
@ -1199,12 +1199,12 @@ public class MainViewModel implements ViewModel {
|
|||
user.addPaymentAccount(okPayAccount);
|
||||
|
||||
if (p2PService.isBootstrapped()) {
|
||||
accountAgeWitnessService.publishAccountAgeWitness(okPayAccount.getPaymentAccountPayload());
|
||||
accountAgeWitnessService.publishMyAccountAgeWitness(okPayAccount.getPaymentAccountPayload());
|
||||
} else {
|
||||
p2PService.addP2PServiceListener(new BootstrapListener() {
|
||||
@Override
|
||||
public void onBootstrapComplete() {
|
||||
accountAgeWitnessService.publishAccountAgeWitness(okPayAccount.getPaymentAccountPayload());
|
||||
accountAgeWitnessService.publishMyAccountAgeWitness(okPayAccount.getPaymentAccountPayload());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class AltCoinAccountsDataModel extends ActivatableDataModel {
|
|||
OpenOfferManager openOfferManager,
|
||||
TradeManager tradeManager,
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
Stage stage,
|
||||
Stage stage,
|
||||
PersistenceProtoResolver persistenceProtoResolver) {
|
||||
this.user = user;
|
||||
this.preferences = preferences;
|
||||
|
@ -115,7 +115,7 @@ class AltCoinAccountsDataModel extends ActivatableDataModel {
|
|||
});
|
||||
}
|
||||
|
||||
accountAgeWitnessService.publishAccountAgeWitness(paymentAccount.getPaymentAccountPayload());
|
||||
accountAgeWitnessService.publishMyAccountAgeWitness(paymentAccount.getPaymentAccountPayload());
|
||||
}
|
||||
|
||||
public boolean onDeleteAccount(PaymentAccount paymentAccount) {
|
||||
|
|
|
@ -115,8 +115,8 @@ class FiatAccountsDataModel extends ActivatableDataModel {
|
|||
preferences.addCryptoCurrency((CryptoCurrency) tradeCurrency);
|
||||
});
|
||||
}
|
||||
|
||||
accountAgeWitnessService.publishAccountAgeWitness(paymentAccount.getPaymentAccountPayload());
|
||||
|
||||
accountAgeWitnessService.publishMyAccountAgeWitness(paymentAccount.getPaymentAccountPayload());
|
||||
}
|
||||
|
||||
public boolean onDeleteAccount(PaymentAccount paymentAccount) {
|
||||
|
|
|
@ -180,7 +180,7 @@ public class LockedView extends ActivatableView<VBox, Void> {
|
|||
} else if (openOfferManager.getOpenOfferById(offerId).isPresent()) {
|
||||
return Optional.of(openOfferManager.getOpenOfferById(offerId).get());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
return Optional.<Tradable>empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ public class ReservedView extends ActivatableView<VBox, Void> {
|
|||
} else if (openOfferManager.getOpenOfferById(offerId).isPresent()) {
|
||||
return Optional.of(openOfferManager.getOpenOfferById(offerId).get());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
return Optional.<Tradable>empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -401,7 +401,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
|
|||
} else if (failedTradesManager.getTradeById(offerId).isPresent()) {
|
||||
return Optional.of(failedTradesManager.getTradeById(offerId).get());
|
||||
} else {
|
||||
return Optional.empty();
|
||||
return Optional.<Tradable>empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -347,8 +347,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
HashMap<String, String> extraDataMap = new HashMap<>();
|
||||
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
final String hashOfPaymentAccountAsHex = accountAgeWitnessService.getWitnessHashAsHex(paymentAccount.getPaymentAccountPayload());
|
||||
extraDataMap.put(OfferPayload.ACCOUNT_AGE_WITNESS_HASH, hashOfPaymentAccountAsHex);
|
||||
final String myWitnessHashAsHex = accountAgeWitnessService.getMyWitnessHashAsHex(paymentAccount.getPaymentAccountPayload());
|
||||
extraDataMap.put(OfferPayload.ACCOUNT_AGE_WITNESS_HASH, myWitnessHashAsHex);
|
||||
}
|
||||
|
||||
Coin buyerSecurityDepositAsCoin = buyerSecurityDeposit.get();
|
||||
|
@ -553,7 +553,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
|
||||
long getMaxTradeLimit() {
|
||||
if (paymentAccount != null)
|
||||
return accountAgeWitnessService.getTradeLimit(paymentAccount, tradeCurrencyCode.get());
|
||||
return accountAgeWitnessService.getMyTradeLimit(paymentAccount, tradeCurrencyCode.get());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -401,10 +401,10 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||
} else if (isInsufficientTradeLimit) {
|
||||
final Optional<PaymentAccount> account = model.getMostMaturePaymentAccountForOffer(offer);
|
||||
if (account.isPresent()) {
|
||||
final long tradeLimit = model.accountAgeWitnessService.getTradeLimit(account.get(), offer.getCurrencyCode());
|
||||
final long tradeLimit = model.accountAgeWitnessService.getMyTradeLimit(account.get(), offer.getCurrencyCode());
|
||||
new Popup<>()
|
||||
.warning(Res.get("offerbook.warning.tradeLimitNotMatching",
|
||||
formatter.formatAccountAge(model.accountAgeWitnessService.getAccountAge(offer)),
|
||||
formatter.formatAccountAge(model.accountAgeWitnessService.getPeersAccountAge(offer)),
|
||||
formatter.formatCoinWithCode(Coin.valueOf(tradeLimit)),
|
||||
formatter.formatCoinWithCode(offer.getMinAmount())))
|
||||
.show();
|
||||
|
|
|
@ -464,7 +464,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
|||
|
||||
boolean isInsufficientTradeLimit(Offer offer) {
|
||||
Optional<PaymentAccount> accountOptional = getMostMaturePaymentAccountForOffer(offer);
|
||||
final long myTradeLimit = accountOptional.isPresent() ? accountAgeWitnessService.getTradeLimit(accountOptional.get(), offer.getCurrencyCode()) : 0L;
|
||||
final long myTradeLimit = accountOptional.isPresent() ? accountAgeWitnessService.getMyTradeLimit(accountOptional.get(), offer.getCurrencyCode()) : 0L;
|
||||
final long offerMinAmount = offer.getMinAmount().value;
|
||||
log.debug("isInsufficientTradeLimit accountOptional={}, myTradeLimit={}, offerMinAmount={}, ",
|
||||
accountOptional.isPresent() ? accountOptional.get().getAccountName() : "null",
|
||||
|
|
|
@ -362,7 +362,7 @@ class TakeOfferDataModel extends ActivatableDataModel {
|
|||
|
||||
long getMaxTradeLimit() {
|
||||
if (paymentAccount != null)
|
||||
return accountAgeWitnessService.getTradeLimit(paymentAccount, getCurrencyCode());
|
||||
return accountAgeWitnessService.getMyTradeLimit(paymentAccount, getCurrencyCode());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -119,8 +119,8 @@ public abstract class Overlay<T extends Overlay> {
|
|||
protected Pane owner;
|
||||
protected GridPane gridPane;
|
||||
protected Button closeButton;
|
||||
protected Optional<Runnable> closeHandlerOptional = Optional.empty();
|
||||
protected Optional<Runnable> actionHandlerOptional = Optional.empty();
|
||||
protected Optional<Runnable> closeHandlerOptional = Optional.<Runnable>empty();
|
||||
protected Optional<Runnable> actionHandlerOptional = Optional.<Runnable>empty();
|
||||
protected Stage stage;
|
||||
protected boolean showReportErrorButtons;
|
||||
protected Label messageLabel;
|
||||
|
|
|
@ -66,7 +66,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
|||
private final BtcWalletService walletService;
|
||||
private final TradeWalletService tradeWalletService;
|
||||
private Dispute dispute;
|
||||
private Optional<Runnable> finalizeDisputeHandlerOptional = Optional.empty();
|
||||
private Optional<Runnable> finalizeDisputeHandlerOptional = Optional.<Runnable>empty();
|
||||
private ToggleGroup tradeAmountToggleGroup, reasonToggleGroup;
|
||||
private DisputeResult disputeResult;
|
||||
private RadioButton buyerGetsTradeAmountRadioButton, sellerGetsTradeAmountRadioButton,
|
||||
|
|
|
@ -65,8 +65,8 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
|||
private Offer offer;
|
||||
private Coin tradeAmount;
|
||||
private Price tradePrice;
|
||||
private Optional<Runnable> placeOfferHandlerOptional = Optional.empty();
|
||||
private Optional<Runnable> takeOfferHandlerOptional = Optional.empty();
|
||||
private Optional<Runnable> placeOfferHandlerOptional = Optional.<Runnable>empty();
|
||||
private Optional<Runnable> takeOfferHandlerOptional = Optional.<Runnable>empty();
|
||||
private BusyAnimation busyAnimation;
|
||||
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ public class BisqInstaller {
|
|||
try {
|
||||
return Optional.of(downloadFiles(fileDescriptors, Utilities.getDownloadOfHomeDir()));
|
||||
} catch (IOException exception) {
|
||||
return Optional.empty();
|
||||
return Optional.<DownloadTask>empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ public class SellerStep3View extends TradeStepView {
|
|||
TitledGroupBg titledGroupBg = addTitledGroupBg(gridPane, ++gridRow, 3, Res.get("portfolio.pending.step3_seller.confirmPaymentReceipt"), Layout.GROUP_DISTANCE);
|
||||
|
||||
TextFieldWithCopyIcon field = addLabelTextFieldWithCopyIcon(gridPane, gridRow, Res.get("portfolio.pending.step3_seller.amountToReceive"),
|
||||
model.getFiatVolume(), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
model.getFiatVolume(), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
field.setCopyWithoutCurrencyPostFix(true);
|
||||
|
||||
String myPaymentDetails = "";
|
||||
|
@ -219,8 +219,8 @@ public class SellerStep3View extends TradeStepView {
|
|||
protected String getWarningText() {
|
||||
setWarningHeadline();
|
||||
String substitute = model.isBlockChainMethod() ?
|
||||
Res.get("portfolio.pending.step3_seller.warn.part1a", model.dataModel.getCurrencyCode()) :
|
||||
Res.get("portfolio.pending.step3_seller.warn.part1b");
|
||||
Res.get("portfolio.pending.step3_seller.warn.part1a", model.dataModel.getCurrencyCode()) :
|
||||
Res.get("portfolio.pending.step3_seller.warn.part1b");
|
||||
return Res.get("portfolio.pending.step3_seller.warn.part2", substitute, model.getDateForOpenDispute());
|
||||
|
||||
|
||||
|
@ -266,13 +266,13 @@ public class SellerStep3View extends TradeStepView {
|
|||
}
|
||||
message += Res.get("portfolio.pending.step3_seller.onPaymentReceived.note");
|
||||
new Popup<>()
|
||||
.headLine(Res.get("portfolio.pending.step3_seller.onPaymentReceived.confirm.headline"))
|
||||
.confirmation(message)
|
||||
.width(700)
|
||||
.actionButtonText(Res.get("portfolio.pending.step3_seller.onPaymentReceived.confirm.yes"))
|
||||
.onAction(this::confirmPaymentReceived)
|
||||
.closeButtonText(Res.get("shared.cancel"))
|
||||
.show();
|
||||
.headLine(Res.get("portfolio.pending.step3_seller.onPaymentReceived.confirm.headline"))
|
||||
.confirmation(message)
|
||||
.width(700)
|
||||
.actionButtonText(Res.get("portfolio.pending.step3_seller.onPaymentReceived.confirm.yes"))
|
||||
.onAction(this::confirmPaymentReceived)
|
||||
.closeButtonText(Res.get("shared.cancel"))
|
||||
.show();
|
||||
} else {
|
||||
confirmPaymentReceived();
|
||||
}
|
||||
|
@ -316,8 +316,8 @@ public class SellerStep3View extends TradeStepView {
|
|||
if (!DevEnv.DEV_MODE && DontShowAgainLookup.showAgain(key)) {
|
||||
DontShowAgainLookup.dontShowAgain(key, true);
|
||||
new Popup<>().headLine(Res.get("popup.attention.forTradeWithId", id))
|
||||
.attention(message)
|
||||
.show();
|
||||
.attention(message)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,9 +350,9 @@ public class SellerStep3View extends TradeStepView {
|
|||
else if (paymentAccountPayload instanceof SepaAccountPayload)
|
||||
return Optional.of(((SepaAccountPayload) paymentAccountPayload).getHolderName());
|
||||
else
|
||||
return Optional.empty();
|
||||
return Optional.<String>empty();
|
||||
} else {
|
||||
return Optional.empty();
|
||||
return Optional.<String>empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ public class Connection implements MessageListener {
|
|||
private OutputStream protoOutputStream;
|
||||
|
||||
// mutable data, set from other threads but not changed internally.
|
||||
private Optional<NodeAddress> peersNodeAddressOptional = Optional.empty();
|
||||
private Optional<NodeAddress> peersNodeAddressOptional = Optional.<NodeAddress>empty();
|
||||
private volatile boolean stopped;
|
||||
private PeerType peerType;
|
||||
private final ObjectProperty<NodeAddress> peersNodeAddressProperty = new SimpleObjectProperty<>();
|
||||
|
|
|
@ -56,7 +56,7 @@ public class RequestDataManager implements MessageListener, ConnectionListener,
|
|||
|
||||
private final Map<NodeAddress, RequestDataHandler> handlerMap = new HashMap<>();
|
||||
private final Map<String, GetDataRequestHandler> getDataRequestHandlers = new HashMap<>();
|
||||
private Optional<NodeAddress> nodeAddressOfPreliminaryDataRequest = Optional.empty();
|
||||
private Optional<NodeAddress> nodeAddressOfPreliminaryDataRequest = Optional.<NodeAddress>empty();
|
||||
private Timer retryTimer;
|
||||
private boolean dataUpdateRequested;
|
||||
private boolean stopped;
|
||||
|
|
Loading…
Add table
Reference in a new issue