From 75730f00ac9930c5800bd0868133903c90ce7930 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Thu, 2 Nov 2023 12:37:49 +0100 Subject: [PATCH] add support for searching for the required gap limit to sign a psbt where global xpubs match --- .../sparrowwallet/drongo/wallet/Wallet.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java b/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java index ecbc356..10d2234 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java @@ -24,6 +24,7 @@ import static com.sparrowwallet.drongo.protocol.Transaction.WITNESS_SCALE_FACTOR public class Wallet extends Persistable implements Comparable { public static final int DEFAULT_LOOKAHEAD = 20; + public static final int SEARCH_LOOKAHEAD = 4000; public static final String ALLOW_DERIVATIONS_MATCHING_OTHER_SCRIPT_TYPES_PROPERTY = "com.sparrowwallet.allowDerivationsMatchingOtherScriptTypes"; private String name; @@ -1484,6 +1485,41 @@ public class Wallet extends Persistable implements Comparable { return signingNodes; } + public List getSigningKeystores(PSBT psbt) { + List signingKeystores = new ArrayList<>(); + + for(Map.Entry entry : psbt.getExtendedPublicKeys().entrySet()) { + for(Keystore keystore : getKeystores()) { + if(entry.getKey().equals(keystore.getExtendedPublicKey()) && entry.getValue().equals(keystore.getKeyDerivation())) { + signingKeystores.add(keystore); + } + } + } + + return signingKeystores; + } + + public Integer getRequiredGapLimit(PSBT psbt) { + Wallet copy = this.copy(); + for(KeyPurpose keyPurpose : KeyPurpose.DEFAULT_PURPOSES) { + WalletNode purposeNode = copy.getNode(keyPurpose); + purposeNode.fillToIndex(purposeNode.getChildren().size() + SEARCH_LOOKAHEAD); + } + Map copySigningNodes = copy.getSigningNodes(psbt); + boolean found = false; + int gapLimit = getGapLimit(); + for(KeyPurpose keyPurpose : KeyPurpose.DEFAULT_PURPOSES) { + OptionalInt optHighestIndex = copySigningNodes.values().stream().filter(node -> node.getKeyPurpose() == keyPurpose).mapToInt(WalletNode::getIndex).max(); + if(optHighestIndex.isPresent()) { + found = true; + Integer highestUsedIndex = getNode(keyPurpose).getHighestUsedIndex(); + gapLimit = Math.max(gapLimit, optHighestIndex.getAsInt() - (highestUsedIndex == null ? -1 : highestUsedIndex)); + } + } + + return found ? gapLimit : null; + } + /** * Determines which keystores have signed a PSBT *