KeyTimeCoinSelector: factor out method isKeyBeforeCutoff()

This commit is contained in:
Sean Gilligan 2023-09-05 18:50:13 -07:00 committed by Andreas Schildbach
parent 0c7e1aec3b
commit 339e0d0450

View file

@ -33,6 +33,7 @@ import java.time.Instant;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
/** /**
* A coin selector that takes all coins assigned to keys created before the given timestamp. * A coin selector that takes all coins assigned to keys created before the given timestamp.
@ -67,23 +68,8 @@ public class KeyTimeCoinSelector implements CoinSelector {
for (TransactionOutput output : candidates) { for (TransactionOutput output : candidates) {
if (ignorePending && !isConfirmed(output)) if (ignorePending && !isConfirmed(output))
continue; continue;
// Find the key that controls output, assuming it's a regular P2PK or P2PKH output. if (!isKeyBeforeCutoff(output))
// We ignore any other kind of exotic output on the assumption we can't spend it ourselves.
final Script scriptPubKey = output.getScriptPubKey();
ECKey controllingKey;
if (ScriptPattern.isP2PK(scriptPubKey)) {
controllingKey = wallet.findKeyFromPubKey(ScriptPattern.extractKeyFromP2PK(scriptPubKey));
} else if (ScriptPattern.isP2PKH(scriptPubKey)) {
controllingKey = wallet.findKeyFromPubKeyHash(ScriptPattern.extractHashFromP2PKH(scriptPubKey), ScriptType.P2PKH);
} else if (ScriptPattern.isP2WPKH(scriptPubKey)) {
controllingKey = wallet.findKeyFromPubKeyHash(ScriptPattern.extractHashFromP2WH(scriptPubKey), ScriptType.P2WPKH);
} else {
log.info("Skipping tx output {} because it's not of simple form.", output);
continue; continue;
}
Objects.requireNonNull(controllingKey, "Coin selector given output as candidate for which we lack the key");
if (controllingKey.creationTime().orElse(Instant.EPOCH).compareTo(time) >= 0) continue;
// It's older than the cutoff time so select.
gathered.push(output); gathered.push(output);
if (gathered.size() >= MAX_SIMULTANEOUS_INPUTS) { if (gathered.size() >= MAX_SIMULTANEOUS_INPUTS) {
log.warn("Reached {} inputs, going further would yield a tx that is too large, stopping here.", gathered.size()); log.warn("Reached {} inputs, going further would yield a tx that is too large, stopping here.", gathered.size());
@ -96,6 +82,36 @@ public class KeyTimeCoinSelector implements CoinSelector {
} }
} }
private boolean isKeyBeforeCutoff(TransactionOutput output) {
Optional<ECKey> optKey = findKey(output);
// It's older than the cutoff time so select.
return optKey.isPresent() && optKey.get().creationTime().orElse(Instant.EPOCH).isBefore(time);
}
/**
* @param output output to find key for
* @return The key for this output, if available, otherwise {@code Optional.empty()}
* @throws NullPointerException if script is P2PK, P2PKH, or P2WPKH and findKeyFromPubKey* returned null
*/
private Optional<ECKey> findKey(TransactionOutput output) {
// Find the key that controls output, assuming it's a regular P2PK or P2PKH output.
// We ignore any other kind of exotic output on the assumption we can't spend it ourselves.
final Script scriptPubKey = output.getScriptPubKey();
ECKey controllingKey;
if (ScriptPattern.isP2PK(scriptPubKey)) {
controllingKey = wallet.findKeyFromPubKey(ScriptPattern.extractKeyFromP2PK(scriptPubKey));
} else if (ScriptPattern.isP2PKH(scriptPubKey)) {
controllingKey = wallet.findKeyFromPubKeyHash(ScriptPattern.extractHashFromP2PKH(scriptPubKey), ScriptType.P2PKH);
} else if (ScriptPattern.isP2WPKH(scriptPubKey)) {
controllingKey = wallet.findKeyFromPubKeyHash(ScriptPattern.extractHashFromP2WH(scriptPubKey), ScriptType.P2WPKH);
} else {
log.info("Skipping tx output {} because it's not of simple form.", output);
return Optional.empty();
}
Objects.requireNonNull(controllingKey, "Coin selector given output as candidate for which we lack the key");
return Optional.of(controllingKey);
}
private boolean isConfirmed(TransactionOutput output) { private boolean isConfirmed(TransactionOutput output) {
Transaction parent = Objects.requireNonNull(output.getParentTransaction()); Transaction parent = Objects.requireNonNull(output.getParentTransaction());
return wallet.getConfidence(parent).getConfidenceType().equals(TransactionConfidence.ConfidenceType.BUILDING); return wallet.getConfidence(parent).getConfidenceType().equals(TransactionConfidence.ConfidenceType.BUILDING);