Make getActiveBurningManCandidates return a list instead of a set

This avoids needless hashing & equality comparisons of instances of
'BurningManCandidate', which are quite large mutable objects (so should
probably use reference equality anyway, and not be used as keys).

Also rearrange a couple of (package) private methods.
This commit is contained in:
Steven Barclay 2024-07-13 16:52:19 +02:00
parent 267becf612
commit aa7aedd0b1
No known key found for this signature in database
GPG Key ID: 9FED6BF1176D500B
2 changed files with 35 additions and 36 deletions

View File

@ -27,7 +27,6 @@ import javax.inject.Singleton;
import com.google.common.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
@ -69,7 +68,7 @@ public class BtcFeeReceiverService implements DaoStateListener {
///////////////////////////////////////////////////////////////////////////////////////////
public String getAddress() {
List<BurningManCandidate> activeBurningManCandidates = new ArrayList<>(burningManService.getActiveBurningManCandidates(currentChainHeight));
List<BurningManCandidate> activeBurningManCandidates = burningManService.getActiveBurningManCandidates(currentChainHeight);
if (activeBurningManCandidates.isEmpty()) {
// If there are no compensation requests (e.g. at dev testing) we fall back to the default address
return burningManService.getLegacyBurningManAddress(currentChainHeight);

View File

@ -205,52 +205,21 @@ public class BurningManService {
return burningManCandidatesByName;
}
private static int imposeCaps(Collection<BurningManCandidate> burningManCandidates, boolean limitCappingRounds) {
List<BurningManCandidate> candidatesInDescendingBurnCapRatio = new ArrayList<>(burningManCandidates);
candidatesInDescendingBurnCapRatio.sort(Comparator.comparing(BurningManCandidate::getBurnCapRatio).reversed());
double thresholdBurnCapRatio = 1.0;
double remainingBurnShare = 1.0;
double remainingCapShare = 1.0;
int cappingRound = 0;
for (BurningManCandidate candidate : candidatesInDescendingBurnCapRatio) {
double invScaleFactor = remainingBurnShare / remainingCapShare;
double burnCapRatio = candidate.getBurnCapRatio();
if (remainingCapShare <= 0.0 || burnCapRatio <= 0.0 || burnCapRatio < invScaleFactor ||
limitCappingRounds && burnCapRatio < 1.0) {
cappingRound++;
break;
}
if (burnCapRatio < thresholdBurnCapRatio) {
thresholdBurnCapRatio = invScaleFactor;
cappingRound++;
}
candidate.imposeCap(cappingRound, candidate.getBurnAmountShare() / thresholdBurnCapRatio);
remainingBurnShare -= candidate.getBurnAmountShare();
remainingCapShare -= candidate.getMaxBoostedCompensationShare();
}
return cappingRound;
}
String getLegacyBurningManAddress(int chainHeight) {
return daoStateService.getParamValue(Param.RECIPIENT_BTC_ADDRESS, chainHeight);
}
Set<BurningManCandidate> getActiveBurningManCandidates(int chainHeight) {
List<BurningManCandidate> getActiveBurningManCandidates(int chainHeight) {
return getActiveBurningManCandidates(chainHeight, !DelayedPayoutTxReceiverService.isProposal412Activated());
}
Set<BurningManCandidate> getActiveBurningManCandidates(int chainHeight, boolean limitCappingRounds) {
List<BurningManCandidate> getActiveBurningManCandidates(int chainHeight, boolean limitCappingRounds) {
return getBurningManCandidatesByName(chainHeight, limitCappingRounds).values().stream()
.filter(burningManCandidate -> burningManCandidate.getCappedBurnAmountShare() > 0)
.filter(candidate -> candidate.getReceiverAddress().isPresent())
.collect(Collectors.toSet());
.collect(Collectors.toList());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
Map<P2PDataStorage.ByteArray, Set<TxOutput>> getProofOfBurnOpReturnTxOutputByHash(int chainHeight) {
Map<P2PDataStorage.ByteArray, Set<TxOutput>> map = new HashMap<>();
daoStateService.getProofOfBurnOpReturnTxOutputs().stream()
@ -262,6 +231,11 @@ public class BurningManService {
return map;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void forEachCompensationIssuance(int chainHeight, BiConsumer<Issuance, CompensationProposal> action) {
proposalService.getProposalPayloads().stream()
.map(ProposalPayload::getProposal)
@ -378,4 +352,30 @@ public class BurningManService {
private long getDecayedGenesisOutputAmount(long amount) {
return Math.round(amount * GENESIS_OUTPUT_AMOUNT_FACTOR);
}
private static int imposeCaps(Collection<BurningManCandidate> burningManCandidates, boolean limitCappingRounds) {
List<BurningManCandidate> candidatesInDescendingBurnCapRatio = new ArrayList<>(burningManCandidates);
candidatesInDescendingBurnCapRatio.sort(Comparator.comparing(BurningManCandidate::getBurnCapRatio).reversed());
double thresholdBurnCapRatio = 1.0;
double remainingBurnShare = 1.0;
double remainingCapShare = 1.0;
int cappingRound = 0;
for (BurningManCandidate candidate : candidatesInDescendingBurnCapRatio) {
double invScaleFactor = remainingBurnShare / remainingCapShare;
double burnCapRatio = candidate.getBurnCapRatio();
if (remainingCapShare <= 0.0 || burnCapRatio <= 0.0 || burnCapRatio < invScaleFactor ||
limitCappingRounds && burnCapRatio < 1.0) {
cappingRound++;
break;
}
if (burnCapRatio < thresholdBurnCapRatio) {
thresholdBurnCapRatio = invScaleFactor;
cappingRound++;
}
candidate.imposeCap(cappingRound, candidate.getBurnAmountShare() / thresholdBurnCapRatio);
remainingBurnShare -= candidate.getBurnAmountShare();
remainingCapShare -= candidate.getMaxBoostedCompensationShare();
}
return cappingRound;
}
}