From 276cb8aecbf4ec0362c2f8e76277ce964f2a3eca Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Thu, 19 Jan 2023 13:52:47 +0200 Subject: [PATCH] cormorant: support transaction.get without txindex, use step function to add bip47 addresses --- .../cormorant/bitcoind/BitcoindClient.java | 16 ++++-- .../bitcoind/BitcoindClientService.java | 3 ++ .../electrum/ElectrumServerService.java | 51 +++++++++++++++---- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClient.java b/src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClient.java index de72a593..402c0a94 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClient.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClient.java @@ -133,7 +133,12 @@ public class BitcoindClient { try { getBitcoindService().loadWallet(CORE_WALLET_NAME, false); } catch(JsonRpcException e) { - getBitcoindService().unloadWallet(CORE_WALLET_NAME, false); + try { + getBitcoindService().unloadWallet(CORE_WALLET_NAME, false); + } catch(JsonRpcException ex) { + //ignore + } + getBitcoindService().loadWallet(CORE_WALLET_NAME, false); } } @@ -188,10 +193,15 @@ public class BitcoindClient { for(Wallet childWallet : wallet.getChildWallets()) { if(childWallet.isNested()) { + Wallet copyChildWallet = childWallet.copy(); for(KeyPurpose keyPurpose : KeyPurpose.DEFAULT_PURPOSES) { - for(WalletNode addressNode : childWallet.getNode(keyPurpose).getChildren()) { + WalletNode purposeNode = copyChildWallet.getNode(keyPurpose); + int addressCount = purposeNode.getChildren().size(); + int gapLimit = ((int)Math.floor(addressCount / 10.0) * 10) + 10; + purposeNode.fillToIndex(gapLimit - 1); + for(WalletNode addressNode : purposeNode.getChildren()) { String addressOutputDescriptor = OutputDescriptor.toDescriptorString(addressNode.getAddress()); - addOutputDescriptor(outputDescriptors, addressOutputDescriptor, childWallet, null, earliestBirthDate); + addOutputDescriptor(outputDescriptors, addressOutputDescriptor, copyChildWallet, null, earliestBirthDate); } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClientService.java b/src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClientService.java index eda68c4a..d702a4e5 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClientService.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/cormorant/bitcoind/BitcoindClientService.java @@ -43,6 +43,9 @@ public interface BitcoindClientService { @JsonRpcMethod("getrawtransaction") Object getRawTransaction(@JsonRpcParam("txid") String txid, @JsonRpcParam("verbose") boolean verbose); + @JsonRpcMethod("gettransaction") + Map getTransaction(@JsonRpcParam("txid") String txid, @JsonRpcParam("verbose") boolean verbose); + @JsonRpcMethod("getmempoolentry") MempoolEntry getMempoolEntry(@JsonRpcParam("txid") String txid); diff --git a/src/main/java/com/sparrowwallet/sparrow/net/cormorant/electrum/ElectrumServerService.java b/src/main/java/com/sparrowwallet/sparrow/net/cormorant/electrum/ElectrumServerService.java index 9d5a22cd..7363425c 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/cormorant/electrum/ElectrumServerService.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/cormorant/electrum/ElectrumServerService.java @@ -13,10 +13,7 @@ import com.sparrowwallet.sparrow.net.cormorant.index.TxEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; @JsonRpcService public class ElectrumServerService { @@ -146,13 +143,47 @@ public class ElectrumServerService { } @JsonRpcMethod("blockchain.transaction.get") + @SuppressWarnings("unchecked") public Object getTransaction(@JsonRpcParam("tx_hash") String tx_hash, @JsonRpcParam("verbose") @JsonRpcOptional boolean verbose) throws BitcoindIOException, TransactionNotFoundException { - try { - return bitcoindClient.getBitcoindService().getRawTransaction(tx_hash, verbose); - } catch(JsonRpcException e) { - throw new TransactionNotFoundException(e.getErrorMessage()); - } catch(IllegalStateException e) { - throw new BitcoindIOException(e); + if(verbose) { + try { + return bitcoindClient.getBitcoindService().getRawTransaction(tx_hash, true); + } catch(JsonRpcException e) { + try { + Map txInfo = bitcoindClient.getBitcoindService().getTransaction(tx_hash, true); + Object decoded = txInfo.get("decoded"); + if(decoded instanceof Map) { + Map decodedMap = (Map)decoded; + decodedMap.put("hex", txInfo.get("hex")); + decodedMap.put("confirmations", txInfo.get("confirmations")); + decodedMap.put("blockhash", txInfo.get("blockhash")); + decodedMap.put("time", txInfo.get("time")); + decodedMap.put("blocktime", txInfo.get("blocktime")); + return decoded; + } + throw new TransactionNotFoundException(e.getErrorMessage()); + } catch(JsonRpcException ex) { + throw new TransactionNotFoundException(ex.getErrorMessage()); + } catch(IllegalStateException ex) { + throw new BitcoindIOException(ex); + } + } catch(IllegalStateException e) { + throw new BitcoindIOException(e); + } + } else { + try { + return bitcoindClient.getBitcoindService().getTransaction(tx_hash, false).get("hex"); + } catch(JsonRpcException e) { + try { + return bitcoindClient.getBitcoindService().getRawTransaction(tx_hash, false); + } catch(JsonRpcException ex) { + throw new TransactionNotFoundException(ex.getErrorMessage()); + } catch(IllegalStateException ex) { + throw new BitcoindIOException(e); + } + } catch(IllegalStateException e) { + throw new BitcoindIOException(e); + } } }