- Add support for multiple pubKeys

- Add more validation
- Add SignerPubKeyAsHex to filter
- Refactor add/remove filter code
This commit is contained in:
chimp1984 2020-08-31 12:33:45 -05:00
parent e2de5221bf
commit cc20a3b6c7
No known key found for this signature in database
GPG key ID: 9801B4EC591F90E3
6 changed files with 159 additions and 71 deletions

View file

@ -60,7 +60,10 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
// created by cloning the object with a non-null sig. // created by cloning the object with a non-null sig.
@Nullable @Nullable
private final String signatureAsBase64; private final String signatureAsBase64;
// The pub key used for the data protection in teh p2p storage // The pub EC key from the dev who has signed and published the filter (different to ownerPubKeyBytes)
private final String signerPubKeyAsHex;
// The pub key used for the data protection in the p2p storage
private final byte[] ownerPubKeyBytes; private final byte[] ownerPubKeyBytes;
private final boolean disableDao; private final boolean disableDao;
private final String disableDaoBelowVersion; private final String disableDaoBelowVersion;
@ -104,7 +107,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
filter.getOwnerPubKeyBytes(), filter.getOwnerPubKeyBytes(),
filter.getCreationDate(), filter.getCreationDate(),
filter.getExtraDataMap(), filter.getExtraDataMap(),
signatureAsBase64); signatureAsBase64,
filter.getSignerPubKeyAsHex());
} }
// Used for signature verification as we created the sig without the signatureAsBase64 field we set it to null again // Used for signature verification as we created the sig without the signatureAsBase64 field we set it to null again
@ -129,7 +133,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
filter.getOwnerPubKeyBytes(), filter.getOwnerPubKeyBytes(),
filter.getCreationDate(), filter.getCreationDate(),
filter.getExtraDataMap(), filter.getExtraDataMap(),
null); null,
filter.getSignerPubKeyAsHex());
} }
public Filter(List<String> bannedOfferIds, public Filter(List<String> bannedOfferIds,
@ -149,7 +154,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
List<String> refundAgents, List<String> refundAgents,
List<String> bannedSignerPubKeys, List<String> bannedSignerPubKeys,
List<String> btcFeeReceiverAddresses, List<String> btcFeeReceiverAddresses,
PublicKey ownerPubKey) { PublicKey ownerPubKey,
String signerPubKeyAsHex) {
this(bannedOfferIds, this(bannedOfferIds,
bannedNodeAddress, bannedNodeAddress,
bannedPaymentAccounts, bannedPaymentAccounts,
@ -170,7 +176,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
Sig.getPublicKeyBytes(ownerPubKey), Sig.getPublicKeyBytes(ownerPubKey),
System.currentTimeMillis(), System.currentTimeMillis(),
null, null,
null); null,
signerPubKeyAsHex);
} }
@ -199,7 +206,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
byte[] ownerPubKeyBytes, byte[] ownerPubKeyBytes,
long creationDate, long creationDate,
@Nullable Map<String, String> extraDataMap, @Nullable Map<String, String> extraDataMap,
@Nullable String signatureAsBase64) { @Nullable String signatureAsBase64,
String signerPubKeyAsHex) {
this.bannedOfferIds = bannedOfferIds; this.bannedOfferIds = bannedOfferIds;
this.bannedNodeAddress = bannedNodeAddress; this.bannedNodeAddress = bannedNodeAddress;
this.bannedPaymentAccounts = bannedPaymentAccounts; this.bannedPaymentAccounts = bannedPaymentAccounts;
@ -221,6 +229,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
this.creationDate = creationDate; this.creationDate = creationDate;
this.extraDataMap = ExtraDataMapValidator.getValidatedExtraDataMap(extraDataMap); this.extraDataMap = ExtraDataMapValidator.getValidatedExtraDataMap(extraDataMap);
this.signatureAsBase64 = signatureAsBase64; this.signatureAsBase64 = signatureAsBase64;
this.signerPubKeyAsHex = signerPubKeyAsHex;
// ownerPubKeyBytes can be null when called from tests // ownerPubKeyBytes can be null when called from tests
if (ownerPubKeyBytes != null) { if (ownerPubKeyBytes != null) {
@ -254,6 +263,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
.addAllBannedSignerPubKeys(bannedSignerPubKeys) .addAllBannedSignerPubKeys(bannedSignerPubKeys)
.addAllBtcFeeReceiverAddresses(btcFeeReceiverAddresses) .addAllBtcFeeReceiverAddresses(btcFeeReceiverAddresses)
.setOwnerPubKeyBytes(ByteString.copyFrom(ownerPubKeyBytes)) .setOwnerPubKeyBytes(ByteString.copyFrom(ownerPubKeyBytes))
.setSignerPubKeyAsHex(signerPubKeyAsHex)
.setCreationDate(creationDate); .setCreationDate(creationDate);
Optional.ofNullable(signatureAsBase64).ifPresent(builder::setSignatureAsBase64); Optional.ofNullable(signatureAsBase64).ifPresent(builder::setSignatureAsBase64);
@ -288,7 +298,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
proto.getOwnerPubKeyBytes().toByteArray(), proto.getOwnerPubKeyBytes().toByteArray(),
proto.getCreationDate(), proto.getCreationDate(),
CollectionUtils.isEmpty(proto.getExtraDataMap()) ? null : proto.getExtraDataMap(), CollectionUtils.isEmpty(proto.getExtraDataMap()) ? null : proto.getExtraDataMap(),
proto.getSignatureAsBase64() proto.getSignatureAsBase64(),
proto.getSignerPubKeyAsHex()
); );
} }
@ -316,6 +327,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
",\n preventPublicBtcNetwork=" + preventPublicBtcNetwork + ",\n preventPublicBtcNetwork=" + preventPublicBtcNetwork +
",\n btcNodes=" + btcNodes + ",\n btcNodes=" + btcNodes +
",\n signatureAsBase64='" + signatureAsBase64 + '\'' + ",\n signatureAsBase64='" + signatureAsBase64 + '\'' +
",\n signerPubKeyAsHex='" + signerPubKeyAsHex + '\'' +
",\n ownerPubKeyBytes=" + Utilities.bytesAsHexString(ownerPubKeyBytes) + ",\n ownerPubKeyBytes=" + Utilities.bytesAsHexString(ownerPubKeyBytes) +
",\n disableDao=" + disableDao + ",\n disableDao=" + disableDao +
",\n disableDaoBelowVersion='" + disableDaoBelowVersion + '\'' + ",\n disableDaoBelowVersion='" + disableDaoBelowVersion + '\'' +

