From 35961c4ee2d122d95c230ea8232c79d5ecca9f4f Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 24 Aug 2020 14:42:19 -0300 Subject: [PATCH 1/4] add shielded balance to getwalletinfo --- qa/rpc-tests/wallet.py | 17 ++++++++++++--- src/wallet/rpcwallet.cpp | 45 +++++++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index c4c14b2eb..97963c902 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -335,8 +335,6 @@ class WalletTest (BitcoinTestFramework): mytxid = wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany(mytaddr, recipients)) - self.sync_all() - self.nodes[2].generate(1) self.sync_all() # check balances @@ -344,10 +342,18 @@ class WalletTest (BitcoinTestFramework): zsendmanyfee = Decimal('0.0001') node2utxobalance = Decimal('23.998') - zsendmanynotevalue - zsendmanyfee + # check z_balance status with getwalletinfo + wallet_info = self.nodes[2].getwalletinfo() + assert_equal(Decimal(wallet_info["z_unconfirmed_balance"]), zsendmanynotevalue) + assert_equal(Decimal(wallet_info["z_balance"]), Decimal('0.0')) + + self.nodes[2].generate(1) + self.sync_all() + assert_equal(self.nodes[2].getbalance(), node2utxobalance) assert_equal(self.nodes[2].getbalance("*"), node2utxobalance) - # check zaddr balance + # check zaddr balance with z_getbalance assert_equal(self.nodes[2].z_getbalance(myzaddr), zsendmanynotevalue) # check via z_gettotalbalance @@ -356,6 +362,11 @@ class WalletTest (BitcoinTestFramework): assert_equal(Decimal(resp["private"]), zsendmanynotevalue) assert_equal(Decimal(resp["total"]), node2utxobalance + zsendmanynotevalue) + # check confirmed z_balance with getwalletinfo + wallet_info = self.nodes[2].getwalletinfo() + assert_equal(Decimal(wallet_info["z_unconfirmed_balance"]), Decimal('0.0')) + assert_equal(Decimal(wallet_info["z_balance"]), zsendmanynotevalue) + # there should be at least one joinsplit mytxdetails = self.nodes[2].gettransaction(mytxid) myvjoinsplits = mytxdetails["vjoinsplit"] diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5fc348175..802753332 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2331,6 +2331,28 @@ UniValue settxfee(const UniValue& params, bool fHelp) return true; } +CAmount getBalanceZaddr(std::string address, int minDepth = 1, int maxDepth = INT_MAX, bool ignoreUnspendable=true) { + CAmount balance = 0; + std::vector sproutEntries; + std::vector saplingEntries; + LOCK2(cs_main, pwalletMain->cs_wallet); + + std::set filterAddresses; + if (address.length() > 0) { + KeyIO keyIO(Params()); + filterAddresses.insert(keyIO.DecodePaymentAddress(address)); + } + + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, maxDepth, true, ignoreUnspendable); + for (auto & entry : sproutEntries) { + balance += CAmount(entry.note.value()); + } + for (auto & entry : saplingEntries) { + balance += CAmount(entry.note.value()); + } + return balance; +} + UniValue getwalletinfo(const UniValue& params, bool fHelp) { if (!EnsureWalletIsAvailable(fHelp)) @@ -2346,6 +2368,8 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) " \"balance\": xxxxxxx, (numeric) the total confirmed transparent balance of the wallet in " + CURRENCY_UNIT + "\n" " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed transparent balance of the wallet in " + CURRENCY_UNIT + "\n" " \"immature_balance\": xxxxxx, (numeric) the total immature transparent balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"z_balance\": xxxxxxx, (numeric) the total confirmed shielded balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"z_unconfirmed_balance\": xxx, (numeric) the total unconfirmed shielded balance of the wallet in " + CURRENCY_UNIT + "\n" " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n" " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n" " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" @@ -2365,6 +2389,8 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) obj.pushKV("balance", ValueFromAmount(pwalletMain->GetBalance())); obj.pushKV("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())); obj.pushKV("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())); + obj.pushKV("z_balance", FormatMoney(getBalanceZaddr("", 1, INT_MAX))); + obj.pushKV("z_unconfirmed_balance", FormatMoney(getBalanceZaddr("", 0, 0))); obj.pushKV("txcount", (int)pwalletMain->mapWallet.size()); obj.pushKV("keypoololdest", pwalletMain->GetOldestKeyPoolTime()); obj.pushKV("keypoolsize", (int)pwalletMain->GetKeyPoolSize()); @@ -3373,21 +3399,6 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign return balance; } -CAmount getBalanceZaddr(std::string address, int minDepth = 1, bool ignoreUnspendable=true) { - CAmount balance = 0; - std::vector sproutEntries; - std::vector saplingEntries; - LOCK2(cs_main, pwalletMain->cs_wallet); - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, address, minDepth, true, ignoreUnspendable); - for (auto & entry : sproutEntries) { - balance += CAmount(entry.note.value()); - } - for (auto & entry : saplingEntries) { - balance += CAmount(entry.note.value()); - } - return balance; -} - struct txblock { int height = 0; @@ -3575,7 +3586,7 @@ UniValue z_getbalance(const UniValue& params, bool fHelp) if (fromTaddr) { nBalance = getBalanceTaddr(fromaddress, nMinDepth, false); } else { - nBalance = getBalanceZaddr(fromaddress, nMinDepth, false); + nBalance = getBalanceZaddr(fromaddress, nMinDepth, INT_MAX, false); } // inZat @@ -3637,7 +3648,7 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp) // pwalletMain->GetBalance() does not accept min depth parameter // so we use our own method to get balance of utxos. CAmount nBalance = getBalanceTaddr("", nMinDepth, !fIncludeWatchonly); - CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, !fIncludeWatchonly); + CAmount nPrivateBalance = getBalanceZaddr("", nMinDepth, INT_MAX, !fIncludeWatchonly); CAmount nTotalBalance = nBalance + nPrivateBalance; UniValue result(UniValue::VOBJ); result.pushKV("transparent", FormatMoney(nBalance)); From 4c4a1c4d6831c9df6d295983fb79419e9beee456 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Thu, 3 Sep 2020 07:34:01 -0600 Subject: [PATCH 2/4] Revert the move of the `getBalanceZaddr` block for ease of review. --- src/wallet/rpcwallet.cpp | 54 +++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 802753332..204a9d149 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2331,27 +2331,7 @@ UniValue settxfee(const UniValue& params, bool fHelp) return true; } -CAmount getBalanceZaddr(std::string address, int minDepth = 1, int maxDepth = INT_MAX, bool ignoreUnspendable=true) { - CAmount balance = 0; - std::vector sproutEntries; - std::vector saplingEntries; - LOCK2(cs_main, pwalletMain->cs_wallet); - - std::set filterAddresses; - if (address.length() > 0) { - KeyIO keyIO(Params()); - filterAddresses.insert(keyIO.DecodePaymentAddress(address)); - } - - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, maxDepth, true, ignoreUnspendable); - for (auto & entry : sproutEntries) { - balance += CAmount(entry.note.value()); - } - for (auto & entry : saplingEntries) { - balance += CAmount(entry.note.value()); - } - return balance; -} +CAmount getBalanceZaddr(std::string address, int minDepth = 1, int maxDepth = INT_MAX, bool ignoreUnspendable=true); UniValue getwalletinfo(const UniValue& params, bool fHelp) { @@ -2655,11 +2635,11 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) // User did not provide zaddrs, so use default i.e. all addresses std::set sproutzaddrs = {}; pwalletMain->GetSproutPaymentAddresses(sproutzaddrs); - + // Sapling support std::set saplingzaddrs = {}; pwalletMain->GetSaplingPaymentAddresses(saplingzaddrs); - + zaddrs.insert(sproutzaddrs.begin(), sproutzaddrs.end()); zaddrs.insert(saplingzaddrs.begin(), saplingzaddrs.end()); } @@ -2671,7 +2651,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) std::vector saplingEntries; pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false); std::set> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs); - + for (auto & entry : sproutEntries) { UniValue obj(UniValue::VOBJ); obj.pushKV("txid", entry.jsop.hash.ToString()); @@ -3399,6 +3379,28 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign return balance; } +CAmount getBalanceZaddr(std::string address, int minDepth = 1, int maxDepth = INT_MAX, bool ignoreUnspendable=true) { + CAmount balance = 0; + std::vector sproutEntries; + std::vector saplingEntries; + LOCK2(cs_main, pwalletMain->cs_wallet); + + std::set filterAddresses; + if (address.length() > 0) { + KeyIO keyIO(Params()); + filterAddresses.insert(keyIO.DecodePaymentAddress(address)); + } + + pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, maxDepth, true, ignoreUnspendable); + for (auto & entry : sproutEntries) { + balance += CAmount(entry.note.value()); + } + for (auto & entry : saplingEntries) { + balance += CAmount(entry.note.value()); + } + return balance; +} + struct txblock { int height = 0; @@ -4284,7 +4286,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp) CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight); bool isShielded = !fromTaddr || zaddrRecipients.size() > 0; if (contextualTx.nVersion == 1 && isShielded) { - contextualTx.nVersion = 2; // Tx format should support vJoinSplits + contextualTx.nVersion = 2; // Tx format should support vJoinSplits } // Create operation and add to global queue @@ -4628,7 +4630,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp) CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight); if (contextualTx.nVersion == 1) { - contextualTx.nVersion = 2; // Tx format should support vJoinSplit + contextualTx.nVersion = 2; // Tx format should support vJoinSplit } // Create operation and add to global queue From bd4469339a79a5146b0998fbfd4f0c58c594d920 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 3 Sep 2020 14:43:10 +0100 Subject: [PATCH 3/4] Rename z_*_balance fields of getwalletinfo output to shielded_*_balance --- qa/rpc-tests/wallet.py | 12 ++++++------ src/wallet/rpcwallet.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 97963c902..83d4cf4c5 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -342,10 +342,10 @@ class WalletTest (BitcoinTestFramework): zsendmanyfee = Decimal('0.0001') node2utxobalance = Decimal('23.998') - zsendmanynotevalue - zsendmanyfee - # check z_balance status with getwalletinfo + # check shielded balance status with getwalletinfo wallet_info = self.nodes[2].getwalletinfo() - assert_equal(Decimal(wallet_info["z_unconfirmed_balance"]), zsendmanynotevalue) - assert_equal(Decimal(wallet_info["z_balance"]), Decimal('0.0')) + assert_equal(Decimal(wallet_info["shielded_unconfirmed_balance"]), zsendmanynotevalue) + assert_equal(Decimal(wallet_info["shielded_balance"]), Decimal('0.0')) self.nodes[2].generate(1) self.sync_all() @@ -362,10 +362,10 @@ class WalletTest (BitcoinTestFramework): assert_equal(Decimal(resp["private"]), zsendmanynotevalue) assert_equal(Decimal(resp["total"]), node2utxobalance + zsendmanynotevalue) - # check confirmed z_balance with getwalletinfo + # check confirmed shielded balance with getwalletinfo wallet_info = self.nodes[2].getwalletinfo() - assert_equal(Decimal(wallet_info["z_unconfirmed_balance"]), Decimal('0.0')) - assert_equal(Decimal(wallet_info["z_balance"]), zsendmanynotevalue) + assert_equal(Decimal(wallet_info["shielded_unconfirmed_balance"]), Decimal('0.0')) + assert_equal(Decimal(wallet_info["shielded_balance"]), zsendmanynotevalue) # there should be at least one joinsplit mytxdetails = self.nodes[2].gettransaction(mytxid) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 204a9d149..ad0fe59e4 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2348,8 +2348,8 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) " \"balance\": xxxxxxx, (numeric) the total confirmed transparent balance of the wallet in " + CURRENCY_UNIT + "\n" " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed transparent balance of the wallet in " + CURRENCY_UNIT + "\n" " \"immature_balance\": xxxxxx, (numeric) the total immature transparent balance of the wallet in " + CURRENCY_UNIT + "\n" - " \"z_balance\": xxxxxxx, (numeric) the total confirmed shielded balance of the wallet in " + CURRENCY_UNIT + "\n" - " \"z_unconfirmed_balance\": xxx, (numeric) the total unconfirmed shielded balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"shielded_balance\": xxxxxxx, (numeric) the total confirmed shielded balance of the wallet in " + CURRENCY_UNIT + "\n" + " \"shielded_unconfirmed_balance\": xxx, (numeric) the total unconfirmed shielded balance of the wallet in " + CURRENCY_UNIT + "\n" " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n" " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n" " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n" @@ -2369,8 +2369,8 @@ UniValue getwalletinfo(const UniValue& params, bool fHelp) obj.pushKV("balance", ValueFromAmount(pwalletMain->GetBalance())); obj.pushKV("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())); obj.pushKV("immature_balance", ValueFromAmount(pwalletMain->GetImmatureBalance())); - obj.pushKV("z_balance", FormatMoney(getBalanceZaddr("", 1, INT_MAX))); - obj.pushKV("z_unconfirmed_balance", FormatMoney(getBalanceZaddr("", 0, 0))); + obj.pushKV("shielded_balance", FormatMoney(getBalanceZaddr("", 1, INT_MAX))); + obj.pushKV("shielded_unconfirmed_balance", FormatMoney(getBalanceZaddr("", 0, 0))); obj.pushKV("txcount", (int)pwalletMain->mapWallet.size()); obj.pushKV("keypoololdest", pwalletMain->GetOldestKeyPoolTime()); obj.pushKV("keypoolsize", (int)pwalletMain->GetKeyPoolSize()); From 9d8555cf1b2999683e049829fb78e0db7aacb337 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Fri, 4 Sep 2020 07:28:15 -0600 Subject: [PATCH 4/4] Fix forward declaration. --- src/wallet/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ad0fe59e4..a37fce0de 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3379,7 +3379,7 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign return balance; } -CAmount getBalanceZaddr(std::string address, int minDepth = 1, int maxDepth = INT_MAX, bool ignoreUnspendable=true) { +CAmount getBalanceZaddr(std::string address, int minDepth, int maxDepth, bool ignoreUnspendable) { CAmount balance = 0; std::vector sproutEntries; std::vector saplingEntries;