mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Inline predicates to simplify HashCashService & FilterManager
Remove all the 'challengeValidation', 'difficultyValidation' and 'testDifficulty' BiPredicate method params from 'HashCashService' & 'ProofOfWorkService', to simplify the API. These were originally included to aid testing, but turned out to be unnecessary. Patches committed on behalf of @chimp1984.
This commit is contained in:
parent
772cd74ab2
commit
92209c3ed7
@ -22,24 +22,18 @@ import com.google.common.primitives.Longs;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* HashCash implementation for proof of work
|
||||
* It doubles required work by difficulty increase (adding one leading zero).
|
||||
* It doubles required work by log2Difficulty increase (adding one leading zero).
|
||||
*
|
||||
* See https://www.hashcash.org/papers/hashcash.pdf
|
||||
*/
|
||||
@Slf4j
|
||||
public class HashCashService extends ProofOfWorkService {
|
||||
// Default validations. Custom implementations might use tolerance.
|
||||
private static final BiPredicate<byte[], byte[]> isChallengeValid = Arrays::equals;
|
||||
private static final BiPredicate<Integer, Integer> isDifficultyValid = Integer::equals;
|
||||
|
||||
HashCashService() {
|
||||
super(0);
|
||||
}
|
||||
@ -50,105 +44,35 @@ public class HashCashService extends ProofOfWorkService {
|
||||
return mint(payload, challenge, difficulty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getChallenge(String itemId, String ownerId) {
|
||||
return getBytes(itemId + ownerId);
|
||||
}
|
||||
|
||||
static CompletableFuture<ProofOfWork> mint(byte[] payload,
|
||||
public CompletableFuture<ProofOfWork> mint(byte[] payload,
|
||||
byte[] challenge,
|
||||
double difficulty) {
|
||||
return HashCashService.mint(payload,
|
||||
challenge,
|
||||
difficulty,
|
||||
HashCashService::testDifficulty);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean verify(ProofOfWork proofOfWork) {
|
||||
return verify(proofOfWork,
|
||||
proofOfWork.getChallenge(),
|
||||
toNumLeadingZeros(proofOfWork.getDifficulty()));
|
||||
}
|
||||
|
||||
static boolean verify(ProofOfWork proofOfWork,
|
||||
byte[] controlChallenge,
|
||||
int controlLog2Difficulty) {
|
||||
return HashCashService.verify(proofOfWork,
|
||||
controlChallenge,
|
||||
controlLog2Difficulty,
|
||||
HashCashService::testDifficulty);
|
||||
}
|
||||
|
||||
static boolean verify(ProofOfWork proofOfWork,
|
||||
byte[] controlChallenge,
|
||||
int controlLog2Difficulty,
|
||||
BiPredicate<byte[], byte[]> challengeValidation,
|
||||
BiPredicate<Integer, Integer> difficultyValidation) {
|
||||
return HashCashService.verify(proofOfWork,
|
||||
controlChallenge,
|
||||
controlLog2Difficulty,
|
||||
challengeValidation,
|
||||
difficultyValidation,
|
||||
HashCashService::testDifficulty);
|
||||
}
|
||||
|
||||
private static boolean testDifficulty(byte[] result, int log2Difficulty) {
|
||||
return HashCashService.numberOfLeadingZeros(result) > log2Difficulty;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Generic
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static CompletableFuture<ProofOfWork> mint(byte[] payload,
|
||||
byte[] challenge,
|
||||
double difficulty,
|
||||
BiPredicate<byte[], Integer> testDifficulty) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
long ts = System.currentTimeMillis();
|
||||
int log2Difficulty = toNumLeadingZeros(difficulty);
|
||||
byte[] result;
|
||||
byte[] hash;
|
||||
long counter = 0;
|
||||
do {
|
||||
result = toSha256Hash(payload, challenge, ++counter);
|
||||
hash = toSha256Hash(payload, challenge, ++counter);
|
||||
}
|
||||
while (!testDifficulty.test(result, log2Difficulty));
|
||||
while (numberOfLeadingZeros(hash) <= log2Difficulty);
|
||||
ProofOfWork proofOfWork = new ProofOfWork(payload, counter, challenge, difficulty, System.currentTimeMillis() - ts, 0);
|
||||
log.info("Completed minting proofOfWork: {}", proofOfWork);
|
||||
return proofOfWork;
|
||||
});
|
||||
}
|
||||
|
||||
static boolean verify(ProofOfWork proofOfWork,
|
||||
byte[] controlChallenge,
|
||||
int controlLog2Difficulty,
|
||||
BiPredicate<byte[], Integer> testDifficulty) {
|
||||
return verify(proofOfWork,
|
||||
controlChallenge,
|
||||
controlLog2Difficulty,
|
||||
HashCashService.isChallengeValid,
|
||||
HashCashService.isDifficultyValid,
|
||||
testDifficulty);
|
||||
}
|
||||
|
||||
static boolean verify(ProofOfWork proofOfWork,
|
||||
byte[] controlChallenge,
|
||||
int controlLog2Difficulty,
|
||||
BiPredicate<byte[], byte[]> challengeValidation,
|
||||
BiPredicate<Integer, Integer> difficultyValidation,
|
||||
BiPredicate<byte[], Integer> testDifficulty) {
|
||||
return challengeValidation.test(proofOfWork.getChallenge(), controlChallenge) &&
|
||||
difficultyValidation.test(toNumLeadingZeros(proofOfWork.getDifficulty()), controlLog2Difficulty) &&
|
||||
verify(proofOfWork, testDifficulty);
|
||||
}
|
||||
|
||||
private static boolean verify(ProofOfWork proofOfWork, BiPredicate<byte[], Integer> testDifficulty) {
|
||||
byte[] hash = HashCashService.toSha256Hash(proofOfWork.getPayload(),
|
||||
@Override
|
||||
boolean verify(ProofOfWork proofOfWork) {
|
||||
byte[] hash = toSha256Hash(proofOfWork.getPayload(),
|
||||
proofOfWork.getChallenge(),
|
||||
proofOfWork.getCounter());
|
||||
return testDifficulty.test(hash, toNumLeadingZeros(proofOfWork.getDifficulty()));
|
||||
return numberOfLeadingZeros(hash) > toNumLeadingZeros(proofOfWork.getDifficulty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getChallenge(String itemId, String ownerId) {
|
||||
return getBytes(itemId + ownerId);
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,9 +19,9 @@ package bisq.common.crypto;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@ -58,15 +58,13 @@ public abstract class ProofOfWorkService {
|
||||
public boolean verify(ProofOfWork proofOfWork,
|
||||
String itemId,
|
||||
String ownerId,
|
||||
double controlDifficulty,
|
||||
BiPredicate<byte[], byte[]> challengeValidation,
|
||||
BiPredicate<Double, Double> difficultyValidation) {
|
||||
double controlDifficulty) {
|
||||
|
||||
Preconditions.checkArgument(proofOfWork.getVersion() == version);
|
||||
|
||||
byte[] controlChallenge = getChallenge(itemId, ownerId);
|
||||
return challengeValidation.test(proofOfWork.getChallenge(), controlChallenge) &&
|
||||
difficultyValidation.test(proofOfWork.getDifficulty(), controlDifficulty) &&
|
||||
return Arrays.equals(proofOfWork.getChallenge(), controlChallenge) &&
|
||||
proofOfWork.getDifficulty() >= controlDifficulty &&
|
||||
verify(proofOfWork);
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class HashCashServiceTest {
|
||||
List<ProofOfWork> tokens = new ArrayList<>();
|
||||
for (int i = 0; i < numTokens; i++) {
|
||||
byte[] challenge = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8);
|
||||
tokens.add(HashCashService.mint(payload, challenge, difficulty).get());
|
||||
tokens.add(new HashCashService().mint(payload, challenge, difficulty).get());
|
||||
}
|
||||
double size = tokens.size();
|
||||
long ts2 = System.currentTimeMillis();
|
||||
|
@ -37,9 +37,9 @@ import bisq.common.app.DevEnv;
|
||||
import bisq.common.app.Version;
|
||||
import bisq.common.config.Config;
|
||||
import bisq.common.config.ConfigFileEditor;
|
||||
import bisq.common.crypto.ProofOfWorkService;
|
||||
import bisq.common.crypto.KeyRing;
|
||||
import bisq.common.crypto.ProofOfWork;
|
||||
import bisq.common.crypto.ProofOfWorkService;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
@ -58,7 +58,6 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@ -66,7 +65,6 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@ -88,12 +86,6 @@ public class FilterManager {
|
||||
private static final String BANNED_SEED_NODES = "bannedSeedNodes";
|
||||
private static final String BANNED_BTC_NODES = "bannedBtcNodes";
|
||||
|
||||
private final BiPredicate<byte[], byte[]> challengeValidation = Arrays::equals;
|
||||
// We only require a new pow if difficulty has increased
|
||||
private final BiPredicate<Double, Double> difficultyValidation =
|
||||
(value, controlValue) -> value - controlValue >= 0;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Listener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -506,9 +498,7 @@ public class FilterManager {
|
||||
}
|
||||
return service.get().verify(offer.getBsqSwapOfferPayload().get().getProofOfWork(),
|
||||
offer.getId(), offer.getOwnerNodeAddress().toString(),
|
||||
filter.getPowDifficulty(),
|
||||
challengeValidation,
|
||||
difficultyValidation);
|
||||
filter.getPowDifficulty());
|
||||
}
|
||||
|
||||
public List<Integer> getEnabledPowVersions() {
|
||||
|
Loading…
Reference in New Issue
Block a user