View file

@ -38,7 +38,6 @@ import bisq.common.crypto.KeyRing;
import org.bitcoinj.core.ECKey; import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Sha256Hash; import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Utils;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
@ -55,6 +54,7 @@ import java.nio.charset.StandardCharsets;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@ -94,8 +94,7 @@ public class FilterManager {
private final boolean ignoreDevMsg; private final boolean ignoreDevMsg;
private final ObjectProperty<Filter> filterProperty = new SimpleObjectProperty<>(); private final ObjectProperty<Filter> filterProperty = new SimpleObjectProperty<>();
private final List<Listener> listeners = new CopyOnWriteArrayList<>(); private final List<Listener> listeners = new CopyOnWriteArrayList<>();
private final String pubKeyAsHex; private final List<String> publicKeys;
private ECKey filterSigningKey; private ECKey filterSigningKey;
@ -120,9 +119,12 @@ public class FilterManager {
this.providersRepository = providersRepository; this.providersRepository = providersRepository;
this.ignoreDevMsg = ignoreDevMsg; this.ignoreDevMsg = ignoreDevMsg;
pubKeyAsHex = useDevPrivilegeKeys ? //todo test
DevEnv.DEV_PRIVILEGE_PUB_KEY : publicKeys = !useDevPrivilegeKeys ?
"022ac7b7766b0aedff82962522c2c14fb8d1961dabef6e5cfd10edc679456a32f1"; Collections.singletonList(DevEnv.DEV_PRIVILEGE_PUB_KEY) :
List.of("0358d47858acdc41910325fce266571540681ef83a0d6fedce312bef9810793a27",
"029340c3e7d4bb0f9e651b5f590b434fecb6175aeaa57145c7804ff05d210e534f");
} }
@ -139,6 +141,7 @@ public class FilterManager {
.map(ProtectedStorageEntry::getProtectedStoragePayload) .map(ProtectedStorageEntry::getProtectedStoragePayload)
.filter(protectedStoragePayload -> protectedStoragePayload instanceof Filter) .filter(protectedStoragePayload -> protectedStoragePayload instanceof Filter)
.map(protectedStoragePayload -> (Filter) protectedStoragePayload) .map(protectedStoragePayload -> (Filter) protectedStoragePayload)
.filter(this::isFilterPublicKeyInList)
.filter(this::verifySignature) .filter(this::verifySignature)
.forEach(this::onFilterAddedFromNetwork); .forEach(this::onFilterAddedFromNetwork);
@ -149,7 +152,7 @@ public class FilterManager {
.filter(protectedStorageEntry -> protectedStorageEntry.getProtectedStoragePayload() instanceof Filter) .filter(protectedStorageEntry -> protectedStorageEntry.getProtectedStoragePayload() instanceof Filter)
.forEach(protectedStorageEntry -> { .forEach(protectedStorageEntry -> {
Filter filter = (Filter) protectedStorageEntry.getProtectedStoragePayload(); Filter filter = (Filter) protectedStorageEntry.getProtectedStoragePayload();
if (verifySignature(filter)) { if (isFilterPublicKeyInList(filter) && verifySignature(filter)) {
onFilterAddedFromNetwork(filter); onFilterAddedFromNetwork(filter);
} }
}); });
@ -161,7 +164,7 @@ public class FilterManager {
.filter(protectedStorageEntry -> protectedStorageEntry.getProtectedStoragePayload() instanceof Filter) .filter(protectedStorageEntry -> protectedStorageEntry.getProtectedStoragePayload() instanceof Filter)
.forEach(protectedStorageEntry -> { .forEach(protectedStorageEntry -> {
Filter filter = (Filter) protectedStorageEntry.getProtectedStoragePayload(); Filter filter = (Filter) protectedStorageEntry.getProtectedStoragePayload();
if (verifySignature(filter)) { if (isFilterPublicKeyInList(filter) && verifySignature(filter)) {
onFilterRemovedFromNetwork(filter); onFilterRemovedFromNetwork(filter);
} }
}); });
@ -209,20 +212,24 @@ public class FilterManager {
}); });
} }
public boolean isValidDevPrivilegeKey(String privKeyString) { public boolean canAddDevFilter(String privKeyString) {
try { if (privKeyString == null || privKeyString.isEmpty()) {
ECKey filterSigningKey = toECKey(privKeyString);
return pubKeyAsHex.equals(Utils.HEX.encode(filterSigningKey.getPubKey()));
} catch (Throwable t) {
return false; return false;
} }
if (!isValidDevPrivilegeKey(privKeyString)) {
log.warn("There is no persisted dev filter to be removed.");
return false;
}
return true;
} }
public void setFilterSigningKey(String privKeyString) { public String getSignerPubKeyAsHex(String privKeyString) {
this.filterSigningKey = toECKey(privKeyString); ECKey ecKey = toECKey(privKeyString);
return getPubKeyAsHex(ecKey);
} }
public void publishFilter(Filter filterWithoutSig) { public void addDevFilter(Filter filterWithoutSig, String privKeyString) {
setFilterSigningKey(privKeyString);
String signatureAsBase64 = getSignature(filterWithoutSig); String signatureAsBase64 = getSignature(filterWithoutSig);
Filter filterWithSig = Filter.cloneWithSig(filterWithoutSig, signatureAsBase64); Filter filterWithSig = Filter.cloneWithSig(filterWithoutSig, signatureAsBase64);
user.setDevelopersFilter(filterWithSig); user.setDevelopersFilter(filterWithSig);
@ -230,8 +237,42 @@ public class FilterManager {
p2PService.addProtectedStorageEntry(filterWithSig); p2PService.addProtectedStorageEntry(filterWithSig);
} }
public boolean canRemoveDevFilter(String privKeyString) {
if (privKeyString == null || privKeyString.isEmpty()) {
return false;
}
public void removeFilter() { Filter developersFilter = getDevFilter();
if (developersFilter == null) {
log.warn("There is no persisted dev filter to be removed.");
return false;
}
if (!isPublicKeyInList(developersFilter.getSignerPubKeyAsHex())) {
log.warn("The SignerPubKey from the filter is not in our pubKey list. " +
"filterSignerPubKey={}, publicKeys={}", developersFilter.getSignerPubKeyAsHex(), publicKeys);
return false;
}
if (!isValidDevPrivilegeKey(privKeyString)) {
log.warn("There is no persisted dev filter to be removed.");
return false;
}
ECKey ecKeyFromPrivate = toECKey(privKeyString);
String pubKeyAsHex = getPubKeyAsHex(ecKeyFromPrivate);
if (!developersFilter.getSignerPubKeyAsHex().equals(pubKeyAsHex)) {
log.warn("pubKeyAsHex derived from private key does not match filterSignerPubKey. " +
"filterSignerPubKey={}, pubKeyAsHex derived from private key={}",
developersFilter.getSignerPubKeyAsHex(), pubKeyAsHex);
return false;
}
return true;
}
public void removeDevFilter(String privKeyString) {
setFilterSigningKey(privKeyString);
Filter filterWithSig = user.getDevelopersFilter(); Filter filterWithSig = user.getDevelopersFilter();
if (filterWithSig == null) { if (filterWithSig == null) {
// Should not happen as UI button is deactivated in that case // Should not happen as UI button is deactivated in that case
@ -259,10 +300,14 @@ public class FilterManager {
} }
@Nullable @Nullable
public Filter getDevelopersFilter() { public Filter getDevFilter() {
return user.getDevelopersFilter(); return user.getDevelopersFilter();
} }
public PublicKey getOwnerPubKey() {
return keyRing.getSignatureKeyPair().getPublic();
}
public boolean isCurrencyBanned(String currencyCode) { public boolean isCurrencyBanned(String currencyCode) {
return getFilter() != null && return getFilter() != null &&
getFilter().getBannedCurrencies() != null && getFilter().getBannedCurrencies() != null &&
@ -347,10 +392,6 @@ public class FilterManager {
.anyMatch(e -> e.equals(witnessSignerPubKeyAsHex)); .anyMatch(e -> e.equals(witnessSignerPubKeyAsHex));
} }
public PublicKey getOwnerPubKey() {
return keyRing.getSignatureKeyPair().getPublic();
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Private // Private
@ -423,6 +464,20 @@ public class FilterManager {
configFileEditor.clearOption(optionName); configFileEditor.clearOption(optionName);
} }
private boolean isValidDevPrivilegeKey(String privKeyString) {
try {
ECKey filterSigningKey = toECKey(privKeyString);
String pubKeyAsHex = getPubKeyAsHex(filterSigningKey);
return isPublicKeyInList(pubKeyAsHex);
} catch (Throwable t) {
return false;
}
}
private void setFilterSigningKey(String privKeyString) {
this.filterSigningKey = toECKey(privKeyString);
}
private String getSignature(Filter filterWithoutSig) { private String getSignature(Filter filterWithoutSig) {
Sha256Hash hash = getSha256Hash(filterWithoutSig); Sha256Hash hash = getSha256Hash(filterWithoutSig);
ECKey.ECDSASignature ecdsaSignature = filterSigningKey.sign(hash); ECKey.ECDSASignature ecdsaSignature = filterSigningKey.sign(hash);
@ -430,6 +485,15 @@ public class FilterManager {
return new String(Base64.encode(encodeToDER), StandardCharsets.UTF_8); return new String(Base64.encode(encodeToDER), StandardCharsets.UTF_8);
} }
private boolean isFilterPublicKeyInList(Filter filter) {
String signerPubKeyAsHex = filter.getSignerPubKeyAsHex();
if (!isPublicKeyInList(signerPubKeyAsHex)) {
log.warn("signerPubKeyAsHex from filter is not part of our pub key list. filter={}, publicKeys={}", filter, publicKeys);
return false;
}
return true;
}
private boolean verifySignature(Filter filter) { private boolean verifySignature(Filter filter) {
try { try {
Filter filterForSigVerification = Filter.cloneWithoutSig(filter); Filter filterForSigVerification = Filter.cloneWithoutSig(filter);
@ -439,7 +503,9 @@ public class FilterManager {
byte[] sigData = Base64.decode(filter.getSignatureAsBase64()); byte[] sigData = Base64.decode(filter.getSignatureAsBase64());
ECKey.ECDSASignature ecdsaSignature = ECKey.ECDSASignature.decodeFromDER(sigData); ECKey.ECDSASignature ecdsaSignature = ECKey.ECDSASignature.decodeFromDER(sigData);
ECKey ecPubKey = ECKey.fromPublicOnly(HEX.decode(pubKeyAsHex)); String signerPubKeyAsHex = filter.getSignerPubKeyAsHex();
byte[] decode = HEX.decode(signerPubKeyAsHex);
ECKey ecPubKey = ECKey.fromPublicOnly(decode);
return ecPubKey.verify(hash, ecdsaSignature); return ecPubKey.verify(hash, ecdsaSignature);
} catch (Throwable e) { } catch (Throwable e) {
log.warn("verifySignature failed. filter={}", filter); log.warn("verifySignature failed. filter={}", filter);
@ -455,4 +521,16 @@ public class FilterManager {
byte[] filterData = filter.toProtoMessage().toByteArray(); byte[] filterData = filter.toProtoMessage().toByteArray();
return Sha256Hash.of(filterData); return Sha256Hash.of(filterData);
} }
private String getPubKeyAsHex(ECKey ecKey) {
return HEX.encode(ecKey.getPubKey());
}
private boolean isPublicKeyInList(String pubKeyAsHex) {
boolean isPublicKeyInList = publicKeys.contains(pubKeyAsHex);
if (!isPublicKeyInList) {
log.warn("pubKeyAsHex is not part of our pub key list. pubKeyAsHex={}, publicKeys={}", pubKeyAsHex, publicKeys);
}
return isPublicKeyInList;
}
} }

View file

@ -60,6 +60,7 @@ public class UserPayloadModelVOTest {
null, null,
0, 0,
null, null,
null,
null)); null));
vo.setRegisteredArbitrator(ArbitratorTest.getArbitratorMock()); vo.setRegisteredArbitrator(ArbitratorTest.getArbitratorMock());

View file

@ -119,6 +119,7 @@ public class FeeReceiverSelectorTest {
null, null,
0, 0,
null, null,
null,
null); null);
} }
} }

