Add PoW version(-list) fields to ProofOfWork & Filter

Add a numeric version field to the 'ProofOfWork' protobuf object, along
with a list of allowed version numbers, 'enabled_pow_versions', to the
filter. The versions are taken to be in order of preference from most to
least preferred when creating a PoW, with an empty list signifying use
of the default algorithm only (that is, version 0: Hashcash).

An explicit list is used instead of an upper & lower version bound, in
case a new PoW algorithm (or changed algorithm params) turns out to
provide worse resistance than an earlier version.

(The fields are unused for now, to be enabled in a later commit.)
This commit is contained in:
Steven Barclay 2021-11-24 15:07:42 +00:00 committed by Christoph Atteneder
parent 998a0e0aaf
commit c3e5dfd19e
No known key found for this signature in database
GPG Key ID: CD5DC1C529CDFD3B
8 changed files with 49 additions and 28 deletions

View File

@ -98,7 +98,7 @@ public class HashCashService {
result = toSha256Hash(payload, challenge, ++counter);
}
while (!testDifficulty.test(result, difficulty));
ProofOfWork proofOfWork = new ProofOfWork(payload, counter, challenge, difficulty, System.currentTimeMillis() - ts);
ProofOfWork proofOfWork = new ProofOfWork(payload, counter, challenge, difficulty, System.currentTimeMillis() - ts, 0);
log.info("Completed minting proofOfWork: {}", proofOfWork);
return proofOfWork;
});

View File

@ -38,51 +38,55 @@ public final class ProofOfWork implements NetworkPayload {
private final byte[] difficulty;
@Getter
private final long duration;
@Getter
private final int version;
public ProofOfWork(byte[] payload,
long counter,
byte[] challenge,
int difficulty,
long duration) {
long duration,
int version) {
this(payload,
counter,
challenge,
BigInteger.valueOf(difficulty).toByteArray(),
duration);
duration,
version);
}
public ProofOfWork(byte[] payload,
long counter,
byte[] challenge,
BigInteger difficulty,
long duration) {
long duration,
int version) {
this(payload,
counter,
challenge,
difficulty.toByteArray(),
duration);
duration,
version);
}
public ProofOfWork(byte[] payload,
long counter,
byte[] challenge,
byte[] difficulty,
long duration) {
private ProofOfWork(byte[] payload,
long counter,
byte[] challenge,
byte[] difficulty,
long duration,
int version) {
this.payload = payload;
this.counter = counter;
this.challenge = challenge;
this.difficulty = difficulty;
this.duration = duration;
this.version = version;
}
public int getNumLeadingZeros() {
return new BigInteger(difficulty).intValue();
}
public BigInteger getTarget() {
return new BigInteger(difficulty);
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
@ -96,6 +100,7 @@ public final class ProofOfWork implements NetworkPayload {
.setChallenge(ByteString.copyFrom(challenge))
.setDifficulty(ByteString.copyFrom(difficulty))
.setDuration(duration)
.setVersion(version)
.build();
}
@ -105,7 +110,8 @@ public final class ProofOfWork implements NetworkPayload {
proto.getCounter(),
proto.getChallenge().toByteArray(),
proto.getDifficulty().toByteArray(),
proto.getDuration()
proto.getDuration(),
proto.getVersion()
);
}
@ -115,8 +121,8 @@ public final class ProofOfWork implements NetworkPayload {
return "ProofOfWork{" +
",\r\n counter=" + counter +
",\r\n numLeadingZeros=" + getNumLeadingZeros() +
",\r\n target=" + getTarget() +
",\r\n duration=" + duration +
",\r\n version=" + version +
"\r\n}";
}
}

View File

@ -108,6 +108,8 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
// Number of leading zeros for pow for BSQ swap offers. Difficulty of 8 requires 0.856 ms in average, 15 about 100 ms.
// See ProofOfWorkTest for more info.
private final int powDifficulty;
// Enabled PoW version numbers in reverse order of preference, starting with 0 for Hashcash.
private final List<Integer> enabledPowVersions;
// Added at v 1.8.0
// BSQ fee gets updated in proposals repo (e.g. https://github.com/bisq-network/proposals/issues/345)
@ -148,6 +150,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
filter.isDisableApi(),
filter.isDisablePowMessage(),
filter.getPowDifficulty(),
filter.getEnabledPowVersions(),
filter.getMakerFeeBtc(),
filter.getTakerFeeBtc(),
filter.getMakerFeeBsq(),
@ -186,6 +189,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
filter.isDisableApi(),
filter.isDisablePowMessage(),
filter.getPowDifficulty(),
filter.getEnabledPowVersions(),
filter.getMakerFeeBtc(),
filter.getTakerFeeBtc(),
filter.getMakerFeeBsq(),
@ -219,6 +223,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
boolean disableApi,
boolean disablePowMessage,
int powDifficulty,
List<Integer> enabledPowVersions,
long makerFeeBtc,
long takerFeeBtc,
long makerFeeBsq,
@ -253,6 +258,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
disableApi,
disablePowMessage,
powDifficulty,
enabledPowVersions,
makerFeeBtc,
takerFeeBtc,
makerFeeBsq,
@ -295,6 +301,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
boolean disableApi,
boolean disablePowMessage,
int powDifficulty,
List<Integer> enabledPowVersions,
long makerFeeBtc,
long takerFeeBtc,
long makerFeeBsq,
@ -329,6 +336,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
this.disableApi = disableApi;
this.disablePowMessage = disablePowMessage;
this.powDifficulty = powDifficulty;
this.enabledPowVersions = enabledPowVersions;
this.makerFeeBtc = makerFeeBtc;
this.takerFeeBtc = takerFeeBtc;
this.makerFeeBsq = makerFeeBsq;
@ -376,6 +384,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
.setDisableApi(disableApi)
.setDisablePowMessage(disablePowMessage)
.setPowDifficulty(powDifficulty)
.addAllEnabledPowVersions(enabledPowVersions)
.setMakerFeeBtc(makerFeeBtc)
.setTakerFeeBtc(takerFeeBtc)
.setMakerFeeBsq(makerFeeBsq)
@ -422,6 +431,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
proto.getDisableApi(),
proto.getDisablePowMessage(),
proto.getPowDifficulty(),
proto.getEnabledPowVersionsList(),
proto.getMakerFeeBtc(),
proto.getTakerFeeBtc(),
proto.getMakerFeeBsq(),
@ -473,6 +483,7 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
",\n disableApi=" + disableApi +
",\n disablePowMessage=" + disablePowMessage +
",\n powDifficulty=" + powDifficulty +
",\n enabledPowVersions=" + enabledPowVersions +
",\n makerFeeBtc=" + makerFeeBtc +
",\n takerFeeBtc=" + takerFeeBtc +
",\n makerFeeBsq=" + makerFeeBsq +

