mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 01:41:11 +01:00
Add export feature for signed account age witness
This commit is contained in:
parent
2b6dd187c6
commit
ef81bde7f2
@ -381,6 +381,15 @@ public class AccountAgeWitnessService {
|
||||
}
|
||||
}
|
||||
|
||||
public long getWitnessSignDate(AccountAgeWitness accountAgeWitness) {
|
||||
List<Long> dates = signedWitnessService.getVerifiedWitnessDateList(accountAgeWitness);
|
||||
if (dates.isEmpty()) {
|
||||
return -1L;
|
||||
} else {
|
||||
return dates.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Return -1 if not signed
|
||||
public long getWitnessSignAge(Offer offer, Date now) {
|
||||
return findWitness(offer)
|
||||
@ -951,4 +960,8 @@ public class AccountAgeWitnessService {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFilteredWitness(AccountAgeWitness accountAgeWitness) {
|
||||
return signedWitnessService.isFilteredWitness(accountAgeWitness);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import bisq.core.util.JsonUtil;
|
||||
|
||||
import bisq.network.p2p.storage.P2PDataStorage;
|
||||
|
||||
import bisq.common.app.DevEnv;
|
||||
import bisq.common.crypto.CryptoException;
|
||||
import bisq.common.crypto.Hash;
|
||||
import bisq.common.crypto.KeyRing;
|
||||
@ -41,11 +42,13 @@ import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@Slf4j
|
||||
@ -197,13 +200,37 @@ public class AccountAgeWitnessUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<String> exportAccount(AccountAgeWitnessService accountAgeWitnessService,
|
||||
PaymentAccount account,
|
||||
KeyRing keyRing,
|
||||
String profileId) {
|
||||
static class SignedWitnessDto {
|
||||
private final String profileId;
|
||||
private final String hashAsHex;
|
||||
private final long accountAgeWitnessDate;
|
||||
private final long witnessSignDate;
|
||||
private final String pubKeyBase64;
|
||||
private final String signatureBase64;
|
||||
|
||||
public SignedWitnessDto(String profileId,
|
||||
String hashAsHex,
|
||||
long accountAgeWitnessDate,
|
||||
long witnessSignDate,
|
||||
String pubKeyBase64,
|
||||
String signatureBase64) {
|
||||
this.profileId = profileId;
|
||||
this.hashAsHex = hashAsHex;
|
||||
this.accountAgeWitnessDate = accountAgeWitnessDate;
|
||||
this.witnessSignDate = witnessSignDate;
|
||||
this.pubKeyBase64 = pubKeyBase64;
|
||||
this.signatureBase64 = signatureBase64;
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<String> signAccountAgeAndBisq2ProfileId(AccountAgeWitnessService accountAgeWitnessService,
|
||||
PaymentAccount account,
|
||||
KeyRing keyRing,
|
||||
String profileId) {
|
||||
return accountAgeWitnessService.findWitness(account.getPaymentAccountPayload(), keyRing.getPubKeyRing())
|
||||
.map(accountAgeWitness -> {
|
||||
try {
|
||||
checkArgument(!accountAgeWitnessService.isFilteredWitness(accountAgeWitness), "Invalid account age witness");
|
||||
String hashAsHex = Hex.encode(accountAgeWitness.getHash());
|
||||
String message = profileId + hashAsHex + accountAgeWitness.getDate();
|
||||
KeyPair signatureKeyPair = keyRing.getSignatureKeyPair();
|
||||
@ -220,4 +247,36 @@ public class AccountAgeWitnessUtils {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Optional<String> signSignedWitnessAndBisq2ProfileId(AccountAgeWitnessService accountAgeWitnessService,
|
||||
PaymentAccount account,
|
||||
KeyRing keyRing,
|
||||
String profileId) {
|
||||
return accountAgeWitnessService.findWitness(account.getPaymentAccountPayload(), keyRing.getPubKeyRing())
|
||||
.map(accountAgeWitness -> {
|
||||
try {
|
||||
checkArgument(!accountAgeWitnessService.isFilteredWitness(accountAgeWitness), "Invalid account age witness");
|
||||
long witnessSignDate = accountAgeWitnessService.getWitnessSignDate(accountAgeWitness);
|
||||
long ageInDays = (System.currentTimeMillis() - witnessSignDate) / TimeUnit.DAYS.toMillis(1);
|
||||
if (!DevEnv.isDevMode()) {
|
||||
checkArgument(witnessSignDate > 0, "Account is not signed yet");
|
||||
checkArgument(ageInDays > 60, "Account must have been signed at least 61 days ago");
|
||||
}
|
||||
String hashAsHex = Hex.encode(accountAgeWitness.getHash());
|
||||
String message = profileId + hashAsHex + accountAgeWitness.getDate() + witnessSignDate;
|
||||
KeyPair signatureKeyPair = keyRing.getSignatureKeyPair();
|
||||
String signatureBase64 = Sig.sign(signatureKeyPair.getPrivate(), message);
|
||||
String pubKeyBase64 = Base64.getEncoder().encodeToString(Sig.getPublicKeyBytes(signatureKeyPair.getPublic()));
|
||||
SignedWitnessDto dto = new SignedWitnessDto(profileId,
|
||||
hashAsHex,
|
||||
accountAgeWitness.getDate(),
|
||||
witnessSignDate,
|
||||
pubKeyBase64,
|
||||
signatureBase64);
|
||||
return JsonUtil.objectToJson(dto);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1819,8 +1819,12 @@ If you do not understand these requirements, do not trade L-BTC on Bisq.
|
||||
|
||||
account.fiat.yourFiatAccounts=Your national currency accounts
|
||||
account.fiat.exportAccountAge=Export account age for Bisq 2
|
||||
account.fiat.exportAccountAge.popup=Your account age and Bisq 2 profile ID got signed and the data is copied \
|
||||
to the clipboard.\n\
|
||||
account.fiat.exportAccountAge.popup=Your 'account age' and Bisq 2 profile ID got signed and the data is copied \
|
||||
to the clipboard.\n\n\This is the data in json format:\n\n\{0}\n\n\
|
||||
Go back to Bisq 2 and follow the instructions there.
|
||||
account.fiat.signedWitness=Export signed witness for Bisq 2
|
||||
account.fiat.signedWitness.popup=Your 'signed account age witness' and Bisq 2 profile ID got signed and the data is copied \
|
||||
to the clipboard.\n\n\This is the data in json format:\n\n\{0}\n\n\
|
||||
Go back to Bisq 2 and follow the instructions there.
|
||||
account.backup.title=Backup wallet
|
||||
account.backup.location=Backup location
|
||||
|
@ -510,35 +510,65 @@ public class FiatAccountsView extends PaymentAccountsView<GridPane, FiatAccounts
|
||||
GridPane.setRowSpan(accountTitledGroupBg, paymentMethodForm.getRowSpan());
|
||||
|
||||
Button exportAccountAgeButton = new AutoTooltipButton(Res.get("account.fiat.exportAccountAge"));
|
||||
exportAccountAgeButton.setOnAction(event -> onExportAccountAge(paymentMethodForm.getPaymentAccount()));
|
||||
exportAccountAgeButton.setOnAction(event -> onExportAccountAgeForBisq2(paymentMethodForm.getPaymentAccount()));
|
||||
exportAccountAgeButton.setMaxWidth(Double.MAX_VALUE);
|
||||
HBox.setHgrow(exportAccountAgeButton, Priority.ALWAYS);
|
||||
|
||||
Button signedWitnessButton = new AutoTooltipButton(Res.get("account.fiat.signedWitness"));
|
||||
signedWitnessButton.setOnAction(event -> onExportSignedWitnessForBisq2(paymentMethodForm.getPaymentAccount()));
|
||||
signedWitnessButton.setMaxWidth(Double.MAX_VALUE);
|
||||
HBox.setHgrow(signedWitnessButton, Priority.ALWAYS);
|
||||
|
||||
|
||||
HBox hBox = (HBox) cancelButton.getParent();
|
||||
hBox.getChildren().add(exportAccountAgeButton);
|
||||
hBox.getChildren().addAll(exportAccountAgeButton, signedWitnessButton);
|
||||
|
||||
model.onSelectAccount(current);
|
||||
}
|
||||
}
|
||||
|
||||
private void onExportAccountAge(PaymentAccount paymentAccount) {
|
||||
private void onExportAccountAgeForBisq2(PaymentAccount paymentAccount) {
|
||||
String prefix = "BISQ2_ACCOUNT_AGE:";
|
||||
try {
|
||||
String profileId = getProfileIdFromClipBoard(prefix);
|
||||
AccountAgeWitnessUtils.signAccountAgeAndBisq2ProfileId(accountAgeWitnessService, paymentAccount, keyRing, profileId)
|
||||
.ifPresent(json -> {
|
||||
Utilities.copyToClipboard(prefix + json);
|
||||
new Popup().information(Res.get("account.fiat.exportAccountAge.popup", json))
|
||||
.width(900).show();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
String error = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
|
||||
new Popup().warning(error).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void onExportSignedWitnessForBisq2(PaymentAccount paymentAccount) {
|
||||
String prefix = "BISQ2_SIGNED_WITNESS:";
|
||||
try {
|
||||
String profileId = getProfileIdFromClipBoard(prefix);
|
||||
AccountAgeWitnessUtils.signSignedWitnessAndBisq2ProfileId(accountAgeWitnessService, paymentAccount, keyRing, profileId)
|
||||
.ifPresent(json -> {
|
||||
Utilities.copyToClipboard(prefix + json);
|
||||
new Popup().information(Res.get("account.fiat.signedWitness.popup", json))
|
||||
.width(900).show();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
String error = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
|
||||
new Popup().warning(error).show();
|
||||
}
|
||||
}
|
||||
|
||||
private String getProfileIdFromClipBoard(String prefix) {
|
||||
String clipboardText = Clipboard.getSystemClipboard().getString();
|
||||
String prefix = "BISQ2_ACCOUNT_AGE_REQUEST:";
|
||||
if (clipboardText != null && clipboardText.startsWith(prefix)) {
|
||||
String profileId = clipboardText.replace(prefix, "");
|
||||
if (profileId.length() == 40) {
|
||||
try {
|
||||
Hex.decode(profileId);
|
||||
AccountAgeWitnessUtils.exportAccount(accountAgeWitnessService, paymentAccount, keyRing, profileId)
|
||||
.ifPresent(json -> {
|
||||
Utilities.copyToClipboard(json);
|
||||
new Popup().information(Res.get("account.fiat.exportAccountAge.popup")).show();
|
||||
});
|
||||
return;
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
Hex.decode(profileId);
|
||||
return profileId;
|
||||
}
|
||||
}
|
||||
log.warn("Clipboard text not in expected format.");
|
||||
throw new RuntimeException("Clipboard text not in expected format. " + clipboardText);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user