View file

@ -79,7 +79,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
if (headLine == null) if (headLine == null)
headLine = Res.get("filterWindow.headline"); headLine = Res.get("filterWindow.headline");
width = 968; width = 1000;
createGridPane(); createGridPane();
@ -87,7 +87,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
scrollPane.setContent(gridPane); scrollPane.setContent(gridPane);
scrollPane.setFitToWidth(true); scrollPane.setFitToWidth(true);
scrollPane.setFitToHeight(true); scrollPane.setFitToHeight(true);
scrollPane.setMaxHeight(1000); scrollPane.setMaxHeight(700);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
addHeadLine(); addHeadLine();
@ -139,7 +139,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
InputTextField disableDaoBelowVersionInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.disableDaoBelowVersion")); InputTextField disableDaoBelowVersionInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.disableDaoBelowVersion"));
InputTextField disableTradeBelowVersionInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.disableTradeBelowVersion")); InputTextField disableTradeBelowVersionInputTextField = addInputTextField(gridPane, ++rowIndex, Res.get("filterWindow.disableTradeBelowVersion"));
final Filter filter = filterManager.getDevelopersFilter(); Filter filter = filterManager.getDevFilter();
if (filter != null) { if (filter != null) {
setupFieldFromList(offerIdsInputTextField, filter.getBannedOfferIds()); setupFieldFromList(offerIdsInputTextField, filter.getBannedOfferIds());
setupFieldFromList(nodesInputTextField, filter.getBannedNodeAddress()); setupFieldFromList(nodesInputTextField, filter.getBannedNodeAddress());
@ -162,55 +162,50 @@ public class FilterWindow extends Overlay<FilterWindow> {
} }
Button removeFilterMessageButton = new AutoTooltipButton(Res.get("filterWindow.remove")); Button removeFilterMessageButton = new AutoTooltipButton(Res.get("filterWindow.remove"));
removeFilterMessageButton.setDisable(filterManager.getDevelopersFilter() == null); removeFilterMessageButton.setDisable(filterManager.getDevFilter() == null);
Button sendButton = new AutoTooltipButton(Res.get("filterWindow.add")); Button sendButton = new AutoTooltipButton(Res.get("filterWindow.add"));
String privKeyString = keyInputTextField.getText();
sendButton.setOnAction(e -> { sendButton.setOnAction(e -> {
if (privKeyString.isEmpty()) { String privKeyString = keyInputTextField.getText();
return; if (filterManager.canAddDevFilter(privKeyString)) {
} String signerPubKeyAsHex = filterManager.getSignerPubKeyAsHex(privKeyString);
Filter newFilter = new Filter( Filter newFilter = new Filter(
readAsList(offerIdsInputTextField), readAsList(offerIdsInputTextField),
readAsList(nodesInputTextField), readAsList(nodesInputTextField),
readAsPaymentAccountFiltersList(paymentAccountFilterInputTextField), readAsPaymentAccountFiltersList(paymentAccountFilterInputTextField),
readAsList(bannedCurrenciesInputTextField), readAsList(bannedCurrenciesInputTextField),
readAsList(bannedPaymentMethodsInputTextField), readAsList(bannedPaymentMethodsInputTextField),
readAsList(arbitratorsInputTextField), readAsList(arbitratorsInputTextField),
readAsList(seedNodesInputTextField), readAsList(seedNodesInputTextField),
readAsList(priceRelayNodesInputTextField), readAsList(priceRelayNodesInputTextField),
preventPublicBtcNetworkCheckBox.isSelected(), preventPublicBtcNetworkCheckBox.isSelected(),
readAsList(btcNodesInputTextField), readAsList(btcNodesInputTextField),
disableDaoCheckBox.isSelected(), disableDaoCheckBox.isSelected(),
disableDaoBelowVersionInputTextField.getText(), disableDaoBelowVersionInputTextField.getText(),
disableTradeBelowVersionInputTextField.getText(), disableTradeBelowVersionInputTextField.getText(),
readAsList(mediatorsInputTextField), readAsList(mediatorsInputTextField),
readAsList(refundAgentsInputTextField), readAsList(refundAgentsInputTextField),
readAsList(bannedSignerPubKeysInputTextField), readAsList(bannedSignerPubKeysInputTextField),
readAsList(btcFeeReceiverAddressesInputTextField), readAsList(btcFeeReceiverAddressesInputTextField),
filterManager.getOwnerPubKey() filterManager.getOwnerPubKey(),
); signerPubKeyAsHex
if (filterManager.isValidDevPrivilegeKey(privKeyString)) { );
filterManager.setFilterSigningKey(privKeyString);
filterManager.publishFilter(newFilter); filterManager.addDevFilter(newFilter, privKeyString);
removeFilterMessageButton.setDisable(filterManager.getDevelopersFilter() == null); removeFilterMessageButton.setDisable(filterManager.getDevFilter() == null);
hide(); hide();
} else { } else {
new Popup().warning(Res.get("shared.invalidKey")).width(300).onClose(this::blurAgain).show(); new Popup().warning(Res.get("shared.invalidKey")).onClose(this::blurAgain).show();
} }
}); });
removeFilterMessageButton.setOnAction(e -> { removeFilterMessageButton.setOnAction(e -> {
if (privKeyString.isEmpty()) { String privKeyString = keyInputTextField.getText();
return; if (filterManager.canRemoveDevFilter(privKeyString)) {
} filterManager.removeDevFilter(privKeyString);
if (filterManager.isValidDevPrivilegeKey(privKeyString)) {
filterManager.setFilterSigningKey(privKeyString);
filterManager.removeFilter();
hide(); hide();
} else { } else {
new Popup().warning(Res.get("shared.invalidKey")).width(300).onClose(this::blurAgain).show(); new Popup().warning(Res.get("shared.invalidKey")).onClose(this::blurAgain).show();
} }
}); });

View file

@ -639,6 +639,7 @@ message Filter {
repeated string bannedSignerPubKeys = 19; repeated string bannedSignerPubKeys = 19;
repeated string btc_fee_receiver_addresses = 20; repeated string btc_fee_receiver_addresses = 20;
int64 creation_date = 21; int64 creation_date = 21;
string signer_pub_key_as_hex = 22;
} }
// not used anymore from v0.6 on. But leave it for receiving TradeStatistics objects from older // not used anymore from v0.6 on. But leave it for receiving TradeStatistics objects from older