View File

@ -2782,6 +2782,7 @@ filterWindow.disableApi=Disable API
filterWindow.disableMempoolValidation=Disable Mempool Validation
filterWindow.disablePowMessage=Disable messages requiring Proof of Work
filterWindow.powDifficulty=Proof of work difficulty (BSQ swap offers)
filterWindow.enabledPowVersions=Enabled proof of work versions (comma sep. integers)
filterWindow.makerFeeBtc=Min. BTC maker fee (e.g. 0.001)
filterWindow.takerFeeBtc=Min. BTC taker fee (e.g. 0.007)
filterWindow.makerFeeBsq=Min. BSQ maker fee (e.g. 15.14)

View File

@ -72,6 +72,7 @@ public class UserPayloadModelVOTest {
false,
false,
0,
Lists.newArrayList(),
0,
0,
0,

View File

@ -133,6 +133,7 @@ public class FeeReceiverSelectorTest {
false,
false,
0,
Lists.newArrayList(),
0,
0,
0,

View File

@ -41,7 +41,8 @@ import com.google.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import javafx.scene.Scene;
import javafx.scene.control.Button;
@ -55,9 +56,6 @@ import javafx.scene.layout.Region;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.collections.FXCollections;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@ -190,6 +188,8 @@ public class FilterWindow extends Overlay<FilterWindow> {
InputTextField powDifficultyTF = addInputTextField(gridPane, ++rowIndex,
Res.get("filterWindow.powDifficulty"));
powDifficultyTF.setText("0");
InputTextField enabledPowVersionsTF = addInputTextField(gridPane, ++rowIndex,
Res.get("filterWindow.enabledPowVersions"));
InputTextField makerFeeBtcTF = addInputTextField(gridPane, ++rowIndex,
Res.get("filterWindow.makerFeeBtc"));
InputTextField takerFeeBtcTF = addInputTextField(gridPane, ++rowIndex,
@ -217,6 +217,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
setupFieldFromList(btcNodesTF, filter.getBtcNodes());
setupFieldFromList(bannedPrivilegedDevPubKeysTF, filter.getBannedPrivilegedDevPubKeys());
setupFieldFromList(autoConfExplorersTF, filter.getBannedAutoConfExplorers());
setupFieldFromList(enabledPowVersionsTF, filter.getEnabledPowVersions());
preventPublicBtcNetworkCheckBox.setSelected(filter.isPreventPublicBtcNetwork());
disableDaoCheckBox.setSelected(filter.isDisableDao());
@ -270,6 +271,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
disableApiCheckBox.isSelected(),
disablePowMessage.isSelected(),
Integer.parseInt(powDifficultyTF.getText()),
readAsList(enabledPowVersionsTF).stream().map(Integer::parseInt).collect(Collectors.toList()),
ParsingUtils.parseToCoin(makerFeeBtcTF.getText(), btcFormatter).value,
ParsingUtils.parseToCoin(takerFeeBtcTF.getText(), btcFormatter).value,
ParsingUtils.parseToCoin(makerFeeBsqTF.getText(), bsqFormatter).value,
@ -325,9 +327,10 @@ public class FilterWindow extends Overlay<FilterWindow> {
hide();
}
private void setupFieldFromList(InputTextField field, Collection<String> values) {
if (values != null)
field.setText(String.join(", ", values));
private void setupFieldFromList(InputTextField field, Collection<?> values) {
if (values != null) {
field.setText(Joiner.on(", ").join(values));
}
}
private void setupFieldFromPaymentAccountFiltersList(InputTextField field, List<PaymentAccountFilter> values) {
@ -349,11 +352,7 @@ public class FilterWindow extends Overlay<FilterWindow> {
}
private List<String> readAsList(InputTextField field) {
if (field.getText().isEmpty()) {
return FXCollections.emptyObservableList();
} else {
return Arrays.asList(StringUtils.deleteWhitespace(field.getText()).split(","));
}
return Splitter.on(',').trimResults().omitEmptyStrings().splitToList(field.getText());
}
private List<PaymentAccountFilter> readAsPaymentAccountFiltersList(InputTextField field) {

View File

@ -770,6 +770,7 @@ message Filter {
bool disable_mempool_validation = 28;
bool disable_pow_message = 29;
int32 pow_difficulty = 30;
repeated int32 enabled_pow_versions = 35;
int64 maker_fee_btc = 31;
int64 taker_fee_btc = 32;
int64 maker_fee_bsq = 33;
@ -883,6 +884,7 @@ message ProofOfWork {
bytes challenge = 3;
bytes difficulty = 4;
int64 duration = 5;
int32 version = 6;
}
message AccountAgeWitness {