From 54ec0d09949c45a5880a71f43b6a946b7f01ca9a Mon Sep 17 00:00:00 2001 From: Charles <18726788+csharpee@users.noreply.github.com> Date: Sun, 29 Mar 2020 03:01:46 -0400 Subject: [PATCH 01/98] updated undefined behavior in accordance with zcash remedy rex4539 #4056 --- src/arith_uint256.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index e9c0dd056..d7a5c0afe 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -193,9 +193,10 @@ unsigned int base_uint::bits() const { for (int pos = WIDTH - 1; pos >= 0; pos--) { if (pn[pos]) { - for (int bits = 31; bits > 0; bits--) { - if (pn[pos] & 1 << bits) + for (size_t bits = 31; bits > 0; bits--) { + if (pn[pos] & (1U << bits)) { return 32 * pos + bits + 1; + } } return 32 * pos + 1; } From bd88898ce037f6ee0e7bb945d9da4b221f931e8f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 12 Apr 2020 05:55:08 -0400 Subject: [PATCH 02/98] Implement z2z transition period for mempool --- src/main.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 17b89a76b..aa8ba176e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1741,6 +1741,25 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, int dosLevel) { AssertLockHeld(cs_main); + uint32_t z2zTransitionWindow = 10; + uint32_t z2zTransitionStart = 340000 - z2zTransitionWindow; + uint32_t z2zTransitionEnd = 340000; + bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; + uint32_t nHeight = chainActive.Height(); + + // This only applies to HUSH3, other chains can start off z2z via ac_private=1 + if(ishush3) { + if((nHeight >= z2zTransitionStart) || (nHeight <= z2zTransitionEnd)) { + // During the z2z transition window, only coinbase tx's as part of blocks are allowed + // Theory: We want an empty mempool at our fork block height, and the only way to assure that + // is to have an empty mempool for a few previous blocks, to take care of potential re-orgs + // and edge cases. This empty mempool assures there will be no transactions involving taddrs + // stuck in the mempool, when the z2z rule takes effect. + // Thanks to jl777 for helping design this + fprintf(stderr,"%s: rejecting all tx's during z2z transition window at height=%d\n", __func__,nHeight); + return false; + } + } if (pfMissingInputs) *pfMissingInputs = false; uint32_t tiptime; From 3d9e662266a28f6d634185d239b6b23ec362b629 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 14 Apr 2020 07:53:01 -0400 Subject: [PATCH 03/98] Switch to -ac_private=1 at our z2z fork height --- src/main.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index aa8ba176e..7575a4e0a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3368,6 +3368,19 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return(false); //fprintf(stderr,"connectblock ht.%d\n",(int32_t)pindex->GetHeight()); AssertLockHeld(cs_main); + + bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; + if(!ASSETCHAINS_PRIVATE && ishush3) { + unsigned int z2zForkHeight = 340000; + unsigned int nHeight = pindex->GetHeight(); + if(nHeight >= z2zForkHeight) { + // At startup, HUSH3 doesn't know a block height yet and so we must wait until + // connecting a block + fprintf(stderr, "%s: Going full z2z at height %d!\n",__func__,nHeight); + ASSETCHAINS_PRIVATE = 1; + } + } + bool fExpensiveChecks = true; if (fCheckpointsEnabled) { CBlockIndex *pindexLastCheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints()); From e51556083793c3c5272f31b3e64cf6cfecddae27 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 14 Apr 2020 22:27:24 -0400 Subject: [PATCH 04/98] Improve and remove mention of sprout in this error message --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7575a4e0a..20c6cffe6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1591,11 +1591,11 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio if ( counter++ < 10 ) fprintf(stderr,"found taddr in private chain: z_z.%d z_t.%d t_z.%d vinsize.%d\n",z_z,z_t,t_z,(int32_t)tx.vin.size()); if ( z_t == 0 || z_z != 0 || t_z != 0 || tx.vin.size() != 0 ) - return state.DoS(100, error("CheckTransaction(): this is a private chain, only sprout -> taddr allowed until deadline"),REJECT_INVALID, "bad-txns-acprivacy-chain"); + return state.DoS(100, error("CheckTransaction(): this is a private chain, sending to taddrs not allowed"),REJECT_INVALID, "bad-txns-acprivacy-chain"); } if ( ASSETCHAINS_TXPOW != 0 ) { - // genesis coinbase 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b + // BTC genesis coinbase 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b uint256 txid = tx.GetHash(); if ( ((ASSETCHAINS_TXPOW & 2) != 0 && iscoinbase != 0) || ((ASSETCHAINS_TXPOW & 1) != 0 && iscoinbase == 0) ) { From 77cc82428bab83079bdd3a0751645b2a8a25cc27 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 15 Apr 2020 00:59:47 -0400 Subject: [PATCH 05/98] Hush Smart Chains --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index ac15db192..b9bc096a7 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -581,7 +581,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-metricsui", _("Set to 1 for a persistent metrics screen, 0 for sequential metrics output (default: 1 if running in a console, 0 otherwise)")); strUsage += HelpMessageOpt("-metricsrefreshtime", strprintf(_("Number of seconds between metrics refreshes (default: %u if running in a console, %u otherwise)"), 1, 600)); } - strUsage += HelpMessageGroup(_("Komodo Asset Chain options:")); + strUsage += HelpMessageGroup(_("Hush Smart Chain options:")); strUsage += HelpMessageOpt("-ac_algo", _("Choose PoW mining algorithm, default is Equihash")); strUsage += HelpMessageOpt("-ac_blocktime", _("Block time in seconds, default is 60")); strUsage += HelpMessageOpt("-ac_cc", _("Cryptoconditions, default 0")); From a2013ecc39219151067578661b3dbf13b4e1fe7f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 15 Apr 2020 02:07:19 -0400 Subject: [PATCH 06/98] Fix incorrect error message --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 20c6cffe6..cfe851f7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6121,7 +6121,7 @@ CBlockIndex * InsertBlockIndex(uint256 hash) // Create new CBlockIndex* pindexNew = new CBlockIndex(); if (!pindexNew) - throw runtime_error("LoadBlockIndex(): new CBlockIndex failed"); + throw runtime_error("InsertBlockIndex(): new CBlockIndex failed"); mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first; pindexNew->phashBlock = &((*mi).first); //fprintf(stderr,"inserted to block index %s\n",hash.ToString().c_str()); From 41a4c84633945f868061abd0b17741ecceaa1935 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 15 Apr 2020 02:39:18 -0400 Subject: [PATCH 07/98] Refactor z2z and additionally set ac_private=1 when loading block index from disk This should avoid the edge case when a node starts up after the z2z block height but has not yet seen a new block and so does not yet know it is an -ac_private=1 chain, as currently that is set in ConnectBlock. --- src/main.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cfe851f7f..472a8bb90 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -114,6 +114,8 @@ bool fAlerts = DEFAULT_ALERTS; /* If the tip is older than this (in seconds), the node is considered to be in initial block download. */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; +bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; +unsigned int z2zForkHeight = 340000; unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; @@ -1742,14 +1744,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { AssertLockHeld(cs_main); uint32_t z2zTransitionWindow = 10; - uint32_t z2zTransitionStart = 340000 - z2zTransitionWindow; - uint32_t z2zTransitionEnd = 340000; - bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; - uint32_t nHeight = chainActive.Height(); + uint32_t z2zTransitionStart = z2zForkHeight - z2zTransitionWindow; + uint32_t nHeight = chainActive.Height(); // This only applies to HUSH3, other chains can start off z2z via ac_private=1 if(ishush3) { - if((nHeight >= z2zTransitionStart) || (nHeight <= z2zTransitionEnd)) { + if((nHeight >= z2zTransitionStart) || (nHeight <= z2zForkHeight)) { // During the z2z transition window, only coinbase tx's as part of blocks are allowed // Theory: We want an empty mempool at our fork block height, and the only way to assure that // is to have an empty mempool for a few previous blocks, to take care of potential re-orgs @@ -3371,7 +3371,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; if(!ASSETCHAINS_PRIVATE && ishush3) { - unsigned int z2zForkHeight = 340000; unsigned int nHeight = pindex->GetHeight(); if(nHeight >= z2zForkHeight) { // At startup, HUSH3 doesn't know a block height yet and so we must wait until @@ -6338,6 +6337,13 @@ bool static LoadBlockIndexDB() chainActive.SetTip(it->second); + // Try to detect if we are z2z based on height of blocks on disk + // This helps to set it correctly on startup before a new block is connected + if(ishush3 && chainActive.Height() >= z2zForkHeight) { + LogPrintf("%s: enabled ac_private=1 at height=%d\n", __func__, chainActive.Height()); + ASSETCHAINS_PRIVATE = 1; + } + // Set hashFinalSproutRoot for the end of best chain it->second->hashFinalSproutRoot = pcoinsTip->GetBestAnchor(SPROUT); From 2bfc18b26d1485dc8d6d3ac1da60a6d9af3ef11a Mon Sep 17 00:00:00 2001 From: Charles <18726788+csharpee@users.noreply.github.com> Date: Thu, 16 Apr 2020 16:48:58 -0400 Subject: [PATCH 08/98] Fix package dep for ccache xz to gz compression algo. --- depends/packages/native_ccache.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk index b3693cc6f..64fee77ba 100644 --- a/depends/packages/native_ccache.mk +++ b/depends/packages/native_ccache.mk @@ -1,8 +1,8 @@ package=native_ccache -$(package)_version=3.7.7 +$(package)_version=3.7.9 $(package)_download_path=https://github.com/ccache/ccache/releases/download/v$($(package)_version) -$(package)_file_name=ccache-$($(package)_version).tar.xz -$(package)_sha256_hash=b7c1d6d6fe42f18e424de92746af863e0bc85794da3d69e44300840c478c98cd +$(package)_file_name=ccache-$($(package)_version).tar.gz +$(package)_sha256_hash=92838e2133c9e704fdab9ee2608dad86c99021278b9ac47d065aa8ff2ea8ce36 define $(package)_set_vars $(package)_config_opts= From 1009c7933de1d284e83afc139a599b0efd1785cf Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 16 Apr 2020 22:10:25 -0400 Subject: [PATCH 09/98] CLI arg -z2zforkheight and avoid a compiler warning --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 472a8bb90..e1beb5c5d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,7 +115,7 @@ bool fAlerts = DEFAULT_ALERTS; */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; -unsigned int z2zForkHeight = 340000; +unsigned int z2zForkHeight = GetArg("-z2zforkheight",340000); unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; @@ -1329,7 +1329,7 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde )) { librustzcash_sapling_verification_ctx_free(ctx); - fprintf(stderr,"%s: Invalid sapling binding sig! tx=%s valueBalance=%li, bindingSig.size=%d\n", __func__, tx.GetHash().ToString().c_str(), tx.valueBalance, tx.bindingSig.size() ); + fprintf(stderr,"%s: Invalid sapling binding sig! tx=%s valueBalance=%li, bindingSig.size=%li\n", __func__, tx.GetHash().ToString().c_str(), tx.valueBalance, tx.bindingSig.size() ); return state.DoS(100, error("ContextualCheckTransaction(): Sapling binding signature invalid"), REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid"); } From b3c7e048ab583556e79bd5651abc49b443227740 Mon Sep 17 00:00:00 2001 From: DenioD <41270280+DenioD@users.noreply.github.com> Date: Sat, 25 Apr 2020 00:30:06 +0200 Subject: [PATCH 10/98] add z_getnotescount as rpc call ported for Hush from https://github.com/zcash/zcash/pull/4465 --- src/rpc/client.cpp | 1 + src/wallet/rpcwallet.cpp | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 4107ad6f8..79011da34 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -139,6 +139,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "z_listunspent", 2 }, { "z_listunspent", 3 }, { "z_getbalance", 1}, + { "z_getnotescount", 0}, { "z_gettotalbalance", 0}, { "z_gettotalbalance", 1}, { "z_gettotalbalance", 2}, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b8115767a..5afd0c4e8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4213,6 +4213,42 @@ UniValue z_getbalance(const UniValue& params, bool fHelp, const CPubKey& mypk) return ValueFromAmount(nBalance); } +UniValue z_getnotescount(const UniValue& params, bool fHelp,const CPubKey& mypk) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() > 1) + throw runtime_error( + "z_getnotescount\n" + "\nArguments:\n" + "1. minconf (numeric, optional, default=1) Only include notes in transactions confirmed at least this many times.\n" + "\nReturns the number of sprout and sapling notes available in the wallet.\n" + "\nResult:\n" + "{\n" + " \"sapling\" (numeric) the number of sapling notes in the wallet\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("z_getnotescount", "0") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + + int nMinDepth = 1; + if (params.size() > 0) + nMinDepth = params[0].get_int(); + + int sapling = 0; + for (auto& wtx : pwalletMain->mapWallet) { + if (wtx.second.GetDepthInMainChain() >= nMinDepth) { + sapling += wtx.second.mapSaplingNoteData.size(); + } + } + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("sapling", sapling)); + + return ret; +} UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& mypk) { @@ -8368,6 +8404,7 @@ static const CRPCCommand commands[] = { "wallet", "z_getinfo", &z_getinfo, true }, { "wallet", "z_listsentbyaddress", &z_listsentbyaddress, true }, { "wallet", "z_listreceivedbyaddress", &z_listreceivedbyaddress, true }, + { "wallet", "z_getnotescount", &z_getnotescount, false }, // TODO: rearrange into another category { "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true }, { "disclosure", "z_validatepaymentdisclosure", &z_validatepaymentdisclosure, true } From ed0385b52465bbde771408e83441c7a600dc06f3 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 30 Apr 2020 06:51:54 -0400 Subject: [PATCH 11/98] Initial merge of subatomic dapp from KMD upstream from dev branch of https://github.com/jl777/komodo/ commit d75041c478bcd721d44be0ab9af45c3d2ba2f69b --- src/cc/dapps/subatomic.c | 1429 +++++++++++++++++++++++++++++++++++ src/cc/dapps/subatomic.json | 26 + 2 files changed, 1455 insertions(+) create mode 100644 src/cc/dapps/subatomic.c create mode 100644 src/cc/dapps/subatomic.json diff --git a/src/cc/dapps/subatomic.c b/src/cc/dapps/subatomic.c new file mode 100644 index 000000000..2f6ebf824 --- /dev/null +++ b/src/cc/dapps/subatomic.c @@ -0,0 +1,1429 @@ +/****************************************************************************** + * Copyright © 2014-2020 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +// build subatomic and put in path: git pull; gcc cc/dapps/subatomic.c -lm -o subatomic; cp subatomic /usr/bin +// alice sends relcoin and gets basecoin + +#define DEXP2P_CHAIN ((char *)"DEX") +#define DEXP2P_PUBKEYS ((char *)"subatomic") +#include "dappinc.h" + +// for OTC mode, the following 4 functions are the only ones that should be needed to support a new "coin" +//int64_t subatomic_getbalance(char *coin); +//bits256 subatomic_coinpayment(int32_t OTCmode,char *coin,char *destaddr,uint64_t paytoshis,char *memostr); +//cJSON *subatomic_txidwait(char *coin,bits256 txid,char *hexstr,int32_t numseconds); +//int64_t subatomic_verifypayment(char *coin,cJSON *rawtx,uint64_t destsatoshis,char *destaddr); + +// TODO: +// address conversion +// new inventory types: +// anonsend + +// bob nodes: +// mutex for bob instances +// "deposits" messages and approved bobs +// volume caps per coin and non-notarized exposure + +// later: +// sharded storage + +#define SUBATOMIC_OTCDEFAULT 1 +#define SUBATOMIC_TIMEOUT 60 +#define SUBATOMIC_LOCKTIME 3600 +#define SUBATOMIC_TXFEE 10000 + +#define SUBATOMIC_PRIORITY 5 + +#define SUBATOMIC_OPENREQUEST 1 +#define SUBATOMIC_APPROVED 2 +#define SUBATOMIC_OPENED 3 +#define SUBATOMIC_PAYMENT 4 +#define SUBATOMIC_PAIDINFULL 5 +#define SUBATOMIC_CLOSED 6 + +cJSON *SUBATOMIC_json; +int32_t SUBATOMIC_retval = -1; + +struct abinfo +{ + char pubkey[67],recvaddr[64],recvZaddr[128],secp[67]; +}; + +struct coininfo +{ + uint64_t satoshis,txfee,maxamount; + char istoken,iszaddr,isfile,isexternal,tokenid[65],coin[16],name[16],cli[256],acname[16],coinstr[16]; +}; + +struct msginfo +{ + UT_hash_handle hh; + bits256 bobpayment,alicepayment; + double price; + uint64_t gotpayment; + uint32_t origid,openrequestid,approvalid,openedid,paymentids[100],paidid,closedid,locktime; + int32_t bobflag,status,OTCmode; + char payload[128],approval[128],senderpub[67],msigaddr[64],redeemscript[256]; + struct coininfo base,rel; + struct abinfo alice,bob; +} *Messages; + +uint64_t subatomic_txfee(char *coin) +{ + return(SUBATOMIC_TXFEE); +} + +char *subatomic_checkname(char *tmpstr,struct msginfo *mp,int32_t baserel,char *coin) +{ + int32_t i,n; cJSON *external,*item; char *coinstr,*clistr; struct coininfo *ptr; + ptr = (baserel == 0) ? &mp->base : &mp->rel; + if ( coin[0] == 0 ) + return(coin); + if ( (external= jarray(&n,SUBATOMIC_json,"externalcoins")) != 0 && n > 0 ) + { + for (i=0; icli) ) + { + ptr->isexternal = 1; + strcpy(ptr->cli,clistr); + //fprintf(stderr,"found external coin %s %s\n",coin,clistr); + } + } + } + if ( coin[0] == '#' ) + { + strcpy(ptr->coinstr,coin); + strcpy(ptr->acname,""); + ptr->isfile = 1; + return(coin); + } + else if ( coin[0] != 'z' ) + { + for (i=1; coin[i]!=0; i++) + if ( coin[i] == '.' ) + { + dpow_tokenregister(ptr->tokenid,0,coin,0); + if ( ptr->tokenid[0] != 0 ) + { + strcpy(tmpstr,coin); + tmpstr[i] = 0; + //fprintf(stderr,"found a tokenmap %s -> %s %s\n",coin,tmpstr,ptr->tokenid); + ptr->istoken = 1; + strcpy(ptr->acname,coin); + strcpy(ptr->coinstr,""); + return(tmpstr); + } + } + if ( ptr->isexternal == 0 ) + { + if ( strcmp(coin,"KMD") != 0 ) + { + strcpy(ptr->acname,coin); + strcpy(ptr->coinstr,""); + } + else + { + strcpy(ptr->coinstr,coin); + strcpy(ptr->acname,""); + } + } + else + { + strcpy(ptr->coinstr,coin); + strcpy(ptr->acname,""); + } + return(coin); + } + else + { + for (i=1; coin[i]!=0; i++) + if ( isupper(coin[i]) == 0 ) + return(coin); + if ( strcmp(coin+1,"KMD") != 0 ) + ptr->iszaddr = 1; + return(coin+1); + } +} + +int32_t subatomic_zonly(struct coininfo *coin) +{ + if ( strcmp(coin->coin,"PIRATE") == 0 ) + return(1); + else return(coin->iszaddr); +} + +// //////////////////////////////// the four key functions needed to support a new item for subatomics + +int64_t _subatomic_getbalance(struct coininfo *coin) +{ + cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0; + if ( (retjson= subatomic_cli(coin->cli,&retstr,"getbalance","","","","","","","")) != 0 ) + { + fprintf(stderr,"_subatomic_getbalance.(%s) %s returned json!\n",coin->coinstr,coin->cli); + free_json(retjson); + } + else if ( retstr != 0 ) + { + amount = atof(retstr) * SATOSHIDEN; + sprintf(cmpstr,"%.8f",dstr(amount)); + if ( strcmp(retstr,cmpstr) != 0 ) + amount++; + //printf("retstr %s -> %.8f\n",retstr,dstr(amount)); + free(retstr); + } + return (amount); +} + +bits256 _subatomic_sendtoaddress(struct coininfo *coin,char *destaddr,int64_t satoshis) +{ + char numstr[32],*retstr,str[65]; cJSON *retjson; bits256 txid; + memset(txid.bytes,0,sizeof(txid)); + sprintf(numstr,"%.8f",(double)satoshis/SATOSHIDEN); + if ( (retjson= subatomic_cli(coin->cli,&retstr,"sendtoaddress",destaddr,numstr,"false","","","","")) != 0 ) + { + fprintf(stderr,"unexpected _subatomic_sendtoaddress json.(%s)\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + if ( strlen(retstr) >= 64 ) + { + retstr[64] = 0; + decode_hex(txid.bytes,32,retstr); + } + fprintf(stderr,"_subatomic_sendtoaddress %s %.8f txid.(%s)\n",destaddr,(double)satoshis/SATOSHIDEN,bits256_str(str,txid)); + free(retstr); + } + return(txid); +} + +cJSON *_subatomic_rawtransaction(struct coininfo *coin,bits256 txid) +{ + cJSON *retjson; char *retstr,str[65]; + if ( (retjson= subatomic_cli(coin->cli,&retstr,"getrawtransaction",bits256_str(str,txid),"1","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"_subatomic_rawtransaction.(%s) %s error.(%s)\n",coin->coin,coin->name,retstr); + free(retstr); + } + return(0); +} + +int64_t subatomic_getbalance(struct coininfo *coin) +{ + char *coinstr,*acname=""; FILE *fp; int64_t retval = 0; + if ( strcmp(coin->coin,"KMD") != 0 ) + { + acname = coin->coin; + coinstr = ""; + } else coinstr = coin->coin; + if ( coin->isfile != 0 ) + { + if ( (fp= fopen(coin->name+1,"rb")) != 0 ) // if alice, add bob pubkey to fname + { + fclose(fp); + retval = SATOSHIDEN; + } + return(retval); + } + else if ( subatomic_zonly(coin) != 0 ) + return(z_getbalance(coinstr,acname,DPOW_recvZaddr)); + else + { + if ( coin->istoken != 0 ) + { + if ( get_getbalance(coinstr,acname) < SUBATOMIC_TXFEE ) + { + fprintf(stderr,"not enough balance to send token\n"); + return(0); + } + //fprintf(stderr,"token balance %s\n",coin->tokenid); + return(get_tokenbalance(coinstr,acname,coin->tokenid) * SATOSHIDEN); + } + else if ( coin->isexternal == 0 ) + return(get_getbalance(coinstr,acname)); + else return(_subatomic_getbalance(coin)); + } +} + +bits256 subatomic_coinpayment(uint32_t origid,int32_t OTCmode,struct coininfo *coin,char *destaddr,uint64_t paytoshis,char *memostr,char *destpub,char *senderpub) +{ + bits256 txid; char opidstr[128],opretstr[32],str[65],*status,*coinstr,*acname=""; cJSON *retjson,*retjson2,*item,*res; int32_t i,pending=0; + memset(&txid,0,sizeof(txid)); + if ( OTCmode == 0 ) + { + fprintf(stderr,"micropayment channels are not supported yet\n"); + return(txid); + } + if ( coin->isfile != 0 ) + { + fprintf(stderr,"start broadcast of (%s)\n",coin->coin+1); + if ( (retjson= dpow_publish(SUBATOMIC_PRIORITY,coin->coin+1)) != 0 ) // spawn thread + { + sprintf(opretstr,"%08x",juint(retjson,"id")); + sprintf(opidstr,"%u",origid); + if ( (retjson2= dpow_broadcast(SUBATOMIC_PRIORITY,opretstr,"inbox",opidstr,senderpub,"","")) != 0 ) + free_json(retjson2); + fprintf(stderr,"broadcast file.(%s) and send id.%u to alice (%s)\n",coin->coin+1,juint(retjson,"id"),jprint(retjson,0)); + txid = jbits256(retjson,"filehash"); + free_json(retjson); + } + fprintf(stderr,"end broadcast of (%s) to %s\n",coin->coin+1,senderpub); + return(txid); + } + else if ( subatomic_zonly(coin) != 0 ) + { + if ( memostr[0] == 0 ) + memostr = "beef"; + z_sendmany(opidstr,"",coin->coin,DPOW_recvZaddr,destaddr,paytoshis,memostr); + for (i=0; icoin,opidstr)) != 0 ) + { + item = jitem(retjson,0); + if ( (status= jstr(item,"status")) != 0 ) + { + if ( strcmp(status,"executing") == 0 ) + pending++; + else + { + res = jobj(item,"result"); + txid = jbits256(res,"txid"); + //fprintf(stderr,"got Ztx txid.%s\n",bits256_str(str,txid)); + free_json(retjson); + break; + } + /*else if ( clearresults != 0 ) + { + if ( (result= z_getoperationresult(coinstr,"",jstri(array,i))) != 0 ) + { + free_json(result); + } + }*/ + } + free_json(retjson); + } + sleep(1); + } + if ( i == 60 ) + printf("%u timed out waiting for opid to finish\n",origid); + } + else + { + if ( strcmp(coin->coin,"KMD") != 0 ) + { + acname = coin->coin; + coinstr = ""; + } else coinstr = coin->coin; + if ( coin->istoken != 0 ) + txid = tokentransfer(coinstr,acname,coin->tokenid,destpub,paytoshis/SATOSHIDEN); + else if ( coin->isexternal == 0 ) + { + sprintf(opretstr,"%08x",origid); + txid = sendtoaddress(coinstr,acname,destaddr,paytoshis,opretstr); + } else txid = _subatomic_sendtoaddress(coin,destaddr,paytoshis); + printf("%u got txid.%s\n",origid,bits256_str(str,txid)); + } + return(txid); +} + +cJSON *subatomic_txidwait(struct coininfo *coin,bits256 txid,char *hexstr,int32_t numseconds,char *senderpub) +{ + int32_t i,zflag; char *coinstr,str[65],*acname=""; cJSON *rawtx; bits256 z; bits256 filehash; + memset(&z,0,sizeof(z)); + if ( memcmp(&z,&txid,sizeof(txid)) == 0 ) + return(0); + if ( hexstr != 0 && hexstr[0] != 0 ) // probably not worth doing and zaddr is a problem to decode + { + // compare against txid + // if matches, sendrawtransaction if OTC mode, decoode and return if channels mode + } + zflag = (subatomic_zonly(coin) != 0); + if ( strcmp(coin->coin,"KMD") != 0 ) + { + acname = coin->coin; + coinstr = ""; + } else coinstr = coin->coin; + for (i=0; iisfile != 0 ) + { + if ( (rawtx= dpow_subscribe(SUBATOMIC_PRIORITY,coin->coin+1,senderpub)) != 0 ) + { + filehash = jbits256(rawtx,"filehash"); + if ( memcmp(&filehash,&txid,sizeof(filehash)) != 0 ) + { + fprintf(stderr,"waiting (%s) (%s)\n",coin->coin+1,jprint(rawtx,0)); + free_json(rawtx); + rawtx = 0; + } else return(rawtx); + } + } + else if ( zflag != 0 ) + rawtx = get_z_viewtransaction(coinstr,acname,txid); + else if ( coin->isexternal == 0 ) + rawtx = get_rawtransaction(coinstr,acname,txid); + else rawtx = _subatomic_rawtransaction(coin,txid); + if ( rawtx != 0 ) + return(rawtx); + sleep(1); + } + printf("%s/%s timeout waiting for %s\n",coin->name,coin->coin,bits256_str(str,txid)); + return(0); +} + +int64_t subatomic_verifypayment(struct coininfo *coin,cJSON *rawtx,uint64_t destsatoshis,char *destaddr,bits256 txid) +{ + int32_t i,n,m,valid=0; bits256 tokenid,filehash,checkhash; cJSON *array,*item,*sobj,*a; char *addr,*acname,*coinstr,tokenaddr[64],*hex; uint8_t hexbuf[512],pub33[33]; uint64_t netval,recvsatoshis = 0; + if ( coin->isfile != 0 ) + { + filehash = jbits256(rawtx,"filehash"); + checkhash = jbits256(rawtx,"checkhash"); + if ( memcmp(&txid,&filehash,sizeof(txid)) == 0 && memcmp(&txid,&checkhash,sizeof(txid)) == 0 ) + { + fprintf(stderr,"verified file is matching the filehash (%s)\n",jprint(rawtx,0)); + return(SATOSHIDEN); + } else return(0); + } + else if ( subatomic_zonly(coin) != 0 ) + { + if ( (array= jarray(&n,rawtx,"outputs")) != 0 && n > 0 ) + { + for (i=0; iistoken != 0 ) + { + if ( (array= jarray(&n,rawtx,"vout")) != 0 && n > 0 ) + { + item = jitem(array,0); + if ( (sobj= jobj(item,"scriptPubKey")) != 0 && (a= jarray(&m,sobj,"addresses")) != 0 && m == 1 ) + { + if ( strcmp(coin->coin,"KMD") != 0 ) + { + acname = coin->coin; + coinstr = ""; + } else coinstr = coin->coin; + if ( get_tokenaddress(coinstr,acname,tokenaddr) != 0 ) + { + //fprintf(stderr,"tokenaddr.%s\n",tokenaddr); + if ( (addr= jstri(a,0)) != 0 && strcmp(addr,tokenaddr) == 0 ) + recvsatoshis += SATOSHIDEN * (uint64_t)(jdouble(item,"value")*SATOSHIDEN + 0.000000004999); + else fprintf(stderr,"miscompare (%s) vs %s\n",jprint(sobj,0),addr); + } + } + item = jitem(array,n-1); + if ( (sobj= jobj(item,"scriptPubKey")) != 0 && (hex= jstr(sobj,"hex")) != 0 && (m= is_hexstr(hex,0)) > 1 && m/2 < sizeof(hexbuf) ) + { + m >>= 1; + decode_hex(hexbuf,m,hex); + decode_hex(tokenid.bytes,32,coin->tokenid); + decode_hex(pub33,33,DPOW_secpkeystr); + // opret 69len EVAL_TOKENS 't' tokenid 1 33 pub33 + if ( hexbuf[0] == 0x6a && hexbuf[1] == 0x45 && hexbuf[2] == 0xf2 && hexbuf[3] == 't' && memcmp(&hexbuf[4],&tokenid,sizeof(tokenid)) == 0 && hexbuf[4+32] == 1 && hexbuf[4+32+1] == 33 && memcmp(&hexbuf[4+32+2],pub33,33) == 0 ) + { + valid = 1; + //fprintf(stderr,"validated it is a token transfer!\n"); + } else fprintf(stderr,"need to validate tokentransfer.(%s) %s %d\n",hex,DPOW_secpkeystr,memcmp(&hexbuf[4+32+2],pub33,33) == 0); + //6a 45 f2 74 2b1feef719ecb526b07416dd432bce603ac6dc8bfe794cddf105cb52f6aae3cd 01 21 02b27de3ee5335518b06f69f4fbabb029cfc737613b100996841d5532b324a5a61 + + } + recvsatoshis *= valid; + } + } + else + { + if ( (array= jarray(&n,rawtx,"vout")) != 0 && n > 0 ) + { + for (i=0; iorigid = origid; + HASH_ADD(hh,Messages,origid,sizeof(origid),mp); + return(mp); +} + +int32_t subatomic_status(struct msginfo *mp,int32_t status) +{ + static FILE *fp; + if ( fp == 0 ) + { + int32_t i,oid,s,n,num,count; struct msginfo *m; long fsize; + if ( (fp= fopen("SUBATOMIC.DB","rb+")) == 0 ) + { + if ( (fp= fopen("SUBATOMIC.DB","wb")) == 0 ) + { + fprintf(stderr,"cant create SUBATOMIC.DB\n"); + exit(-1); + } + } + else + { + fseek(fp,0,SEEK_END); + fsize = ftell(fp); + if ( (fsize % (sizeof(uint32_t)*2)) != 0 ) + { + fprintf(stderr,"SUBATOMIC.DB illegal filesize.%ld\n",fsize); + exit(-1); + } + n = (int32_t)(fsize / (sizeof(uint32_t)*2)); + rewind(fp); + for (i=num=count=0; i SUBATOMIC_CLOSED ) + { + fprintf(stderr,"SUBATOMIC.DB corrupted at filepos.%ld: illegal status.%d\n",ftell(fp),s); + exit(-1); + } + //fprintf(stderr,"%u <- %d\n",oid,s); + if ( (m= subatomic_find(oid)) == 0 ) + { + m = subatomic_add(oid); + count++; + } + if ( s > m->status ) + { + m->status = s; + num++; + } + } + fprintf(stderr,"initialized %d messages, updated %d out of total.%d\n",count,num,n); + } + } + if ( mp->status >= status ) + return(-1); + if ( fwrite(&mp->origid,1,sizeof(mp->origid),fp) != sizeof(mp->origid) || fwrite(&status,1,sizeof(status),fp) != sizeof(status) ) + fprintf(stderr,"error updating SUBATOMIC.DB, risk of double spends\n"); + fflush(fp); + mp->status = status; + return(0); +} + +struct msginfo *subatomic_tracker(uint32_t origid) +{ + struct msginfo *mp; + if ( (mp= subatomic_find(origid)) == 0 ) + { + mp = subatomic_add(origid); + subatomic_status(mp,0); + } + return(mp); +} + +char *subatomic_hexstr(char *jsonstr) +{ + char *hexstr; int32_t i,c,n = (int32_t)strlen(jsonstr); + hexstr = malloc(2*n + 3); + strcpy(hexstr,jsonstr); + for (i=0; iorigid); + jaddnum(item,"price",mp->price); + jaddnum(item,"openrequest",mp->openrequestid); + jaddstr(item,"base",mp->base.name); + jaddstr(item,"basecoin",mp->base.coin); + jadd64bits(item,"basesatoshis",mp->base.satoshis); + jadd64bits(item,"basetxfee",mp->base.txfee); + jadd64bits(item,"maxbaseamount",mp->base.maxamount); + jaddstr(item,"rel",mp->rel.name); + jaddstr(item,"relcoin",mp->rel.coin); + jadd64bits(item,"relsatoshis",mp->rel.satoshis); + jadd64bits(item,"reltxfee",mp->rel.txfee); + jadd64bits(item,"maxrelamount",mp->rel.maxamount); + jaddstr(item,"alice",mp->alice.pubkey); + jaddstr(item,"alicesecp",mp->alice.secp); + jaddstr(item,"bob",mp->bob.pubkey); + jaddstr(item,"bobsecp",mp->bob.secp); + if ( subatomic_zonly(&mp->rel) != 0 ) + jaddstr(item,"bobZaddr",mp->bob.recvZaddr); + else jaddstr(item,"bobaddr",mp->bob.recvaddr); + if ( mp->rel.istoken != 0 ) + jaddstr(item,"bobtoken",mp->rel.tokenid); + if ( subatomic_zonly(&mp->base) != 0 ) + jaddstr(item,"aliceZaddr",mp->alice.recvZaddr); + else jaddstr(item,"aliceaddr",mp->alice.recvaddr); + if ( mp->base.istoken != 0 ) + jaddstr(item,"alicetoken",mp->base.tokenid); + return(item); +} + +uint64_t subatomic_orderbook_mpset(struct msginfo *mp,char *basecheck) +{ + cJSON *retjson; char *tagA,*tagB,*senderpub,*str,tmpstr[32]; int32_t matches=0; double volA,volB; int64_t txfee=0; + strcpy(mp->base.name,basecheck); + strcpy(mp->base.coin,subatomic_checkname(tmpstr,mp,0,basecheck)); + mp->rel.txfee = subatomic_txfee(mp->rel.coin); + if ( (retjson= dpow_get(mp->origid)) != 0 ) + { + //fprintf(stderr,"dpow_get.(%s) (%s/%s)\n",jprint(retjson,0),mp->base.coin,mp->rel.coin); + if ( (senderpub= jstr(retjson,"senderpub")) != 0 && is_hexstr(senderpub,0) == 66 && (tagA= jstr(retjson,"tagA")) != 0 && (tagB= jstr(retjson,"tagB")) != 0 && strncmp(tagB,mp->rel.name,strlen(mp->rel.name)) == 0 && strlen(tagA) < sizeof(mp->base.name) ) + { + strcpy(mp->base.name,tagA); + strcpy(mp->base.coin,subatomic_checkname(tmpstr,mp,0,tagA)); + if ( basecheck[0] == 0 || strncmp(basecheck,tagA,strlen(basecheck)) == 0 ) + matches = 1; + else if ( strcmp(tagA,mp->base.name) == 0 ) + matches = 1; + else if ( mp->bobflag != 0 && tagA[0] == '#' && strcmp(mp->base.name,"#allfiles") == 0 ) + matches = 1; + if ( matches != 0 ) + { + if ( (str= jstr(retjson,"decrypted")) != 0 && strlen(str) < 128 ) + strcpy(mp->payload,str); + mp->locktime = juint(retjson,"timestamp") + SUBATOMIC_LOCKTIME; + mp->base.txfee = subatomic_txfee(mp->base.coin); + strcpy(mp->senderpub,senderpub); + volB = jdouble(retjson,"amountB"); + volA = jdouble(retjson,"amountA"); + mp->base.maxamount = volA*SATOSHIDEN + 0.0000000049999; + mp->rel.maxamount = volB*SATOSHIDEN + 0.0000000049999; + if ( 0 && mp->rel.istoken == 0 ) + txfee = mp->rel.txfee; + if ( mp->base.maxamount != 0 && mp->rel.maxamount != 0 && volA > SMALLVAL && volB > SMALLVAL && mp->rel.satoshis <= mp->rel.maxamount ) + { + mp->price = volA / volB; + mp->base.satoshis = (mp->rel.satoshis - txfee) * mp->price; + //fprintf(stderr,"base satoshis.%llu\n",(long long)mp->base.satoshis); + } else fprintf(stderr,"%u rel %llu vs (%llu %llu)\n",mp->origid,(long long)mp->rel.satoshis,(long long)mp->base.maxamount,(long long)mp->rel.maxamount); + } else printf("%u didnt match (%s) tagA.%s %s, tagB.%s %s %d %d\n",mp->origid,basecheck,tagA,mp->base.name,tagB,mp->rel.name,tagA[0] == '#', strcmp(mp->base.name,"#allfiles") == 0); + } else printf("%u didnt compare tagA.%s %s, tagB.%s %s\n",mp->origid,tagA,mp->base.name,tagB,mp->rel.name); + free_json(retjson); + } + return(mp->base.satoshis); +} + +char *randhashstr(char *str) +{ + bits256 rands; int32_t i; + for (i=0; i<32; i++) + rands.bytes[i] = rand() >> 17; + bits256_str(str,rands); + return(str); +} + +void subatomic_extrafields(cJSON *dest,cJSON *src) +{ + char *str; + if ( (str= jstr(src,"approval")) != 0 ) + jaddstr(dest,"approval",str); + if ( (str= jstr(src,"opened")) != 0 ) + jaddstr(dest,"opened",str); + if ( (str= jstr(src,"payamount")) != 0 ) + jaddstr(dest,"payamount",str); + if ( (str= jstr(src,"destaddr")) != 0 ) + jaddstr(dest,"destaddr",str); + if ( (str= jstr(src,"bobpayment")) != 0 ) + jaddstr(dest,"bobpayment",str); + if ( (str= jstr(src,"alicepayment")) != 0 ) + jaddstr(dest,"alicepayment",str); + if ( (str= jstr(src,"bobaddr")) != 0 ) + jaddstr(dest,"bobaddr",str); + if ( (str= jstr(src,"bobZaddr")) != 0 ) + jaddstr(dest,"bobZaddr",str); + if ( (str= jstr(src,"aliceaddr")) != 0 ) + jaddstr(dest,"aliceaddr",str); + if ( (str= jstr(src,"aliceZaddr")) != 0 ) + jaddstr(dest,"aliceZaddr",str); + if ( (str= jstr(src,"alicetoken")) != 0 ) + jaddstr(dest,"alicetoken",str); + if ( (str= jstr(src,"bobtoken")) != 0 ) + jaddstr(dest,"bobtoken",str); +} + +char *subatomic_submit(cJSON *argjson,int32_t tobob) +{ + char *jsonstr,*hexstr; + jaddnum(argjson,"tobob",tobob != 0); + jsonstr = jprint(argjson,1); + hexstr = subatomic_hexstr(jsonstr); + free(jsonstr); + return(hexstr); +} + +#define SCRIPT_OP_IF 0x63 +#define SCRIPT_OP_ELSE 0x67 +#define SCRIPT_OP_DUP 0x76 +#define SCRIPT_OP_ENDIF 0x68 +#define SCRIPT_OP_TRUE 0x51 +#define SCRIPT_OP_2 0x52 +#define SCRIPT_OP_3 0x53 +#define SCRIPT_OP_DROP 0x75 +#define SCRIPT_OP_EQUALVERIFY 0x88 +#define SCRIPT_OP_HASH160 0xa9 +#define SCRIPT_OP_EQUAL 0x87 +#define SCRIPT_OP_CHECKSIG 0xac +#define SCRIPT_OP_CHECKMULTISIG 0xae +#define SCRIPT_OP_CHECKMULTISIGVERIFY 0xaf +#define SCRIPT_OP_CHECKLOCKTIMEVERIFY 0xb1 + +int32_t subatomic_redeemscript(char *redeemscript,uint32_t locktime,char *pubkeyA,char *pubkeyB) // not needed +{ + // if ( refund ) OP_HASH160 <2of2 multisig hash> OP_EQUAL // standard multisig + // else CLTV OP_DROP OP_CHECKSIG // standard spend + uint8_t pubkeyAbytes[33],pubkeyBbytes[33],hex[4096]; int32_t i,n = 0; + decode_hex(pubkeyAbytes,33,pubkeyA); + decode_hex(pubkeyBbytes,33,pubkeyB); + hex[n++] = SCRIPT_OP_IF; + hex[n++] = SCRIPT_OP_2; + hex[n++] = 33, memcpy(&hex[n],pubkeyAbytes,33), n += 33; + hex[n++] = 33, memcpy(&hex[n],pubkeyBbytes,33), n += 33; + hex[n++] = SCRIPT_OP_2; + hex[n++] = SCRIPT_OP_CHECKMULTISIG; + hex[n++] = SCRIPT_OP_ELSE; + hex[n++] = 4; + hex[n++] = locktime & 0xff, locktime >>= 8; + hex[n++] = locktime & 0xff, locktime >>= 8; + hex[n++] = locktime & 0xff, locktime >>= 8; + hex[n++] = locktime & 0xff; + hex[n++] = SCRIPT_OP_CHECKLOCKTIMEVERIFY; + hex[n++] = SCRIPT_OP_DROP; + hex[n++] = 33; memcpy(&hex[n],pubkeyAbytes,33); n += 33; + hex[n++] = SCRIPT_OP_CHECKSIG; + hex[n++] = SCRIPT_OP_ENDIF; + for (i=0; i>4) & 0xf); + redeemscript[i*2 + 1] = hexbyte(hex[i] & 0xf); + } + redeemscript[n*2] = 0; + /*tmpbuf[0] = SCRIPT_OP_HASH160; + tmpbuf[1] = 20; + calc_OP_HASH160(scriptPubKey,tmpbuf+2,redeemscript); + tmpbuf[22] = SCRIPT_OP_EQUAL; + init_hexbytes_noT(scriptPubKey,tmpbuf,23); + if ( p2shaddr != 0 ) + { + p2shaddr[0] = 0; + if ( (btc_addr= base58_encode_check(addrtype,true,tmpbuf+2,20)) != 0 ) + { + if ( strlen(btc_addr->str) < 36 ) + strcpy(p2shaddr,btc_addr->str); + cstr_free(btc_addr,true); + } + }*/ + return(n); +} + +int32_t subatomic_approved(struct msginfo *mp,cJSON *approval,cJSON *msgjson,char *senderpub) +{ + char *hexstr,numstr[32],redeemscript[1024],*coin,*acname=""; cJSON *retjson,*decodejson; int32_t i,retval = 0; + subatomic_extrafields(approval,msgjson); + if ( mp->OTCmode == 0 ) + { + coin = (mp->bobflag != 0) ? mp->base.coin : mp->rel.coin; // the other side gets this coin + if ( strcmp(coin,"KMD") != 0 ) + { + acname = coin; + coin = ""; + } + if ( get_createmultisig2(coin,acname,mp->msigaddr,mp->redeemscript,mp->alice.secp,mp->bob.secp) != 0 ) + { + subatomic_redeemscript(redeemscript,mp->locktime,mp->alice.secp,mp->bob.secp); + if ( (decodejson= get_decodescript(coin,acname,redeemscript)) != 0 ) + { + fprintf(stderr,"%s %s msigaddr.%s %s -> %s %s\n",mp->bobflag!=0?"bob":"alice",(mp->bobflag != 0) ? mp->base.coin : mp->rel.coin,mp->msigaddr,mp->redeemscript,redeemscript,jprint(decodejson,0)); + free(decodejson); + } + } + } + sprintf(numstr,"%u",mp->origid); + for (i=0; numstr[i]!=0; i++) + sprintf(&mp->approval[i<<1],"%02x",numstr[i]); + sprintf(&mp->approval[i<<1],"%02x",' '); + i++; + mp->approval[i<<1] = 0; + jaddstr(approval,"approval",mp->approval); + hexstr = subatomic_submit(approval,!mp->bobflag); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"approved",senderpub,"","")) != 0 ) + { + if ( (mp->approvalid= juint(retjson,"id")) != 0 ) + retval = 1; + printf("%u approvalid.%u (%s)\n",mp->origid,mp->approvalid,senderpub); + subatomic_status(mp,SUBATOMIC_APPROVED); + free_json(retjson); + } + free(hexstr); + return(retval); +} + +int32_t subatomic_opened(struct msginfo *mp,cJSON *opened,cJSON *msgjson,char *senderpub) +{ + char *hexstr,channelstr[65]; cJSON *retjson; int32_t retval = 0; + subatomic_extrafields(opened,msgjson); + jaddstr(opened,"opened",randhashstr(channelstr)); + hexstr = subatomic_submit(opened,!mp->bobflag); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"opened",senderpub,"","")) != 0 ) + { + if ( (mp->openedid= juint(retjson,"id")) != 0 ) + retval = 1; + printf("%u openedid.%u\n",mp->origid,mp->openedid); + subatomic_status(mp,SUBATOMIC_OPENED); + free_json(retjson); + } + free(hexstr); + return(retval); +} + +int32_t subatomic_payment(struct msginfo *mp,cJSON *payment,cJSON *msgjson,char *senderpub) +{ + bits256 txid; uint64_t paytoshis; cJSON *retjson; char numstr[32],*coin,*dest,*hexstr; int32_t retval = 0; + if ( mp->bobflag == 0 ) + { + coin = mp->rel.name; + paytoshis = mp->rel.satoshis; + if ( subatomic_zonly(&mp->rel) != 0 ) + dest = mp->bob.recvZaddr; + else dest = mp->bob.recvaddr; + sprintf(numstr,"%llu",(long long)paytoshis); + jaddstr(payment,"alicepays",numstr); + jaddstr(payment,"bobdestaddr",dest); + txid = subatomic_coinpayment(mp->origid,mp->OTCmode,&mp->rel,dest,paytoshis,mp->approval,mp->bob.secp,senderpub); + jaddbits256(payment,"alicepayment",txid); + mp->alicepayment = txid; + hexstr = 0; // get it from rawtransaction of txid + jaddstr(payment,"alicetx",hexstr); + } + else + { + coin = mp->base.name; + paytoshis = mp->base.satoshis; + if ( subatomic_zonly(&mp->base) != 0 ) + dest = mp->alice.recvZaddr; + else dest = mp->alice.recvaddr; + sprintf(numstr,"%llu",(long long)paytoshis); + jaddstr(payment,"bobpays",numstr); + jaddstr(payment,"alicedestaddr",dest); + txid = subatomic_coinpayment(mp->origid,mp->OTCmode,&mp->base,dest,paytoshis,mp->approval,mp->alice.secp,senderpub); + jaddbits256(payment,"bobpayment",txid); + mp->bobpayment = txid; + hexstr = 0; // get it from rawtransaction of txid + jaddstr(payment,"bobtx",hexstr); + } + hexstr = subatomic_submit(payment,!mp->bobflag); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"payment",senderpub,"","")) != 0 ) + { + if ( (mp->paymentids[0]= juint(retjson,"id")) != 0 ) + retval = 1; + printf("%u: %.8f %s -> %s, paymentid[0] %u\n",mp->origid,dstr(paytoshis),coin,dest,mp->paymentids[0]); + subatomic_status(mp,SUBATOMIC_PAYMENT); + free_json(retjson); + } + free(hexstr); + return(retval); +} + +int32_t subatomic_paidinfull(struct msginfo *mp,cJSON *paid,cJSON *msgjson,char *senderpub) +{ + char *hexstr; cJSON *retjson; int32_t retval = 0; + jaddstr(paid,"paid","in full"); + subatomic_extrafields(paid,msgjson); + hexstr = subatomic_submit(paid,!mp->bobflag); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"paid",senderpub,"","")) != 0 ) + { + if ( (mp->paidid= juint(retjson,"id")) != 0 ) + retval = 1; + printf("%u paidid.%u\n",mp->origid,mp->paidid); + subatomic_status(mp,SUBATOMIC_PAIDINFULL); + free_json(retjson); + } + free(hexstr); + return(retval); +} + +int32_t subatomic_closed(struct msginfo *mp,cJSON *closed,cJSON *msgjson,char *senderpub) +{ + char *hexstr; cJSON *retjson; int32_t retval = 0; + jaddnum(closed,"closed",mp->origid); + subatomic_extrafields(closed,msgjson); + hexstr = subatomic_submit(closed,!mp->bobflag); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"closed",senderpub,"","")) != 0 ) + { + if ( (mp->closedid= juint(retjson,"id")) != 0 ) + retval = 1; + subatomic_status(mp,SUBATOMIC_CLOSED); + printf("%u closedid.%u\n",mp->origid,mp->closedid); + free_json(retjson); + } + free(hexstr); + return(retval); +} + +uint32_t subatomic_alice_openrequest(struct msginfo *origmp) +{ + struct msginfo *mp; cJSON *retjson,*openrequest; char *hexstr,*str,tmpstr[32]; + mp = subatomic_tracker(origmp->origid); + mp->origid = origmp->origid; + mp->rel.satoshis = origmp->rel.satoshis; + mp->rel.istoken = origmp->rel.istoken; + strcpy(mp->rel.tokenid,origmp->rel.tokenid); + strcpy(mp->rel.name,origmp->rel.name); + strcpy(mp->rel.coin,subatomic_checkname(tmpstr,mp,1,origmp->rel.name)); + strcpy(mp->alice.pubkey,DPOW_pubkeystr); + strcpy(mp->alice.secp,DPOW_secpkeystr); + strcpy(mp->alice.recvZaddr,DPOW_recvZaddr); + strcpy(mp->alice.recvaddr,DPOW_recvaddr); + printf("rel.%s/%s %s openrequest %u status.%d (%s/%s)\n",mp->rel.name,mp->rel.coin,mp->rel.tokenid,mp->origid,mp->status,mp->alice.recvaddr,mp->alice.recvZaddr); + if ( mp->status == 0 && subatomic_orderbook_mpset(mp,"") != 0 ) + { + strcpy(mp->bob.pubkey,mp->senderpub); + if ( subatomic_zonly(&mp->base) != 0 || subatomic_zonly(&mp->rel) != 0 ) + mp->OTCmode = 1; + else mp->OTCmode = SUBATOMIC_OTCDEFAULT; + strcpy(origmp->base.name,mp->base.name); + strcpy(origmp->base.coin,mp->base.coin); + origmp->base.istoken = mp->base.istoken; + strcpy(origmp->base.tokenid,mp->base.tokenid); + origmp->OTCmode = mp->OTCmode; + if ( mp->rel.istoken != 0 && ((mp->rel.satoshis % SATOSHIDEN) != 0 || mp->rel.iszaddr != 0) ) + { + printf("%u cant do zaddr or fractional rel %s.%s tokens %.8f\n",mp->origid,mp->rel.coin,mp->rel.tokenid,dstr(mp->rel.satoshis)); + return(0); + } + else if ( mp->base.istoken != 0 && ((mp->base.satoshis % SATOSHIDEN) != 0 || mp->base.iszaddr != 0 ) ) + { + printf("%u cant do zaddr or fractional base %s.%s tokens %.8f\n",mp->origid,mp->base.coin,mp->base.tokenid,dstr(mp->base.satoshis)); + return(0); + } + else if ( (openrequest= subatomic_mpjson(mp)) != 0 ) + { + hexstr = subatomic_submit(openrequest,!mp->bobflag); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,(char *)"inbox",(char *)"openrequest",mp->bob.pubkey,"","")) != 0 ) + { + mp->openrequestid = juint(retjson,"id"); + printf("%u openrequest.%u -> (%s)\n",mp->origid,mp->openrequestid,mp->bob.pubkey); + subatomic_status(mp,SUBATOMIC_OPENREQUEST); + free_json(retjson); + } + free(hexstr); + } + } + return(mp->openrequestid); +} + +void subatomic_bob_gotopenrequest(uint32_t inboxid,char *senderpub,cJSON *msgjson,char *basename,char *relname) +{ + struct msginfo *mp; cJSON *approval; int32_t origid; char *addr,tmpstr[32],*coin,*acname=""; + origid = juint(msgjson,"origid"); + mp = subatomic_tracker(origid); + strcpy(mp->base.name,basename); + strcpy(mp->base.coin,subatomic_checkname(tmpstr,mp,0,basename)); + strcpy(mp->rel.name,relname); + strcpy(mp->rel.coin,subatomic_checkname(tmpstr,mp,1,relname)); + mp->origid = origid; + mp->rel.satoshis = j64bits(msgjson,"relsatoshis"); + mp->bobflag = 1; + strcpy(mp->bob.pubkey,DPOW_pubkeystr); + strcpy(mp->bob.secp,DPOW_secpkeystr); + strcpy(mp->bob.recvZaddr,DPOW_recvZaddr); + strcpy(mp->bob.recvaddr,DPOW_recvaddr); + if ( (addr= jstr(msgjson,"aliceaddr")) != 0 ) + strcpy(mp->alice.recvaddr,addr); + if ( (addr= jstr(msgjson,"aliceZaddr")) != 0 ) + strcpy(mp->alice.recvZaddr,addr); + if ( (addr= jstr(msgjson,"alicesecp")) != 0 ) + strcpy(mp->alice.secp,addr); + if ( subatomic_zonly(&mp->base) != 0 || subatomic_zonly(&mp->rel) != 0 ) + mp->OTCmode = 1; + else mp->OTCmode = SUBATOMIC_OTCDEFAULT; + printf("%u got open request\n",mp->origid); + if ( mp->status == 0 && subatomic_orderbook_mpset(mp,basename) != 0 && (approval= subatomic_mpjson(mp)) != 0 ) + { + if ( mp->rel.istoken != 0 && ((mp->rel.satoshis % SATOSHIDEN) != 0 || mp->rel.iszaddr != 0) ) + { + printf("%u cant do zaddr or fractional rel %s.%s tokens %.8f\n",mp->origid,mp->rel.coin,mp->rel.tokenid,dstr(mp->rel.satoshis)); + subatomic_closed(mp,approval,msgjson,senderpub); + return; + } + else if ( mp->base.istoken != 0 && ((mp->base.satoshis % SATOSHIDEN) != 0 || mp->base.iszaddr != 0 ) ) + { + printf("%u cant do zaddr or fractional base %s.%s tokens %.8f\n",mp->origid,mp->base.coin,mp->base.tokenid,dstr(mp->base.satoshis)); + subatomic_closed(mp,approval,msgjson,senderpub); + return; + } + else if ( subatomic_getbalance(&mp->base) < mp->base.satoshis ) + { + printf("%u bob node low on %s funds! %.8f not enough for %.8f\n",mp->origid,mp->base.coin,dstr(subatomic_getbalance(&mp->base)),dstr(mp->base.satoshis)); + subatomic_closed(mp,approval,msgjson,senderpub); + } + else + { + printf("%u bob (%s/%s) gotopenrequest origid.%u status.%d (%s/%s) SENDERPUB.(%s)\n",mp->origid,mp->base.name,mp->rel.name,mp->origid,mp->status,mp->bob.recvaddr,mp->bob.recvZaddr,senderpub); + subatomic_approved(mp,approval,msgjson,senderpub); + } + } +} + +int32_t subatomic_channelapproved(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +{ + struct msginfo *mp; cJSON *approval; char *addr,*coin,*acname; int32_t retval = 0; + mp = subatomic_tracker(juint(msgjson,"origid")); + if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (approval= subatomic_mpjson(mp)) != 0 ) + { + printf("%u iambob.%d (%s/%s) channelapproved origid.%u status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->origid,mp->status); + if ( mp->bobflag == 0 && mp->status == SUBATOMIC_OPENREQUEST ) + { + if ( (addr= jstr(msgjson,"bobaddr")) != 0 ) + strcpy(mp->bob.recvaddr,addr); + if ( (addr= jstr(msgjson,"bobZaddr")) != 0 ) + strcpy(mp->bob.recvZaddr,addr); + if ( (addr= jstr(msgjson,"bobsecp")) != 0 ) + strcpy(mp->bob.secp,addr); + retval = subatomic_approved(mp,approval,msgjson,senderpub); + } + else if ( mp->bobflag != 0 && mp->status == SUBATOMIC_APPROVED ) + retval = subatomic_opened(mp,approval,msgjson,senderpub); + } + return(retval); +} + +int32_t subatomic_incomingopened(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +{ + struct msginfo *mp; cJSON *payment; int32_t retval = 0; + mp = subatomic_tracker(juint(msgjson,"origid")); + if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (payment= subatomic_mpjson(mp)) != 0 ) + { + printf("%u iambob.%d (%s/%s) incomingchannel status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->status); + if ( mp->bobflag == 0 && mp->status == SUBATOMIC_APPROVED ) + retval = subatomic_payment(mp,payment,msgjson,senderpub); + else if ( mp->bobflag != 0 && mp->status == SUBATOMIC_OPENED ) + retval = 1; // nothing to do + } + return(retval); +} + +int32_t subatomic_incomingpayment(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +{ + static FILE *fp; + struct msginfo *mp; cJSON *pay,*rawtx,*retjson; bits256 txid; char str[65],*hexstr; int32_t retval = 0; + mp = subatomic_tracker(juint(msgjson,"origid")); + if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (pay= subatomic_mpjson(mp)) != 0 ) + { + printf("%u iambob.%d (%s/%s) incomingpayment status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->status); + if ( mp->bobflag == 0 ) + { + txid = jbits256(msgjson,"bobpayment"); + jaddbits256(msgjson,"alicepayment",mp->alicepayment); + printf("%u alice waits for %s.%s to be in mempool (%.8f -> %s)\n",mp->origid,mp->base.name,bits256_str(str,txid),dstr(mp->base.satoshis),subatomic_zonly(&mp->base) == 0 ? mp->alice.recvaddr : mp->alice.recvZaddr); + hexstr = jstr(msgjson,"bobtx"); + if ( (rawtx= subatomic_txidwait(&mp->base,txid,hexstr,SUBATOMIC_TIMEOUT,senderpub)) != 0 ) + { + if ( subatomic_verifypayment(&mp->base,rawtx,mp->base.satoshis,subatomic_zonly(&mp->base) == 0 ? mp->alice.recvaddr : mp->alice.recvZaddr,txid) >= 0 ) + mp->gotpayment = 1; + free_json(rawtx); + } + if ( mp->gotpayment != 0 ) + { + printf("%u SWAP COMPLETE <<<<<<<<<<<<<<<<\n",mp->origid); + SUBATOMIC_retval = 0; + if ( mp->base.iszaddr == 0 ) + { + sprintf(str,"%u",mp->origid); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,bits256_str(str,mp->alicepayment),(char *)"completed",str,DPOW_pubkeystr,"","")) != 0 ) + free_json(retjson); + } + } + else + { + printf("%u SWAP INCOMPLETE, waiting on %s.%s\n",mp->origid,mp->base.name,bits256_str(str,txid)); + if ( (fp= fopen("SUBATOMIC.incomplete","a+")) != 0 ) + { + char *jsonstr = jprint(msgjson,0); + fwrite(jsonstr,1,strlen(jsonstr),fp); + fputc('\n',fp); + fclose(fp); + free(jsonstr); + } + if ( mp->base.iszaddr == 0 ) + { + sprintf(str,"%u",mp->origid); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,bits256_str(str,mp->alicepayment),(char *)"incomplete",str,DPOW_pubkeystr,"","")) != 0 ) + free_json(retjson); + } + subatomic_closed(mp,pay,msgjson,senderpub); + exit(-1); + } + } + if ( mp->gotpayment != 0 ) + retval = subatomic_paidinfull(mp,pay,msgjson,senderpub); + else + { + if ( mp->bobflag != 0 && mp->status == SUBATOMIC_OPENED ) + { + txid = jbits256(msgjson,"alicepayment"); + printf("%u bob waits for %s.%s to be in mempool (%.8f -> %s)\n",mp->origid,mp->rel.name,bits256_str(str,txid),dstr(mp->rel.satoshis),subatomic_zonly(&mp->rel) == 0 ? mp->bob.recvaddr : mp->bob.recvZaddr); + hexstr = jstr(msgjson,"alicetx"); + if ( (rawtx= subatomic_txidwait(&mp->rel,txid,hexstr,SUBATOMIC_TIMEOUT,senderpub)) != 0 ) + { + if ( subatomic_verifypayment(&mp->rel,rawtx,mp->rel.satoshis,subatomic_zonly(&mp->rel) == 0 ? mp->bob.recvaddr : mp->bob.recvZaddr,txid) >= 0 ) + mp->gotpayment = 1; + free_json(rawtx); + } + if ( mp->gotpayment != 0 ) + { + retval = subatomic_payment(mp,pay,msgjson,senderpub); + jaddbits256(msgjson,"bobpayment",mp->bobpayment); + if ( mp->rel.iszaddr == 0 ) + { + sprintf(str,"%u",mp->origid); + if ( (retjson= dpow_broadcast(SUBATOMIC_PRIORITY,bits256_str(str,mp->bobpayment),(char *)"completed",str,DPOW_pubkeystr,"","")) != 0 ) + free_json(retjson); + } + printf("%u SWAP COMPLETE <<<<<<<<<<<<<<<<\n",mp->origid); + if ( (fp= fopen("SUBATOMIC.proof","rb+")) == 0 ) + fp = fopen("SUBATOMIC.proof","wb"); + if ( fp != 0 ) + { + char *jsonstr = jprint(msgjson,0); + fseek(fp,0,SEEK_END); + fwrite(jsonstr,1,strlen(jsonstr),fp); + fputc('\n',fp); + fflush(fp); + free(jsonstr); + } + } else printf("%u SWAP INCOMPLETE: %s\n",mp->origid,jprint(msgjson,0)); + } + } + } + return(retval); +} + +int32_t subatomic_incomingfullypaid(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +{ + struct msginfo *mp; cJSON *closed; int32_t retval = 0; + mp = subatomic_tracker(juint(msgjson,"origid")); + if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (closed= subatomic_mpjson(mp)) != 0 ) + { + printf("%u iambob.%d (%s/%s) incomingfullypaid status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->status); + // error check msgjson vs M + if ( mp->bobflag == 0 && mp->status == SUBATOMIC_PAIDINFULL ) + retval = subatomic_closed(mp,closed,msgjson,senderpub); + else if ( mp->bobflag != 0 && mp->status == SUBATOMIC_PAYMENT ) + retval = subatomic_paidinfull(mp,closed,msgjson,senderpub); + } + return(retval); +} + +int32_t subatomic_incomingclosed(uint32_t inboxid,char *senderpub,cJSON *msgjson,struct msginfo *origmp) +{ + struct msginfo *mp; cJSON *closed; int32_t retval = 0; + mp = subatomic_tracker(juint(msgjson,"origid")); + if ( subatomic_orderbook_mpset(mp,mp->base.name) != 0 && (closed= subatomic_mpjson(mp)) != 0 ) + { + printf("%u iambob.%d (%s/%s) incomingclose status.%d\n",mp->origid,mp->bobflag,mp->base.name,mp->rel.name,mp->status); + if ( mp->bobflag != 0 ) + dpow_cancel(mp->origid); + if ( mp->status < SUBATOMIC_CLOSED ) + { + retval = subatomic_closed(mp,closed,msgjson,senderpub); + subatomic_status(mp,SUBATOMIC_CLOSED); + } + retval = 1; + } + return(retval); +} + +int32_t subatomic_ismine(int32_t bobflag,cJSON *json,char *basename,char *relname) +{ + char *base,*rel; + if ( (base= jstr(json,"base")) != 0 && (rel= jstr(json,"rel")) != 0 ) + { + if ( strcmp(base,basename) == 0 && strcmp(rel,relname) == 0 ) + return(1); + if ( bobflag != 0 ) + { + if ( strcmp(basename,"#allfiles") == 0 && base[0] == '#' ) + return(1); + fprintf(stderr,"skip ismine (%s/%s) vs (%s/%s)\n",basename,relname,base,rel); + } + } + return(0); +} + +void subatomic_tokensregister(int32_t priority) +{ + char *token_name,*tokenid,existing[65]; cJSON *tokens,*token; int32_t i,numtokens; + if ( SUBATOMIC_json != 0 && (tokens= jarray(&numtokens,SUBATOMIC_json,"tokens")) != 0 ) + { + for (i=0; i 0 ) + { + for (j=0; j %s, %u %llu %u\n",mp->bobflag,mp->base.name,mp->rel.name,mp->origid,(long long)mp->rel.satoshis,mp->openrequestid); + while ( 1 ) + { + if ( msgs == 0 ) + { + sleep(1); + fflush(stdout); + if ( mp->bobflag != 0 ) + { + dpow_pubkeyregister(SUBATOMIC_PRIORITY); + subatomic_tokensregister(SUBATOMIC_PRIORITY); + subatomic_filesregister(SUBATOMIC_PRIORITY); + } + } + msgs = 0; + for (iter=0; iter<(int32_t)(sizeof(tagBs)/sizeof(*tagBs)); iter++) + { + tagB = tagBs[iter]; + if ( (ptrs= dpow_inboxcheck(&n,&stopats[iter],tagB)) != 0 ) + { + for (i=0; ijsonstr)) != 0 ) + { + if ( jint(inboxjson,"tobob") != mp->bobflag ) + continue; + if ( subatomic_ismine(mp->bobflag,inboxjson,mp->base.name,mp->rel.name) != 0 ) + { + if ( strcmp(tagB,"openrequest") == 0 && mp->bobflag != 0 ) + subatomic_bob_gotopenrequest(ptr->shorthash,ptr->senderpub,inboxjson,mp->base.name,mp->rel.name); + else if ( strcmp(tagB,"approved") == 0 ) + mask |= subatomic_channelapproved(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 0; + else if ( strcmp(tagB,"opened") == 0 ) + mask |= subatomic_incomingopened(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 1; + else if ( strcmp(tagB,"payment") == 0 ) + mask |= subatomic_incomingpayment(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 2; + else if ( strcmp(tagB,"paid") == 0 ) + mask |= subatomic_incomingfullypaid(ptr->shorthash,ptr->senderpub,inboxjson,mp) << 3; + else if ( strcmp(tagB,"closed") == 0 ) + mask |= subatomic_incomingclosed(ptr->shorthash,ptr->senderpub,inboxjson,mp) * 0x1f; + else fprintf(stderr,"iambob.%d unknown unexpected tagB.(%s)\n",mp->bobflag,tagB); + } + free_json(inboxjson); + } else fprintf(stderr,"subatomic iambob.%d loop got unparseable(%s)\n",mp->bobflag,ptr->jsonstr); + free(ptr); + ptrs[i] = 0; + } + } + free(ptrs); + } + } + if ( mp->bobflag == 0 && (mask & 0x1f) == 0x1f ) + { + printf("alice %u %llu %u finished\n",mp->origid,(long long)mp->rel.satoshis,mp->openrequestid); + break; + } + } +} + +int32_t main(int32_t argc,char **argv) +{ + char *fname = "subatomic.json"; + int32_t i,height; char *coin,*kcli,*subatomic,*hashstr,*acname=(char *)""; cJSON *retjson; bits256 blockhash; char checkstr[65],str[65],str2[65],tmpstr[32]; long fsize; struct msginfo M; + memset(&M,0,sizeof(M)); + srand((int32_t)time(NULL)); + if ( (subatomic= filestr(&fsize,fname)) == 0 ) + { + fprintf(stderr,"cant load %s file\n",fname); + exit(-1); + } + if ( (SUBATOMIC_json= cJSON_Parse(subatomic)) == 0 ) + { + fprintf(stderr,"cant parse subatomic.json file (%s)\n",subatomic); + exit(-1); + } + free(subatomic); + if ( argc >= 4 ) + { + if ( dpow_pubkey() < 0 ) + { + fprintf(stderr,"couldnt set pubkey for DEX\n"); + return(-1); + } + coin = (char *)argv[1]; + if ( argv[2][0] != 0 ) + REFCOIN_CLI = (char *)argv[2]; + else + { + if ( strcmp(coin,"KMD") != 0 ) + { + acname = coin; + } + } + hashstr = (char *)argv[3]; + strcpy(M.rel.coin,subatomic_checkname(tmpstr,&M,1,coin)); + strcpy(M.rel.name,coin); + if ( argc == 4 && strlen(hashstr) == 64 ) // for blocknotify usage, seems not needed + { + height = get_coinheight(coin,acname,&blockhash); + bits256_str(checkstr,blockhash); + if ( strcmp(checkstr,hashstr) == 0 ) + { + fprintf(stderr,"%s: (%s) %s height.%d\n",coin,REFCOIN_CLI!=0?REFCOIN_CLI:"",checkstr,height); + if ( (retjson= dpow_ntzdata(coin,SUBATOMIC_PRIORITY,height,blockhash)) != 0 ) + free_json(retjson); + } else fprintf(stderr,"coin.%s (%s) %s vs %s, height.%d\n",coin,REFCOIN_CLI!=0?REFCOIN_CLI:"",checkstr,hashstr,height); + if ( strcmp("BTC",coin) != 0 ) + { + bits256 prevntzhash,ntzhash; int32_t prevntzheight,ntzheight; uint32_t ntztime,prevntztime; char hexstr[81]; cJSON *retjson2; + prevntzhash = dpow_ntzhash(coin,&prevntzheight,&prevntztime); + if ( (retjson= get_getinfo(coin,acname)) != 0 ) + { + ntzheight = juint(retjson,"notarized"); + ntzhash = jbits256(retjson,"notarizedhash"); + if ( ntzheight > prevntzheight ) + { + get_coinmerkleroot(coin,acname,ntzhash,&ntztime); + fprintf(stderr,"NOTARIZATION %s.%d %s t.%u\n",coin,ntzheight,bits256_str(str,ntzhash),ntztime); + bits256_str(hexstr,ntzhash); + sprintf(&hexstr[64],"%08x",ntzheight); + sprintf(&hexstr[72],"%08x",ntztime); + hexstr[80] = 0; + if ( (retjson2= dpow_broadcast(SUBATOMIC_PRIORITY,hexstr,coin,"notarizations",DPOW_pubkeystr,"","")) != 0 ) + free_json(retjson2); + } + else if ( ntzheight == prevntzheight && memcmp(&prevntzhash,&ntzhash,32) != 0 ) + fprintf(stderr,"NTZ ERROR %s.%d %s != %s\n",coin,ntzheight,bits256_str(str,ntzhash),bits256_str(str2,prevntzhash)); + free_json(retjson); + } + } + } + else if ( argc == 5 && atol(hashstr) > 10000 ) + { + char checkstr[32]; uint64_t mult = 1; + M.origid = (uint32_t)atol(hashstr); + sprintf(checkstr,"%u",M.origid); + if ( strcmp(checkstr,hashstr) == 0 ) // alice + { + M.rel.satoshis = (uint64_t)(atof(argv[4])*SATOSHIDEN+0.0000000049999); + for (i=0; M.rel.name[i]!=0; i++) + if ( M.rel.name[i] == '.' ) + { + mult = SATOSHIDEN; + break; + } + if ( subatomic_getbalance(&M.rel) < M.rel.satoshis/mult ) + { + fprintf(stderr,"not enough balance %s %.8f for %.8f\n",M.rel.coin,dstr(subatomic_getbalance(&M.rel)),dstr(M.rel.satoshis/mult)); + return(-1); + } + fprintf(stderr,"subatomic_channel_alice (%s/%s) %s %u with %.8f %llu\n",M.rel.name,M.rel.coin,hashstr,M.origid,atof(argv[4]),(long long)M.rel.satoshis); + dpow_pubkeyregister(SUBATOMIC_PRIORITY); + M.openrequestid = subatomic_alice_openrequest(&M); + if ( M.openrequestid != 0 ) + subatomic_loop(&M); + } else fprintf(stderr,"checkstr mismatch %s %s != %s\n",coin,hashstr,checkstr); + } + else + { + M.bobflag = 1; + strcpy(M.base.name,hashstr); + strcpy(M.base.coin,subatomic_checkname(tmpstr,&M,0,hashstr)); + subatomic_loop(&M); // while ( 1 ) loop for each relcoin -> basecoin + } + } + return(SUBATOMIC_retval); +} + diff --git a/src/cc/dapps/subatomic.json b/src/cc/dapps/subatomic.json new file mode 100644 index 000000000..7420c712c --- /dev/null +++ b/src/cc/dapps/subatomic.json @@ -0,0 +1,26 @@ +{ +"authorized": [ + {"chmex":"030754bffcf6dfcb34a20c486ff5a5be5546b9cc16fba9692165272b3f8e98c4af" }, + {"SHossain":"03c8657bd57b6ceb14514a10e99fe8a0cec5a9bc24592df7f66f050e670e4f6bac" }, + {"satinder":"03732f8ef851ff234c74d0df575c2c5b159e2bab3faca4ec52b3f217d5cda5361d" }, + {"ml777":"02453d028c74cb9551e1aaf35113383b6ecbd9f06ff23a4ab1a953429b9763e345" }, + {"tonylhub":"0218e0f435d4544404c25a7759b7f7174d821215085ef936218c5569d975af468b" }, + {"gthub":"036c7de9a5090fbad78b9eea41549ccacc07bd0e9e7f8d290c88f470f3569e1a35" }, + {"zkTrader":"026c6b0b35ec0adc2f8a5c648da1fce634f798c69d5e9fe518400447e88398b830" }, + {"nutellalicka":"03aee08860e0340f0f490a3ef3718d6676882f2d63d4f536dfebb1d348b82c79ee" }, + {"gcharang":"02d3431950c2f0f9654217b6ce3d44468d3a9ca7255741767fdeee7c5ec6b47567" }, + {"jl777":"02b27de3ee5335518b06f69f4fbabb029cfc737613b100996841d5532b324a5a61" } +], +"tokens":[ + {"RICK.demo":"2b1feef719ecb526b07416dd432bce603ac6dc8bfe794cddf105cb52f6aae3cd"} +], +"files":[ + {"filename":"komodod","prices":[{"KMD":0.1}, {"PIRATE":1}]} +], +"externalcoins":[ + { "BTC":"bitcoin-cli" }, + { "CHIPS":"chips-cli" }, + { "VRSC":"verus" } +] +} + From 19ddbe12802c690b5eada1627dd58b9707d839d4 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 30 Apr 2020 06:57:21 -0400 Subject: [PATCH 12/98] Update subatomic json --- src/cc/dapps/subatomic.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cc/dapps/subatomic.json b/src/cc/dapps/subatomic.json index 7420c712c..7832fdb9e 100644 --- a/src/cc/dapps/subatomic.json +++ b/src/cc/dapps/subatomic.json @@ -15,12 +15,13 @@ {"RICK.demo":"2b1feef719ecb526b07416dd432bce603ac6dc8bfe794cddf105cb52f6aae3cd"} ], "files":[ - {"filename":"komodod","prices":[{"KMD":0.1}, {"PIRATE":1}]} + {"filename":"hushd","prices":[{"HUSH":0.1}, {"PIRATE":1}]} ], "externalcoins":[ { "BTC":"bitcoin-cli" }, + { "KMD":"komodod-cli" }, { "CHIPS":"chips-cli" }, - { "VRSC":"verus" } + { "PIRATE":"pirate-cli" } ] } From 70bd156655a3b92d9e6d3924b8227a0dd8e1d869 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 30 Apr 2020 07:04:52 -0400 Subject: [PATCH 13/98] Add dapp header to make subatomic happy --- src/cc/dapps/dappinc.h | 1599 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1599 insertions(+) create mode 100644 src/cc/dapps/dappinc.h diff --git a/src/cc/dapps/dappinc.h b/src/cc/dapps/dappinc.h new file mode 100644 index 000000000..3c71dfdec --- /dev/null +++ b/src/cc/dapps/dappinc.h @@ -0,0 +1,1599 @@ +/****************************************************************************** + * Copyright © 2014-2020 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include +#include +#include +#include +#include "cJSON.c" + +bits256 zeroid; + +int32_t unstringbits(char *buf,uint64_t bits) +{ + int32_t i; + for (i=0; i<8; i++,bits>>=8) + if ( (buf[i]= (char)(bits & 0xff)) == 0 ) + break; + buf[i] = 0; + return(i); +} + +uint64_t stringbits(char *str) +{ + uint64_t bits = 0; + if ( str == 0 ) + return(0); + int32_t i,n = (int32_t)strlen(str); + if ( n > 8 ) + n = 8; + for (i=n-1; i>=0; i--) + bits = (bits << 8) | (str[i] & 0xff); + //printf("(%s) -> %llx %llu\n",str,(long long)bits,(long long)bits); + return(bits); +} + +char hexbyte(int32_t c) +{ + c &= 0xf; + if ( c < 10 ) + return('0'+c); + else if ( c < 16 ) + return('a'+c-10); + else return(0); +} + +int32_t _unhex(char c) +{ + if ( c >= '0' && c <= '9' ) + return(c - '0'); + else if ( c >= 'a' && c <= 'f' ) + return(c - 'a' + 10); + else if ( c >= 'A' && c <= 'F' ) + return(c - 'A' + 10); + return(-1); +} + +int32_t is_hexstr(char *str,int32_t n) +{ + int32_t i; + if ( str == 0 || str[0] == 0 ) + return(0); + for (i=0; str[i]!=0; i++) + { + if ( n > 0 && i >= n ) + break; + if ( _unhex(str[i]) < 0 ) + break; + } + if ( n == 0 ) + return(i); + return(i == n); +} + +int32_t unhex(char c) +{ + int32_t hex; + if ( (hex= _unhex(c)) < 0 ) + { + //printf("unhex: illegal hexchar.(%c)\n",c); + } + return(hex); +} + +unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } + +int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex) +{ + int32_t adjust,i = 0; + //printf("decode.(%s)\n",hex); + if ( is_hexstr(hex,n) <= 0 ) + { + memset(bytes,0,n); + return(n); + } + if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) + hex[--n] = 0; + if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) + hex[--n] = 0; + if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) + { + if ( n > 0 ) + { + bytes[0] = unhex(hex[0]); + printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); + } + bytes++; + hex++; + adjust = 1; + } else adjust = 0; + if ( n > 0 ) + { + for (i=0; i>4) & 0xf); + hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); + //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); + } + hexbytes[len*2] = 0; + //printf("len.%ld\n",len*2+1); + return((int32_t)len*2+1); +} + +long _stripwhite(char *buf,int accept) +{ + int32_t i,j,c; + if ( buf == 0 || buf[0] == 0 ) + return(0); + for (i=j=0; buf[i]!=0; i++) + { + buf[j] = c = buf[i]; + if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') ) + j++; + } + buf[j] = 0; + return(j); +} + +char *clonestr(char *str) +{ + char *clone; + if ( str == 0 || str[0]==0) + { + printf("warning cloning nullstr.%p\n",str); + //#ifdef __APPLE__ + // while ( 1 ) sleep(1); + //#endif + str = (char *)""; + } + clone = (char *)malloc(strlen(str)+16); + strcpy(clone,str); + return(clone); +} + +int32_t safecopy(char *dest,char *src,long len) +{ + int32_t i = -1; + if ( src != 0 && dest != 0 && src != dest ) + { + if ( dest != 0 ) + memset(dest,0,len); + for (i=0; i0; i--) + str[i] = str[i-1]; + str[0] = '/'; + str[n+1] = 0; + }*/ +#endif + return(str); +#endif +} + +void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep) +{ + FILE *fp; + long filesize,buflen = *allocsizep; + uint8_t *buf = *bufp; + *lenp = 0; + if ( (fp= fopen(portable_path(fname),"rb")) != 0 ) + { + fseek(fp,0,SEEK_END); + filesize = ftell(fp); + if ( filesize == 0 ) + { + fclose(fp); + *lenp = 0; + //printf("loadfile null size.(%s)\n",fname); + return(0); + } + if ( filesize > buflen ) + { + *allocsizep = filesize; + *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); + } + rewind(fp); + if ( buf == 0 ) + printf("Null buf ???\n"); + else + { + if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) + printf("error reading filesize.%ld\n",(long)filesize); + buf[filesize] = 0; + } + fclose(fp); + *lenp = filesize; + //printf("loaded.(%s)\n",buf); + } //else printf("OS_loadfile couldnt load.(%s)\n",fname); + return(buf); +} + +void *filestr(long *allocsizep,char *_fname) +{ + long filesize = 0; char *fname,*buf = 0; void *retptr; + *allocsizep = 0; + fname = malloc(strlen(_fname)+1); + strcpy(fname,_fname); + retptr = loadfile(fname,(uint8_t **)&buf,&filesize,allocsizep); + free(fname); + return(retptr); +} + +char *send_curl(char *url,char *fname) +{ + long fsize; char curlstr[1024]; + sprintf(curlstr,"curl --url \"%s\" > %s",url,fname); + system(curlstr); + return(filestr(&fsize,fname)); +} + +cJSON *get_urljson(char *url,char *fname) +{ + char *jsonstr; cJSON *json = 0; + if ( (jsonstr= send_curl(url,fname)) != 0 ) + { + //printf("(%s) -> (%s)\n",url,jsonstr); + json = cJSON_Parse(jsonstr); + free(jsonstr); + } + return(json); +} + +////////////////////////////////////////////// +// start of dapp +////////////////////////////////////////////// +int md_unlink(char *file) +{ +#ifdef _WIN32 + _chmod(file, 0600); + return( _unlink(file) ); +#else + return(unlink(file)); +#endif +} + +char *REFCOIN_CLI,DPOW_pubkeystr[67],DPOW_secpkeystr[67],DPOW_handle[67],DPOW_recvaddr[64],DPOW_recvZaddr[128]; + +cJSON *get_komodocli(char *refcoin,char **retstrp,char *acname,char *method,char *arg0,char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6) +{ + long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,fname[32768]; + sprintf(fname,"/tmp/notarizer_%s_%d",method,(rand() >> 17) % 10000); + //if ( (acname == 0 || acname[0] == 0) && strcmp(refcoin,"KMD") != 0 ) + // acname = refcoin; + if ( acname[0] != 0 ) + { + if ( refcoin[0] != 0 && strcmp(refcoin,"KMD") != 0 && strcmp(refcoin,acname) != 0 ) + printf("unexpected: refcoin.(%s) acname.(%s)\n",refcoin,acname); + sprintf(cmdstr,"komodo-cli -ac_name=%s %s %s %s %s %s %s %s %s > %s\n",acname,method,arg0,arg1,arg2,arg3,arg4,arg5,arg6,fname); + } + else if ( strcmp(refcoin,"KMD") == 0 ) + sprintf(cmdstr,"komodo-cli %s %s %s %s %s %s %s %s > %s\n",method,arg0,arg1,arg2,arg3,arg4,arg5,arg6,fname); + else if ( REFCOIN_CLI != 0 && REFCOIN_CLI[0] != 0 ) + { + sprintf(cmdstr,"%s %s %s %s %s %s %s %s %s > %s\n",REFCOIN_CLI,method,arg0,arg1,arg2,arg3,arg4,arg5,arg6,fname); + //printf("ref.(%s) REFCOIN_CLI (%s)\n",refcoin,cmdstr); + } +//fprintf(stderr,"system(%s)\n",cmdstr); + system(cmdstr); + *retstrp = 0; + if ( (jsonstr= filestr(&fsize,fname)) != 0 ) + { + jsonstr[strlen(jsonstr)-1]='\0'; + //fprintf(stderr,"%s -> jsonstr.(%s)\n",cmdstr,jsonstr); + if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0 ) + *retstrp = jsonstr; + else free(jsonstr); + md_unlink(fname); + } //else fprintf(stderr,"system(%s) -> NULL\n",cmdstr); + return(retjson); +} + +cJSON *subatomic_cli(char *clistr,char **retstrp,char *method,char *arg0,char *arg1,char *arg2,char *arg3,char *arg4,char *arg5,char *arg6) +{ + long fsize; cJSON *retjson = 0; char cmdstr[32768],*jsonstr,fname[32768]; + sprintf(fname,"/tmp/subatomic_%s_%d",method,(rand() >> 17) % 10000); + sprintf(cmdstr,"%s %s %s %s %s %s %s %s %s > %s\n",clistr,method,arg0,arg1,arg2,arg3,arg4,arg5,arg6,fname); +//fprintf(stderr,"system(%s)\n",cmdstr); + system(cmdstr); + *retstrp = 0; + if ( (jsonstr= filestr(&fsize,fname)) != 0 ) + { + jsonstr[strlen(jsonstr)-1]='\0'; + //fprintf(stderr,"%s -> jsonstr.(%s)\n",cmdstr,jsonstr); + if ( (jsonstr[0] != '{' && jsonstr[0] != '[') || (retjson= cJSON_Parse(jsonstr)) == 0 ) + *retstrp = jsonstr; + else free(jsonstr); + md_unlink(fname); + } //else fprintf(stderr,"system(%s) -> NULL\n",cmdstr); + return(retjson); +} + +bits256 komodobroadcast(char *refcoin,char *acname,cJSON *hexjson) +{ + char *hexstr,*retstr,str[65]; cJSON *retjson; bits256 txid; + memset(txid.bytes,0,sizeof(txid)); + if ( (hexstr= jstr(hexjson,"hex")) != 0 ) + { + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"sendrawtransaction",hexstr,"","","","","","")) != 0 ) + { + //fprintf(stderr,"broadcast.(%s)\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + if ( strlen(retstr) >= 64 ) + { + retstr[64] = 0; + decode_hex(txid.bytes,32,retstr); + } + fprintf(stderr,"broadcast %s txid.(%s)\n",strlen(acname)>0?acname:refcoin,bits256_str(str,txid)); + free(retstr); + } + } + return(txid); +} + +bits256 sendtoaddress(char *refcoin,char *acname,char *destaddr,int64_t satoshis,char *oprethexstr) +{ + char numstr[32],*retstr,str[65]; cJSON *retjson; bits256 txid; + memset(txid.bytes,0,sizeof(txid)); + sprintf(numstr,"%.8f",(double)satoshis/SATOSHIDEN); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"sendtoaddress",destaddr,numstr,"false","","",oprethexstr,"")) != 0 ) + { + fprintf(stderr,"unexpected sendrawtransaction json.(%s)\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + if ( strlen(retstr) >= 64 ) + { + retstr[64] = 0; + decode_hex(txid.bytes,32,retstr); + } + fprintf(stderr,"sendtoaddress %s %.8f txid.(%s)\n",destaddr,(double)satoshis/SATOSHIDEN,bits256_str(str,txid)); + free(retstr); + } + return(txid); +} + +bits256 tokentransfer(char *refcoin,char *acname,char *tokenid,char *destpub,int64_t units) +{ + char numstr[32],*retstr,str[65]; cJSON *retjson; bits256 txid; + memset(txid.bytes,0,sizeof(txid)); + sprintf(numstr,"%llu",(long long)units); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"tokentransfer",tokenid,destpub,numstr,"","","","")) != 0 ) + { + txid = komodobroadcast(refcoin,acname,retjson); + fprintf(stderr,"tokentransfer returned (%s)\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"tokentransfer.(%s) error.(%s)\n",acname,retstr); + free(retstr); + } + return(txid); +} + +char *get_tokenaddress(char *refcoin,char *acname,char *tokenaddr) +{ + char *retstr,*str; cJSON *retjson; + tokenaddr[0] = 0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"tokenaddress","","","","","","","")) != 0 ) + { + if ( (str= jstr(retjson,"myCCAddress(Tokens)")) != 0 ) + { + strcpy(tokenaddr,str); + fprintf(stderr,"tokenaddress returned (%s)\n",tokenaddr); + free_json(retjson); + return(tokenaddr); + } + free_json(retjson); + } + else if ( retstr != 0 ) + { + //fprintf(stderr,"tokentransfer.(%s) error.(%s)\n",acname,retstr); + free(retstr); + } + return(0); +} + +int64_t get_tokenbalance(char *refcoin,char *acname,char *tokenid) +{ + cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"tokenbalance",tokenid,"","","","","","")) != 0 ) + { + amount = j64bits(retjson,"balance"); + fprintf(stderr,"tokenbalance %llu\n",(long long)amount); + free_json(retjson); + } + else if ( retstr != 0 ) + { + //printf("retstr %s -> %.8f\n",retstr,dstr(amount)); + free(retstr); + } + return (amount); +} + +cJSON *get_decodescript(char *refcoin,char *acname,char *script) +{ + cJSON *retjson; char *retstr; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"decodescript",script,"","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_decodescript.(%s) error.(%s)\n",acname,retstr); + free(retstr); + } + return(0); +} + +char *get_createmultisig2(char *refcoin,char *acname,char *msigaddr,char *redeemscript,char *pubkeyA,char *pubkeyB) +{ + //char para 2 '["02c3af47b51a506b08b4ededb156cb4c3f9db9e0ac7ad27b8623c08a056fdcc220", "038e61fbface549a850862f12ed99b7cbeef5c2bd2d8f1daddb34809416f0259e1"]' + cJSON *retjson; char *retstr,*str,params[256]; int32_t height=0; + msigaddr[0] = 0; + redeemscript[0] = 0; + sprintf(params,"'[\"%s\", \"%s\"]'",pubkeyA,pubkeyB); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"createmultisig","2",params,"","","","","")) != 0 ) + { + if ( (str= jstr(retjson,"address")) != 0 ) + strcpy(msigaddr,str); + if ( (str= jstr(retjson,"redeemScript")) != 0 ) + strcpy(redeemscript,str); + free_json(retjson); + if ( msigaddr[0] != 0 && redeemscript[0] != 0 ) + return(msigaddr); + else return(0); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"%s get_createmultisig2.(%s) error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +int32_t get_coinheight(char *refcoin,char *acname,bits256 *blockhashp) +{ + cJSON *retjson; char *retstr; int32_t height=0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getblockchaininfo","","","","","","","")) != 0 ) + { + height = jint(retjson,"blocks"); + *blockhashp = jbits256(retjson,"bestblockhash"); + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"%s get_coinheight.(%s) error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(height); +} + +bits256 get_coinblockhash(char *refcoin,char *acname,int32_t height) +{ + cJSON *retjson; char *retstr,heightstr[32]; bits256 hash; + memset(hash.bytes,0,sizeof(hash)); + sprintf(heightstr,"%d",height); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getblockhash",heightstr,"","","","","","")) != 0 ) + { + fprintf(stderr,"unexpected blockhash json.(%s)\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + if ( strlen(retstr) >= 64 ) + { + retstr[64] = 0; + decode_hex(hash.bytes,32,retstr); + } + free(retstr); + } + return(hash); +} + +bits256 get_coinmerkleroot(char *refcoin,char *acname,bits256 blockhash,uint32_t *blocktimep) +{ + cJSON *retjson; char *retstr,str[65]; bits256 merkleroot; + memset(merkleroot.bytes,0,sizeof(merkleroot)); + *blocktimep = 0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getblockheader",bits256_str(str,blockhash),"","","","","","")) != 0 ) + { + merkleroot = jbits256(retjson,"merkleroot"); + *blocktimep = juint(retjson,"time"); + //fprintf(stderr,"got merkleroot.(%s)\n",bits256_str(str,merkleroot)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"%s %s get_coinmerkleroot error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(merkleroot); +} + +uint32_t get_heighttime(char *refcoin,char *acname,int32_t height) +{ + bits256 blockhash; uint32_t blocktime; + blockhash = get_coinblockhash(refcoin,acname,height); + get_coinmerkleroot(refcoin,acname,blockhash,&blocktime); + return(blocktime); +} + +int32_t get_coinheader(char *refcoin,char *acname,bits256 *blockhashp,bits256 *merklerootp,int32_t prevheight) +{ + int32_t height = 0; char str[65]; bits256 bhash; uint32_t blocktime; + if ( prevheight == 0 ) + height = get_coinheight(refcoin,acname,&bhash) - 20; + else height = prevheight + 1; + if ( height > 0 ) + { + *blockhashp = get_coinblockhash(refcoin,acname,height); + if ( bits256_nonz(*blockhashp) != 0 ) + { + *merklerootp = get_coinmerkleroot(refcoin,acname,*blockhashp,&blocktime); + if ( bits256_nonz(*merklerootp) != 0 ) + return(height); + } + } + memset(blockhashp,0,sizeof(*blockhashp)); + memset(merklerootp,0,sizeof(*merklerootp)); + return(0); +} + +cJSON *get_rawmempool(char *refcoin,char *acname) +{ + cJSON *retjson; char *retstr; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getrawmempool","","","","","","","")) != 0 ) + { + //printf("mempool.(%s)\n",jprint(retjson,0)); + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_rawmempool.(%s) error.(%s)\n",acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *get_addressutxos(char *refcoin,char *acname,char *coinaddr) +{ + cJSON *retjson; char *retstr,jsonbuf[256]; + if ( refcoin[0] != 0 && strcmp(refcoin,"KMD") != 0 ) + printf("warning: assumes %s has addressindex enabled\n",refcoin); + sprintf(jsonbuf,"{\\\"addresses\\\":[\\\"%s\\\"]}",coinaddr); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getaddressutxos",jsonbuf,"","","","","","")) != 0 ) + { + //printf("addressutxos.(%s)\n",jprint(retjson,0)); + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_addressutxos.(%s) error.(%s)\n",acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *get_rawtransaction(char *refcoin,char *acname,bits256 txid) +{ + cJSON *retjson; char *retstr,str[65]; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getrawtransaction",bits256_str(str,txid),"1","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_rawtransaction.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *get_z_viewtransaction(char *refcoin,char *acname,bits256 txid) +{ + cJSON *retjson; char *retstr,str[65]; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_viewtransaction",bits256_str(str,txid),"","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_z_viewtransaction.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *get_listunspent(char *refcoin,char *acname) +{ + cJSON *retjson; char *retstr,str[65]; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"listunspent","","","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_listunspent.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *get_getinfo(char *refcoin,char *acname) +{ + cJSON *retjson; char *retstr,str[65]; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getinfo","","","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"get_getinfo.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *z_listunspent(char *refcoin,char *acname) +{ + cJSON *retjson; char *retstr,str[65]; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_listunspent","","","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"z_listunspent.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *z_listoperationids(char *refcoin,char *acname) +{ + cJSON *retjson; char *retstr,str[65]; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_listoperationids","","","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"z_listoperationids.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *z_getoperationstatus(char *refcoin,char *acname,char *opid) +{ + cJSON *retjson; char *retstr,str[65],params[512]; + sprintf(params,"'[\"%s\"]'",opid); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_getoperationstatus",params,"","","","","","")) != 0 ) + { + //printf("got status (%s)\n",jprint(retjson,0)); + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"z_getoperationstatus.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +cJSON *z_getoperationresult(char *refcoin,char *acname,char *opid) +{ + cJSON *retjson; char *retstr,str[65],params[512]; + sprintf(params,"'[\"%s\"]'",opid); + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_getoperationresult",params,"","","","","","")) != 0 ) + { + return(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"z_getoperationresult.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return(0); +} + +int32_t validateaddress(char *refcoin,char *acname,char *depositaddr, char* compare) +{ + cJSON *retjson; char *retstr; int32_t res=0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"validateaddress",depositaddr,"","","","","","")) != 0 ) + { + if (is_cJSON_True(jobj(retjson,compare)) != 0 ) res=1; + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"validateaddress.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return (res); +} + +int32_t z_validateaddress(char *refcoin,char *acname,char *depositaddr, char *compare) +{ + cJSON *retjson; char *retstr; int32_t res=0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_validateaddress",depositaddr,"","","","","","")) != 0 ) + { + if (is_cJSON_True(jobj(retjson,compare)) != 0 ) + res=1; + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"z_validateaddress.(%s) %s error.(%s)\n",refcoin,acname,retstr); + free(retstr); + } + return (res); +} + +int64_t get_getbalance(char *refcoin,char *acname) +{ + cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getbalance","","","","","","","")) != 0 ) + { + fprintf(stderr,"get_getbalance.(%s) %s returned json!\n",refcoin,acname); + free_json(retjson); + } + else if ( retstr != 0 ) + { + amount = atof(retstr) * SATOSHIDEN; + sprintf(cmpstr,"%.8f",dstr(amount)); + if ( strcmp(retstr,cmpstr) != 0 ) + amount++; + //printf("retstr %s -> %.8f\n",retstr,dstr(amount)); + free(retstr); + } + return (amount); +} + +int64_t z_getbalance(char *refcoin,char *acname,char *coinaddr) +{ + cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_getbalance",coinaddr,"","","","","","")) != 0 ) + { + fprintf(stderr,"z_getbalance.(%s) %s returned json!\n",refcoin,acname); + free_json(retjson); + } + else if ( retstr != 0 ) + { + amount = atof(retstr) * SATOSHIDEN; + sprintf(cmpstr,"%.8f",dstr(amount)); + if ( strcmp(retstr,cmpstr) != 0 ) + amount++; + //printf("retstr %s -> %.8f\n",retstr,dstr(amount)); + free(retstr); + } + return (amount); +} + +int32_t z_exportkey(char *privkey,char *refcoin,char *acname,char *zaddr) +{ + cJSON *retjson; char *retstr,cmpstr[64]; int64_t amount=0; + privkey[0] = 0; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_exportkey",zaddr,"","","","","","")) != 0 ) + { + fprintf(stderr,"z_exportkey.(%s) %s returned json!\n",refcoin,acname); + free_json(retjson); + return(-1); + } + else if ( retstr != 0 ) + { + //printf("retstr %s -> %.8f\n",retstr,dstr(amount)); + strcpy(privkey,retstr); + free(retstr); + return(0); + } + return(-1); +} + +int32_t getnewaddress(char *coinaddr,char *refcoin,char *acname) +{ + cJSON *retjson; char *retstr; int64_t amount=0; int32_t retval = -1; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"getnewaddress","","","","","","","")) != 0 ) + { + fprintf(stderr,"getnewaddress.(%s) %s returned json!\n",refcoin,acname); + free_json(retjson); + } + else if ( retstr != 0 ) + { + strcpy(coinaddr,retstr); + free(retstr); + retval = 0; + } + return(retval); +} + +int32_t z_getnewaddress(char *coinaddr,char *refcoin,char *acname,char *typestr) +{ + cJSON *retjson; char *retstr; int64_t amount=0; int32_t retval = -1; + if ( (retjson= get_komodocli(refcoin,&retstr,acname,"z_getnewaddress",typestr,"","","","","","")) != 0 ) + { + fprintf(stderr,"z_getnewaddress.(%s) %s returned json!\n",refcoin,acname); + free_json(retjson); + } + else if ( retstr != 0 ) + { + strcpy(coinaddr,retstr); + free(retstr); + retval = 0; + } + return(retval); +} + +int64_t find_onetime_amount(char *coinstr,char *coinaddr) +{ + cJSON *array,*item; int32_t i,n; char *addr; int64_t amount = 0; + coinaddr[0] = 0; + if ( (array= get_listunspent(coinstr,"")) != 0 ) + { + //printf("got listunspent.(%s)\n",jprint(array,0)); + if ( (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i 0 ) + { + for (i=0; i %s\n",coinstr,acname,srcaddr,params); + if ( (retjson= get_komodocli(coinstr,&retstr,acname,"z_sendmany",addr,params,"","","","","")) != 0 ) + { + printf("unexpected json z_sendmany.(%s)\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"z_sendmany.(%s) -> opid.(%s)\n",coinstr,retstr); + strcpy(opidstr,retstr); + free(retstr); + retval = 0; + } + return(retval); +} + +int32_t z_mergetoaddress(char *opidstr,char *coinstr,char *acname,char *destaddr) +{ + cJSON *retjson; char *retstr,addr[128],*opstr; int32_t retval = -1; + sprintf(addr,"[\\\"ANY_SPROUT\\\"]"); + if ( (retjson= get_komodocli(coinstr,&retstr,acname,"z_mergetoaddress",addr,destaddr,"","","","","")) != 0 ) + { + if ( (opstr= jstr(retjson,"opid")) != 0 ) + strcpy(opidstr,opstr); + retval = jint(retjson,"remainingNotes"); + fprintf(stderr,"%s\n",jprint(retjson,0)); + free_json(retjson); + } + else if ( retstr != 0 ) + { + fprintf(stderr,"z_mergetoaddress.(%s) -> opid.(%s)\n",coinstr,retstr); + strcpy(opidstr,retstr); + free(retstr); + } + return(retval); +} + +int32_t empty_mempool(char *coinstr,char *acname) +{ + cJSON *array; int32_t n; + if ( (array= get_rawmempool(coinstr,acname)) != 0 ) + { + if ( (n= cJSON_GetArraySize(array)) > 0 ) + return(0); + free_json(array); + return(1); + } + return(-1); +} + +cJSON *getinputarray(int64_t *totalp,cJSON *unspents,int64_t required) +{ + cJSON *vin,*item,*vins = cJSON_CreateArray(); int32_t i,n,v; int64_t satoshis; bits256 txid; + *totalp = 0; + if ( (n= cJSON_GetArraySize(unspents)) > 0 ) + { + for (i=0; i= required ) + break; + } + } + } + return(vins); +} + +int32_t tx_has_voutaddress(char *refcoin,char *acname,bits256 txid,char *coinaddr) +{ + cJSON *txobj,*vouts,*vout,*vins,*vin,*sobj,*addresses; char *addr,str[65]; int32_t i,j,n,numarray,retval = 0, hasvout=0; + if ( (txobj= get_rawtransaction(refcoin,acname,txid)) != 0 ) + { + if ( (vouts= jarray(&numarray,txobj,"vout")) != 0 ) + { + for (i=0; i 0 ) + { + for (i=0; i 0 ) + { + for (j=0; j 0 && strcmp(vinaddr,cmpaddr) == 0 ) + return(0); + printf("mismatched vinaddr.(%s) vs %s\n",vinaddr,cmpaddr); + } + } + return(-1); +} + +int32_t txid_in_vins(char *refcoin,bits256 txid,bits256 cmptxid) +{ + cJSON *txjson,*vins,*vin; int32_t numvins,v,vinvout; bits256 vintxid; char str[65]; + if ( (txjson= get_rawtransaction(refcoin,"",txid)) != 0 ) + { + if ( (vins= jarray(&numvins,txjson,"vin")) != 0 ) + { + for (v=0; v n.%d retval.%d\n",tagA,tagB,pubkeystr,n,retval); + } + free_json(retjson); + } + return(retval); +} + +int32_t dpow_hasmessage(char *payload,char *tagA,char *tagB,char *pubkeystr) +{ + cJSON *retjson,*item,*array; char *retstr,*pstr; int32_t i,n,retval = 0; + if ( (retjson= get_komodocli((char *)"",&retstr,DEXP2P_CHAIN,"DEX_list","0","0",tagA,tagB,pubkeystr,"","")) != 0 ) + { + if ( (array= jarray(&n,retjson,"matches")) != 0 ) + { + for (i=0; i 0 ) + { + ptrs = calloc(n,sizeof(*ptrs)); + for (i=0; ishorthash = juint(item,"id"); + ptrs[m]->jsonstr = ptr; + strcpy(ptrs[m]->senderpub,senderpub); + m++; + } + } + } + *nump = m; + } + free_json(retjson); + } + return(ptrs); +} + + From 888efff4d1935266416288a50b1630a481966166 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 30 Apr 2020 07:06:47 -0400 Subject: [PATCH 14/98] Add subatomic to dapp makefile --- src/cc/dapps/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cc/dapps/Makefile b/src/cc/dapps/Makefile index 6e7874788..1fea27084 100644 --- a/src/cc/dapps/Makefile +++ b/src/cc/dapps/Makefile @@ -1,6 +1,10 @@ +# Copyright 2020 The Hush Developers # just type make to compile all dapps all: zmigrate oraclefeed +subatomic: + $(CC) subatomic.c -o subatomic -lm + zmigrate: $(CC) zmigrate.c -o zmigrate -lm @@ -9,3 +13,4 @@ oraclefeed: clean: rm zmigrate oraclefeed + From 8a4e72fca2e0b41dc9f6875a40c2ceba048029eb Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 8 May 2020 08:57:34 -0400 Subject: [PATCH 15/98] Remove some sprout code from BuildWitnessCache --- src/wallet/wallet.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 53b3af6a6..546d9a547 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1288,10 +1288,6 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) LogPrintf("Building Witnesses for block %i %.4f complete\n", pblockindex->GetHeight(), pblockindex->GetHeight() / double(height)); } - SproutMerkleTree sproutTree; - sproutRoot = pblockindex->pprev->hashFinalSproutRoot; - pcoinsTip->GetSproutAnchorAt(sproutRoot, sproutTree); - SaplingMerkleTree saplingTree; saplingRoot = pblockindex->pprev->hashFinalSaplingRoot; pcoinsTip->GetSaplingAnchorAt(saplingRoot, saplingTree); From dd5d932f8711c17e66fde407c1cdf2d0ae7aedf1 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 11 May 2020 06:34:48 -0400 Subject: [PATCH 16/98] Only print these when -zdebug is turned on --- src/wallet/rpcwallet.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5afd0c4e8..37f67042b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4388,7 +4388,9 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp, const CPubKey& my // Fetch the note that is being spent auto res = pwalletMain->mapSaplingNullifiersToNotes.find(spend.nullifier); if (res == pwalletMain->mapSaplingNullifiersToNotes.end()) { - fprintf(stderr,"Could not find spending note %s", uint256_str(str, spend.nullifier)); + if(fZdebug) { + fprintf(stderr,"Could not find spending note %s\n", uint256_str(str, spend.nullifier)); + } continue; } auto op = res->second; @@ -4442,8 +4444,10 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp, const CPubKey& my pa = recovered->second; isOutgoing = true; } else { - // Unreadable - fprintf(stderr,"Could not recover Sapling note!"); + // Unreadable or unconfirmed? + if(fZdebug) { + fprintf(stderr,"Could not recover Sapling note!\n"); + } continue; } } From 095157d2d97de6da7de24ab168d36b383a6dbda3 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 11 May 2020 06:42:01 -0400 Subject: [PATCH 17/98] Remove sprout junk --- src/wallet/wallet.cpp | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 546d9a547..8d56fdfae 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1298,7 +1298,7 @@ void CWallet::BuildWitnessCache(const CBlockIndex* pindex, bool witnessOnly) for (std::pair& wtxItem : mapWallet) { - if (wtxItem.second.mapSproutNoteData.empty() && wtxItem.second.mapSaplingNoteData.empty()) + if (wtxItem.second.mapSaplingNoteData.empty()) continue; if (wtxItem.second.GetDepthInMainChain() > 0) { @@ -3062,38 +3062,11 @@ void CWallet::DeleteWalletTransactions(const CBlockIndex* pindex) { continue; } - //Check for unspent inputs or spend less than N Blocks ago. (Sprout) - for (auto & pair : pwtx->mapSproutNoteData) { - SproutNoteData nd = pair.second; - if (!nd.nullifier || pwalletMain->GetSproutSpendDepth(*nd.nullifier) <= fDeleteTransactionsAfterNBlocks) { - LogPrint("deletetx","DeleteTx - Unspent sprout input tx %s\n", pwtx->GetHash().ToString()); - deleteTx = false; - continue; - } - } - if (!deleteTx) { txSaveCount++; continue; } - //Check for outputs that no longer have parents in the wallet. Exclude parents that are in the same transaction. (Sprout) - for (int i = 0; i < pwtx->vjoinsplit.size(); i++) { - const JSDescription& jsdesc = pwtx->vjoinsplit[i]; - for (const uint256 &nullifier : jsdesc.nullifiers) { - // JSOutPoint op = pwalletMain->mapSproutNullifiersToNotes[nullifier]; - if (pwalletMain->IsSproutNullifierFromMe(nullifier)) { - const uint256& parentHash = pwalletMain->mapSproutNullifiersToNotes[nullifier].hash; - const CWalletTx* parent = pwalletMain->GetWalletTx(parentHash); - if (parent != NULL && parentHash != wtxid) { - LogPrint("deletetx","DeleteTx - Parent of sprout tx %s found\n", pwtx->GetHash().ToString()); - deleteTx = false; - continue; - } - } - } - } - if (!deleteTx) { txSaveCount++; continue; From 2324e8ca4b5e6dbd34a51e9e415493742e285464 Mon Sep 17 00:00:00 2001 From: ssadler Date: Mon, 27 Apr 2020 16:10:30 -0300 Subject: [PATCH 18/98] fix fingerprint encoding --- src/cryptoconditions/src/cryptoconditions.c | 20 +++++++++++------- src/cryptoconditions/src/internal.h | 2 +- .../tests/test_failure_modes.py | 21 +++++++++++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 74949affc..f7acde1aa 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -117,14 +117,15 @@ uint32_t fromAsnSubtypes(const ConditionTypes_t types) { size_t cc_conditionBinary(const CC *cond, unsigned char *buf) { Condition_t *asn = calloc(1, sizeof(Condition_t)); - asnCondition(cond, asn); + bool r = asnCondition(cond, asn); + size_t out = 0; + if (!r) goto end; asn_enc_rval_t rc = der_encode_to_buffer(&asn_DEF_Condition, asn, buf, 1000); - if (rc.encoded == -1) { - fprintf(stderr, "CONDITION NOT ENCODED\n"); - return 0; - } + if (rc.encoded == -1) goto end; + out = rc.encoded; +end: ASN_STRUCT_FREE(asn_DEF_Condition, asn); - return rc.encoded; + return out; } @@ -140,17 +141,22 @@ size_t cc_fulfillmentBinary(const CC *cond, unsigned char *buf, size_t length) { } -void asnCondition(const CC *cond, Condition_t *asn) { +bool asnCondition(const CC *cond, Condition_t *asn) { asn->present = cc_isAnon(cond) ? cond->conditionType->asnType : cond->type->asnType; // This may look a little weird - we dont have a reference here to the correct // union choice for the condition type, so we just assign everything to the threshold // type. This works out nicely since the union choices have the same binary interface. + CompoundSha256Condition_t *choice = &asn->choice.thresholdSha256; choice->cost = cc_getCost(cond); choice->fingerprint.buf = cond->type->fingerprint(cond); + if (choice->fingerprint.buf == 0) { + return 0; + } choice->fingerprint.size = 32; choice->subtypes = asnSubtypes(cond->type->getSubtypes(cond)); + return 1; } diff --git a/src/cryptoconditions/src/internal.h b/src/cryptoconditions/src/internal.h index 790e28962..e2525cbe4 100644 --- a/src/cryptoconditions/src/internal.h +++ b/src/cryptoconditions/src/internal.h @@ -65,7 +65,7 @@ extern int CCTypeRegistryLength; */ uint32_t fromAsnSubtypes(ConditionTypes_t types); CC *mkAnon(const Condition_t *asnCond); -void asnCondition(const CC *cond, Condition_t *asn); +bool asnCondition(const CC *cond, Condition_t *asn); Condition_t *asnConditionNew(const CC *cond); Fulfillment_t *asnFulfillmentNew(const CC *cond); struct CC *fulfillmentToCC(Fulfillment_t *ffill); diff --git a/src/cryptoconditions/tests/test_failure_modes.py b/src/cryptoconditions/tests/test_failure_modes.py index 59b0b3f24..435e20c88 100644 --- a/src/cryptoconditions/tests/test_failure_modes.py +++ b/src/cryptoconditions/tests/test_failure_modes.py @@ -82,4 +82,25 @@ def test_malleability_checked(): assert not cc_rfb(b'\xa2\x13\xa0\x0f\xa0\x06\x80\x04abcd\xa0\x05\x80\x03abc\xa1\x00') +def test_large_threshold(): + conds = [{ + 'type': "secp256k1-sha-256", + "publicKey": "02D5D969305535AC29A77079C11D4F0DD40661CF96E04E974A5E8D7E374EE225AA" + }] + + for i in range(250): + conds.append({ + "type": "eval-sha-256", + "code": "VEVTVAE" + }) + + r = jsonRPC("encodeCondition", { + "type": "threshold-sha-256", + "subfulfillments": conds, + "threshold": 251 + }) + assert 'error' not in r, r + + + so.cc_conditionUri.restype = ctypes.c_char_p From eabcce62f7ddc89d4a6b322e89c8bf3e831e25e6 Mon Sep 17 00:00:00 2001 From: ssadler Date: Thu, 7 May 2020 22:32:59 -0300 Subject: [PATCH 19/98] return void where possible and pass references to indicate that a NULL result is impossible --- src/cryptoconditions/src/anon.c | 5 +---- src/cryptoconditions/src/cryptoconditions.c | 16 ++++++---------- src/cryptoconditions/src/ed25519.c | 5 ++--- src/cryptoconditions/src/eval.c | 9 +++------ .../src/include/secp256k1/src/ecmult_const.h | 2 +- src/cryptoconditions/src/internal.h | 6 +++--- src/cryptoconditions/src/prefix.c | 7 +++---- src/cryptoconditions/src/preimage.c | 7 ++----- src/cryptoconditions/src/secp256k1.c | 5 ++--- src/cryptoconditions/src/threshold.c | 6 ++---- src/cryptoconditions/src/utils.c | 6 ++---- 11 files changed, 27 insertions(+), 47 deletions(-) diff --git a/src/cryptoconditions/src/anon.c b/src/cryptoconditions/src/anon.c index 55d7a3b7f..6a4de4b0b 100644 --- a/src/cryptoconditions/src/anon.c +++ b/src/cryptoconditions/src/anon.c @@ -53,11 +53,8 @@ static void anonToJSON(const CC *cond, cJSON *params) { } -static unsigned char *anonFingerprint(const CC *cond) { - unsigned char *out = calloc(1, 32); - //fprintf(stderr,"anon fingerprint %p %p\n",out,cond->fingerprint); +static void anonFingerprint(const CC *cond, uint8_t *out) { memcpy(out, cond->fingerprint, 32); - return out; } diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index f7acde1aa..303b9aa41 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -65,8 +65,8 @@ void appendUriSubtypes(uint32_t mask, unsigned char *buf) { char *cc_conditionUri(const CC *cond) { - unsigned char *fp = cond->type->fingerprint(cond); - if (!fp) return NULL; + unsigned char *fp = calloc(1, 32); + cond->type->fingerprint(cond, fp); unsigned char *encoded = base64_encode(fp, 32); @@ -117,9 +117,8 @@ uint32_t fromAsnSubtypes(const ConditionTypes_t types) { size_t cc_conditionBinary(const CC *cond, unsigned char *buf) { Condition_t *asn = calloc(1, sizeof(Condition_t)); - bool r = asnCondition(cond, asn); + asnCondition(cond, asn); size_t out = 0; - if (!r) goto end; asn_enc_rval_t rc = der_encode_to_buffer(&asn_DEF_Condition, asn, buf, 1000); if (rc.encoded == -1) goto end; out = rc.encoded; @@ -141,7 +140,7 @@ size_t cc_fulfillmentBinary(const CC *cond, unsigned char *buf, size_t length) { } -bool asnCondition(const CC *cond, Condition_t *asn) { +void asnCondition(const CC *cond, Condition_t *asn) { asn->present = cc_isAnon(cond) ? cond->conditionType->asnType : cond->type->asnType; // This may look a little weird - we dont have a reference here to the correct @@ -150,13 +149,10 @@ bool asnCondition(const CC *cond, Condition_t *asn) { CompoundSha256Condition_t *choice = &asn->choice.thresholdSha256; choice->cost = cc_getCost(cond); - choice->fingerprint.buf = cond->type->fingerprint(cond); - if (choice->fingerprint.buf == 0) { - return 0; - } choice->fingerprint.size = 32; + choice->fingerprint.buf = calloc(1, 32); + cond->type->fingerprint(cond, choice->fingerprint.buf); choice->subtypes = asnSubtypes(cond->type->getSubtypes(cond)); - return 1; } diff --git a/src/cryptoconditions/src/ed25519.c b/src/cryptoconditions/src/ed25519.c index 8d73d3cf1..e4d090d1e 100644 --- a/src/cryptoconditions/src/ed25519.c +++ b/src/cryptoconditions/src/ed25519.c @@ -25,11 +25,10 @@ struct CCType CC_Ed25519Type; -static unsigned char *ed25519Fingerprint(const CC *cond) { +static void ed25519Fingerprint(const CC *cond, uint8_t *out) { Ed25519FingerprintContents_t *fp = calloc(1, sizeof(Ed25519FingerprintContents_t)); - //fprintf(stderr,"ed25519 fingerprint %p %p\n",fp,cond->publicKey); OCTET_STRING_fromBuf(&fp->publicKey, cond->publicKey, 32); - return hashFingerprintContents(&asn_DEF_Ed25519FingerprintContents, fp); + hashFingerprintContents(&asn_DEF_Ed25519FingerprintContents, fp, out); } diff --git a/src/cryptoconditions/src/eval.c b/src/cryptoconditions/src/eval.c index 99ff1ebf5..a18d51202 100644 --- a/src/cryptoconditions/src/eval.c +++ b/src/cryptoconditions/src/eval.c @@ -25,11 +25,8 @@ struct CCType CC_EvalType; -static unsigned char *evalFingerprint(const CC *cond) { - unsigned char *hash = calloc(1, 32); - //fprintf(stderr,"evalfingerprint %p %p\n",hash,cond->code); - sha256(cond->code, cond->codeLength, hash); - return hash; +static void evalFingerprint(const CC *cond, uint8_t *out) { + sha256(cond->code, cond->codeLength, out); } @@ -105,7 +102,7 @@ static uint32_t evalSubtypes(const CC *cond) { */ int jsonVerifyEval(CC *cond, void *context) { if (cond->codeLength == 5 && 0 == memcmp(cond->code, "TEST", 4)) { - return cond->code[5]; + return cond->code[4]; } fprintf(stderr, "Cannot verify eval; user function unknown\n"); return 0; diff --git a/src/cryptoconditions/src/include/secp256k1/src/ecmult_const.h b/src/cryptoconditions/src/include/secp256k1/src/ecmult_const.h index bdb9ae43a..5a36ba40b 100644 --- a/src/cryptoconditions/src/include/secp256k1/src/ecmult_const.h +++ b/src/cryptoconditions/src/include/secp256k1/src/ecmult_const.h @@ -36,4 +36,4 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons #endif - +#endif diff --git a/src/cryptoconditions/src/internal.h b/src/cryptoconditions/src/internal.h index e2525cbe4..7cfcaa225 100644 --- a/src/cryptoconditions/src/internal.h +++ b/src/cryptoconditions/src/internal.h @@ -41,7 +41,7 @@ typedef struct CCType { char name[100]; Condition_PR asnType; int (*visitChildren)(CC *cond, CCVisitor visitor); - unsigned char *(*fingerprint)(const CC *cond); + void (*fingerprint)(const CC *cond, uint8_t *fp); unsigned long (*getCost)(const CC *cond); uint32_t (*getSubtypes)(const CC *cond); CC *(*fromJSON)(const cJSON *params, char *err); @@ -65,7 +65,7 @@ extern int CCTypeRegistryLength; */ uint32_t fromAsnSubtypes(ConditionTypes_t types); CC *mkAnon(const Condition_t *asnCond); -bool asnCondition(const CC *cond, Condition_t *asn); +void asnCondition(const CC *cond, Condition_t *asn); Condition_t *asnConditionNew(const CC *cond); Fulfillment_t *asnFulfillmentNew(const CC *cond); struct CC *fulfillmentToCC(Fulfillment_t *ffill); @@ -77,7 +77,7 @@ struct CCType *getTypeByAsnEnum(Condition_PR present); */ unsigned char *base64_encode(const unsigned char *data, size_t input_length); unsigned char *base64_decode(const unsigned char *data_, size_t *output_length); -unsigned char *hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp); +void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t* out); void dumpStr(unsigned char *str, size_t len); int checkString(const cJSON *value, char *key, char *err); int checkDecodeBase64(const cJSON *value, char *key, char *err, unsigned char **data, size_t *size); diff --git a/src/cryptoconditions/src/prefix.c b/src/cryptoconditions/src/prefix.c index 45c6d8033..67dc6f644 100644 --- a/src/cryptoconditions/src/prefix.c +++ b/src/cryptoconditions/src/prefix.c @@ -37,13 +37,12 @@ static int prefixVisitChildren(CC *cond, CCVisitor visitor) { } -static unsigned char *prefixFingerprint(const CC *cond) { +static void prefixFingerprint(const CC *cond, uint8_t *out) { PrefixFingerprintContents_t *fp = calloc(1, sizeof(PrefixFingerprintContents_t)); - //fprintf(stderr,"prefixfinger %p %p\n",fp,cond->prefix); - asnCondition(cond->subcondition, &fp->subcondition); // TODO: check asnCondition for safety + asnCondition(cond->subcondition, &fp->subcondition); fp->maxMessageLength = cond->maxMessageLength; OCTET_STRING_fromBuf(&fp->prefix, cond->prefix, cond->prefixLength); - return hashFingerprintContents(&asn_DEF_PrefixFingerprintContents, fp); + hashFingerprintContents(&asn_DEF_PrefixFingerprintContents, fp, out); } diff --git a/src/cryptoconditions/src/preimage.c b/src/cryptoconditions/src/preimage.c index 9e7fe12f4..a45e621d4 100644 --- a/src/cryptoconditions/src/preimage.c +++ b/src/cryptoconditions/src/preimage.c @@ -44,11 +44,8 @@ static unsigned long preimageCost(const CC *cond) { } -static unsigned char *preimageFingerprint(const CC *cond) { - unsigned char *hash = calloc(1, 32); - //fprintf(stderr,"preimage %p %p\n",hash,cond->preimage); - sha256(cond->preimage, cond->preimageLength, hash); - return hash; +static void preimageFingerprint(const CC *cond, uint8_t *out) { + sha256(cond->preimage, cond->preimageLength, out); } diff --git a/src/cryptoconditions/src/secp256k1.c b/src/cryptoconditions/src/secp256k1.c index a16115bb8..44ff1f0e2 100644 --- a/src/cryptoconditions/src/secp256k1.c +++ b/src/cryptoconditions/src/secp256k1.c @@ -88,11 +88,10 @@ void initVerify() { } -static unsigned char *secp256k1Fingerprint(const CC *cond) { +static void secp256k1Fingerprint(const CC *cond, uint8_t *out) { Secp256k1FingerprintContents_t *fp = calloc(1, sizeof(Secp256k1FingerprintContents_t)); - //fprintf(stderr,"secpfinger %p %p size %d vs %d\n",fp,cond->publicKey,(int32_t)sizeof(Secp256k1FingerprintContents_t),(int32_t)SECP256K1_PK_SIZE); OCTET_STRING_fromBuf(&fp->publicKey, cond->publicKey, SECP256K1_PK_SIZE); - return hashFingerprintContents(&asn_DEF_Secp256k1FingerprintContents, fp); + hashFingerprintContents(&asn_DEF_Secp256k1FingerprintContents, fp, out); } diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index 9547f4f8c..e94666c3d 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -94,17 +94,15 @@ static int cmpConditionBin(const void *a, const void *b) { } -static unsigned char *thresholdFingerprint(const CC *cond) { - /* Create fingerprint */ +static void thresholdFingerprint(const CC *cond, uint8_t *out) { ThresholdFingerprintContents_t *fp = calloc(1, sizeof(ThresholdFingerprintContents_t)); - //fprintf(stderr,"thresholdfinger %p\n",fp); fp->threshold = cond->threshold; for (int i=0; isize; i++) { Condition_t *asnCond = asnConditionNew(cond->subconditions[i]); asn_set_add(&fp->subconditions2, asnCond); } qsort(fp->subconditions2.list.array, cond->size, sizeof(Condition_t*), cmpConditionBin); - return hashFingerprintContents(&asn_DEF_ThresholdFingerprintContents, fp); + hashFingerprintContents(&asn_DEF_ThresholdFingerprintContents, fp, out); } diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index 6a2167119..ebb2bd143 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -210,7 +210,7 @@ void jsonAddBase64(cJSON *params, char *key, unsigned char *bin, size_t size) { } -unsigned char *hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp) { +void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t *out) { unsigned char buf[BUF_SIZE]; asn_enc_rval_t rc = der_encode_to_buffer(asnType, fp, buf, BUF_SIZE); ASN_STRUCT_FREE(*asnType, fp); @@ -218,9 +218,7 @@ unsigned char *hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp) fprintf(stderr, "Encoding fingerprint failed\n"); return 0; } - unsigned char *hash = calloc(1,32); - sha256(buf, rc.encoded, hash); - return hash; + sha256(buf, rc.encoded, out); } From f3a4f773687ee6e29eff4801e9880f6c4282827d Mon Sep 17 00:00:00 2001 From: DenioD <41270280+DenioD@users.noreply.github.com> Date: Tue, 19 May 2020 10:03:53 +0200 Subject: [PATCH 20/98] port expired transaction notify from Zcash. Issue #110 --- src/init.cpp | 11 +++++++++++ src/main.cpp | 6 +++++- src/txmempool.cpp | 5 ++++- src/txmempool.h | 2 +- src/ui_interface.h | 3 +++ 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index ac15db192..fd0303786 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -399,6 +399,7 @@ std::string HelpMessage(HelpMessageMode mode) #ifndef _WIN32 strUsage += HelpMessageOpt("-pid=", strprintf(_("Specify pid file (default: %s)"), "komodod.pid")); #endif + strUsage += HelpMessageOpt("-txexpirynotify=", _("Execute command when transaction expires (%s in cmd is replaced by transaction id)")); strUsage += HelpMessageOpt("-prune=", strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode disables wallet support and is incompatible with -txindex. " "Warning: Reverting this setting requires re-downloading the entire blockchain. " "(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); @@ -618,6 +619,14 @@ static void BlockNotifyCallback(const uint256& hashNewTip) boost::thread t(runCommand, strCmd); // thread runs free } +static void TxExpiryNotifyCallback(const uint256& txid) +{ + std::string strCmd = GetArg("-txexpirynotify", ""); + + boost::replace_all(strCmd, "%s", txid.GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free +} + struct CImportingNow { CImportingNow() { @@ -2114,6 +2123,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-blocknotify")) uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); + if (mapArgs.count("-txexpirynotify")) + uiInterface.NotifyTxExpiration.connect(TxExpiryNotifyCallback); if ( KOMODO_REWIND >= 0 ) { uiInterface.InitMessage(_("Activating best chain...")); diff --git a/src/main.cpp b/src/main.cpp index 17b89a76b..3426facd7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4210,7 +4210,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * mempool.removeForBlock(pblock->vtx, pindexNew->GetHeight(), txConflicted, !IsInitialBlockDownload()); // Remove transactions that expire at new block height from mempool - mempool.removeExpired(pindexNew->GetHeight()); + auto ids = mempool.removeExpired(pindexNew->GetHeight()); + + for (auto id : ids) { + uiInterface.NotifyTxExpiration(id); + } // Update chainActive & related variables. UpdateTip(pindexNew); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 8a99a99e6..307be723e 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -513,7 +513,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); extern char ASSETCHAINS_SYMBOL[]; -void CTxMemPool::removeExpired(unsigned int nBlockHeight) +std::vector CTxMemPool::removeExpired(unsigned int nBlockHeight) { CBlockIndex *tipindex; // Remove expired txs from the mempool @@ -528,11 +528,14 @@ void CTxMemPool::removeExpired(unsigned int nBlockHeight) transactionsToRemove.push_back(tx); } } + std::vector ids; for (const CTransaction& tx : transactionsToRemove) { list removed; remove(tx, removed, true); + ids.push_back(tx.GetHash()); LogPrint("mempool", "Removing expired txid: %s\n", tx.GetHash().ToString()); } + return ids; } /** diff --git a/src/txmempool.h b/src/txmempool.h index f8aa0e9a7..59eeb0d98 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -218,7 +218,7 @@ public: void removeWithAnchor(const uint256 &invalidRoot, ShieldedType type); void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags); void removeConflicts(const CTransaction &tx, std::list& removed); - void removeExpired(unsigned int nBlockHeight); + std::vector removeExpired(unsigned int nBlockHeight); void removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, std::list& conflicts, bool fCurrentEstimate = true); void removeWithoutBranchId(uint32_t nMemPoolBranchId); diff --git a/src/ui_interface.h b/src/ui_interface.h index ee0fd9113..59a549a9d 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -98,6 +98,9 @@ public: /** New block has been accepted */ boost::signals2::signal NotifyBlockTip; + + /** Transaction expired */ + boost::signals2::signal NotifyTxExpiration; }; extern CClientUIInterface uiInterface; From 6e4be99c21fb0c14d0475321a11cf136b6b32d1a Mon Sep 17 00:00:00 2001 From: DenioD <41270280+DenioD@users.noreply.github.com> Date: Tue, 19 May 2020 10:20:28 +0200 Subject: [PATCH 21/98] Add dpow season 4 pubkeys Issue #109 --- src/komodo_defs.h | 71 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 34b1cc364..fa22a49ba 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -47,7 +47,7 @@ // 7113400 = 5x current KMD blockheight. // to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. -#define NUM_KMD_SEASONS 4 +#define NUM_KMD_SEASONS 5 #define NUM_KMD_NOTARIES 64 // $ ./contrib/block_time.pl 166250 @@ -329,7 +329,74 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"gt_AR", "0307c1cf89bd8ed4db1b09a0a98cf5f746fc77df3803ecc8611cf9455ec0ce6960" }, {"patchkez_SH", "03d7c187689bf829ca076a30bbf36d2e67bb74e16a3290d8a55df21d6cb15c80c1" }, {"decker_AR", "02a85540db8d41c7e60bf0d33d1364b4151cad883dd032878ea4c037f67b769635" } - } + }, + { + // Season 4 + { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, + { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, + { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, + { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, + { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, + { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, + { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, + { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, + { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, + { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, + { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, + { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, + { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, + { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, + { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, + { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, + { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, + { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, + { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, + { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, + { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, + { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, + { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, + { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, + { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, + { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, + { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, + { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, + { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, + { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, + { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, + { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, + { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, + { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, + { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, + { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, + { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, + { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, + { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, + { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, + { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, + { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, + { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, + { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, + { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, + { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, + { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, + { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, + { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, + { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, + { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, + { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } + } }; #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) From b879f536e98fb99f4347dcfea6892b611756b765 Mon Sep 17 00:00:00 2001 From: ca333 Date: Sat, 14 Mar 2020 23:18:16 +0100 Subject: [PATCH 22/98] debug.log spam prevention --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3426facd7..20d4a0355 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1224,9 +1224,9 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde if (IsExpiredTx(tx, nHeight)) { // Don't increase banscore if the transaction only just expired int expiredDosLevel = IsExpiredTx(tx, nHeight - 1) ? (dosLevel > 10 ? dosLevel : 10) : 0; - string strHex = EncodeHexTx(tx); + //string strHex = EncodeHexTx(tx); //fprintf(stderr, "transaction exipred.%s\n",strHex.c_str()); - return state.DoS(expiredDosLevel, error("ContextualCheckTransaction(): transaction %s is expired, expiry block %i vs current block %i\n txhex.%s",tx.GetHash().ToString(),tx.nExpiryHeight,nHeight,strHex), REJECT_INVALID, "tx-overwinter-expired"); + return state.DoS(expiredDosLevel, error("ContextualCheckTransaction(): transaction %s is expired, expiry block %i vs current block %i\n",tx.GetHash().ToString(),tx.nExpiryHeight,nHeight), REJECT_INVALID, "tx-overwinter-expired"); } } From 3199c01328989ccca6641d7014dfbc80ba2ddd4e Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sun, 26 Jan 2020 07:34:49 +0300 Subject: [PATCH 23/98] =?UTF-8?q?CVE-2018=E2=80=9320586=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - https://medium.com/@lukedashjr/cve-2018-20586-disclosure-ff3e1ab9a21f - https://github.com/bitcoin/bitcoin/pull/14618/files --- src/httpserver.cpp | 11 ++++++++--- src/utilstrencodings.cpp | 3 ++- src/utilstrencodings.h | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index e1d235665..603e1e6ae 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -11,6 +11,7 @@ #include "rpc/protocol.h" // For HTTP status codes #include "sync.h" #include "ui_interface.h" +#include "utilstrencodings.h" #include #include @@ -251,21 +252,25 @@ static void http_request_cb(struct evhttp_request* req, void* arg) { std::unique_ptr hreq(new HTTPRequest(req)); - LogPrint("http", "Received a %s request for %s from %s\n", - RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString()); - // Early address-based allow check if (!ClientAllowed(hreq->GetPeer())) { + LogPrint("http", "HTTP request from %s rejected: Client network is not allowed RPC access\n", + hreq->GetPeer().ToString()); hreq->WriteReply(HTTP_FORBIDDEN); return; } // Early reject unknown HTTP methods if (hreq->GetRequestMethod() == HTTPRequest::UNKNOWN) { + LogPrint("http", "HTTP request from %s rejected: Unknown HTTP request method\n", + hreq->GetPeer().ToString()); hreq->WriteReply(HTTP_BADMETHOD); return; } + LogPrint("http", "Received a %s request for %s from %s\n", + RequestMethodString(hreq->GetRequestMethod()), SanitizeString(hreq->GetURI(), SAFE_CHARS_URI).substr(0, 100), hreq->GetPeer().ToString()); + // Find registered handler for prefix std::string strURI = hreq->GetURI(); std::string path; diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index d4bba72ee..132ae82ab 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -20,7 +20,8 @@ static const string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO static const string SAFE_CHARS[] = { CHARS_ALPHA_NUM + " .,;_/:?@()", // SAFE_CHARS_DEFAULT - CHARS_ALPHA_NUM + " .,;_?@" // SAFE_CHARS_UA_COMMENT + CHARS_ALPHA_NUM + " .,;_?@", // SAFE_CHARS_UA_COMMENT + CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%" // SAFE_CHARS_URI }; string SanitizeString(const string& str, int rule) diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 37a07ea06..2d851093f 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -26,7 +26,8 @@ enum SafeChars { SAFE_CHARS_DEFAULT, //!< The full set of allowed chars - SAFE_CHARS_UA_COMMENT //!< BIP-0014 subset + SAFE_CHARS_UA_COMMENT, //!< BIP-0014 subset + SAFE_CHARS_URI //!< Chars allowed in URIs (RFC 3986) }; std::string SanitizeFilename(const std::string& str); From bde1f3c632556fdfa4ac210fa0b7994a76c5a911 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 27 Jan 2020 05:00:24 +0300 Subject: [PATCH 24/98] limit blockchain progress to a max of 1.000000 Issue: https://github.com/zcash/zcash/issues/3161 Fix commit: https://github.com/zcash/zcash/pull/4176/commits/b3594b52739c96105a3f6976924a9075b1c5bbe2 --- src/checkpoints.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 7fd94e4e7..026475f88 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -74,7 +74,7 @@ namespace Checkpoints { fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor; } - return fWorkBefore / (fWorkBefore + fWorkAfter); + return std::min(fWorkBefore / (fWorkBefore + fWorkAfter), 1.0); } int GetTotalBlocksEstimate(const CChainParams::CCheckpointData& data) From c7d96194d6edb348febaea95b829032a504168b8 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 19 Mar 2020 01:55:56 +0300 Subject: [PATCH 25/98] [test] proper removing of txes that violates interest validation from mempool In CreateNewBlock of miner https://github.com/KomodoPlatform/komodo/blob/master/src/miner.cpp#L331 we have a condition that prevents miners to include certain txes in block if tx violates komodo_validate_interest check. so, if such txes will exist in mempool and in some reason they was not miner earlier, if they have nExpiryHeight = 0 - they NEVER will be included in block by miners. Also, code in CTxMemPool::removeExpired that should remove such txes from mempool didn't do it due to mistake. As a result these txes stucks in mempool. No one can mine it, bcz no one can include it in block, and no one get success to remove it from mempool. Look on old code: ``` (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(...) ) < 0 ``` But should be: ``` (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(...) < 0 ) ``` Bcz we should compare with 0 result of komodo_validate_interest, but we had different behaviour, due to typo. --- src/txmempool.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 307be723e..ca0ed7f51 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -523,8 +523,12 @@ std::vector CTxMemPool::removeExpired(unsigned int nBlockHeight) { const CTransaction& tx = it->GetTx(); tipindex = chainActive.LastTip(); - if (IsExpiredTx(tx, nBlockHeight) || (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(tx,tipindex->GetHeight()+1,tipindex->GetMedianTimePast() + 777,0)) < 0) + + bool fInterestNotValidated = ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(tx,tipindex->GetHeight()+1,tipindex->GetMedianTimePast() + 777,0) < 0; + if (IsExpiredTx(tx, nBlockHeight) || fInterestNotValidated) { + if (fInterestNotValidated && tipindex != 0) + LogPrintf("Removing interest violate txid.%s nHeight.%d nTime.%u vs locktime.%u\n",tx.GetHash().ToString(),tipindex->GetHeight()+1,tipindex->GetMedianTimePast() + 777,tx.nLockTime); transactionsToRemove.push_back(tx); } } From 2c60f2ffaeec2a9a8e1960de672bad4f2d965b53 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Tue, 25 Feb 2020 17:56:17 +0300 Subject: [PATCH 26/98] disable assertion when -debug arg is passed --- src/miner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/miner.cpp b/src/miner.cpp index 8d3c5d4c4..a91fa9527 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -340,7 +340,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 if (!mempool.mapTx.count(txin.prevout.hash)) { LogPrintf("ERROR: mempool transaction missing input\n"); - if (fDebug) assert("mempool transaction missing input" == 0); + // if (fDebug) assert("mempool transaction missing input" == 0); fMissingInputs = true; if (porphan) vOrphan.pop_back(); From c0834c3cb7bca48b2b9f701c2e2000aa3f2ed919 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 29 May 2020 01:55:00 -0400 Subject: [PATCH 27/98] S4 dpow notaries --- src/komodo_defs.h | 130 +++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index fa22a49ba..6d867b229 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -331,71 +331,71 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"decker_AR", "02a85540db8d41c7e60bf0d33d1364b4151cad883dd032878ea4c037f67b769635" } }, { - // Season 4 - { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, - { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, - { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, - { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, - { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, - { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, - { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, - { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, - { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, - { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, - { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, - { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, - { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, - { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, - { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, - { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, - { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, - { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, - { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, - { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, - { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, - { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, - { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, - { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, - { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, - { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, - { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, - { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, - { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, - { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, - { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, - { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, - { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, - { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, - { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, - { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, - { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, - { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, - { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, - { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, - { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, - { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, - { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, - { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, - { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, - { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, - { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, - { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, - { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, - { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, - { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, - { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } + // Season 4 https://github.com/KomodoPlatform/dPoW/blob/s4/iguana/3rd_party + {"alien_AR", "024f20c096b085308e21893383f44b4faf1cdedea9ad53cc7d7e7fbfa0c30c1e71" }, + {"alien_EU", "022b85908191788f409506ebcf96a892f3274f352864c3ed566c5a16de63953236" }, + {"alien_NA", "022f62b56ddfd07c9860921c701285ac39bb3ac8f6f083d1b59c8f4943be3de162" }, + {"alright_DEV", "03b6f9493658bdd102503585a08ae642b49d6a68fb69ac3626f9737cd7581abdfa" }, + {"artemii235_DEV", "037a20916d2e9ea575300ac9d729507c23a606b9a200c8e913d7c9832f912a1fa7" }, + {"chainmakers_NA", "028803e07bcc521fde264b7191a944f9b3612e8ee4e24a99bcd903f6976240839a" }, + {"chainzilla_SH", "0311dde03c2dd654ce78323b718ed3ad73a464d1bde97820f3395f54788b5420dd" }, + {"chmex_AR", "030cd487e10fbf142e0e8d582e702ecb775f378569c3cb5acd0ff97b6b12803588" }, + {"chmex_EU", "030bf7bd7ad0515c33b5d5d9a91e0729baf801b9002f80495ae535ea1cebb352cb" }, + {"cipi_EU", "026f4f66385daaf8313ef30ffe4988e7db497132682dca185a70763d93e1417d9d" }, + {"cipi_NA", "03f4e69edcb4fa3b2095cb8cb1ca010f4ec4972eac5d8822397e5c8d87aa21a739" }, + {"daemonfox_NA", "023c7584b1006d4a62a4b4c9c1ede390a3789316547897d5ed49ff9385a3acb411" }, + {"dappvader_SH", "025199bc04bcb8a17976d9fe8bc87763a6150c2727321aa59bf34a2b49f2f3a0ce" }, + {"decker_AR", "02a85540db8d41c7e60bf0d33d1364b4151cad883dd032878ea4c037f67b769635" }, + {"decker_DEV", "02fca8ee50e49f480de275745618db7b0b3680b0bdcce7dcae7d2e0fd5c3345744" }, + {"decker_EU", "027777775b89ff548c3be54fb0c9455437d87f38bfce83bdef113899881b219c9e" }, + {"dragonhound_NA", "029912212d370ee0fb4d38eefd8bfcd8ab04e2c3b0354020789c29ddf2a35c72d6" }, + {"dudezmobi_AR", "033c121d3f8d450174674a73f3b7f140b2717a7d51ea19ee597e2e8e8f9d5ed87f" }, + {"etszombi_AR", "03bfcbca83f11e622fa4eed9a1fa25dba377981ea3b22e3d0a4015f9a932af9272" }, + {"etszombi_EU", "03a5c083c78ba397970f20b544a01c13e7ed36ca8a5ae26d5fe7bd38b92b6a0c94" }, + {"fullmoon_AR", "03639bc56d3fecf856f17759a441c5893668e7c2d460f3d216798a413cd6766bb2" }, + {"fullmoon_NA", "03e388bcc579ac2675f8fadfa921eec186dcea8d2b43de1eed6caba23d5a962b74" }, + {"fullmoon_SH", "03a5cfda2b097c808834ccdd805828c811b519611feabdfe6b3644312e53f6748f" }, + {"gcharang_SH", "02a654037d12cdd609f4fad48e15ec54538e03f61fdae1acb855f16ebacac6bd73" }, + {"greer_NA", "0262da6aaa0b295b8e2f120035924758a4a630f899316dc63ee15ef03e9b7b2b23" }, + {"indenodes_AR", "0242778789986d614f75bcf629081651b851a12ab1cc10c73995b27b90febb75a2" }, + {"indenodes_EU", "03a416533cace0814455a1bb1cd7861ce825a543c6f6284a432c4c8d8875b7ace9" }, + {"indenodes_NA", "02b3908eda4078f0e9b6704451cdc24d418e899c0f515fab338d7494da6f0a647b" }, + {"indenodes_SH", "031d1584cf0eb4a2d314465e49e2677226b1615c3718013b8d6b4854c15676a58c" }, + {"karasugoi_NA", "02f803e6f159824a181cc5d709f3d1e7ff65f19e1899920724aeb4e3d2d869f911" }, + {"madmax_AR", "027afddbcf690230dd8d435ec16a7bfb0083e6b77030f763437f291dfc40a579d0" }, + {"madmax_EU", "0397ec3a4ad84b3009566d260c89f1c4404e86e5d044964747c9371277e38f5995" }, + {"madmax_NA", "036d3afebe1eab09f4c38c3ee6a4659ad390f3df92787c11437a58c59a29e408e6" }, + {"marmarachain_AR", "028690ca1e3afdf8a38b421f6a41f5ff407afc96d5a7a6a488330aae26c8b086bb" }, + {"mcrypt_SH", "027a4ca7b11d3456ff558c08bb04483a89c7f383448461fd0b6b3b07424aabe9a4" }, + {"metaphilibert_AR", "0239e34ad22957bbf4c8df824401f237b2afe8d40f7a645ecd43e8f27dde1ab0da" }, + {"metaphilibert_SH", "03b21ff042bf1730b28bde43f44c064578b41996117ac7634b567c3773089e3be3" }, + {"mihailo_EU", "036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252" }, + {"mrlynch_AR", "03e67440141f53a08684c329ebc852b018e41f905da88e52aa4a6dc5aa4b12447a" }, + {"mylo_SH", "026d5f29d09ff3f33e14db4811606249b2438c6bcf964876714f81d1f2d952acde" }, + {"node9_EU", "0392e4c9400e69f28c6b9e89d586da69d5a6af7702f1045eaa6ebc1996f0496e1f" }, + {"nodeone_NA", "0310a249c6c2dcc29f2135715138a9ddb8e01c0eab701cbd0b96d9cec660dbdc58" }, + {"nutellalicka_SH", "0284c4d3cb97dd8a32d10fb32b1855ae18cf845dad542e3b8937ca0e998fb54ecc" }, + {"oszy_EU", "03c53bd421de4a29ce68c8cc83f802e1181e77c08f8f16684490d61452ea8d023a" }, + {"patchkez_SH", "028c08db6e7242681f50db6c234fe3d6e12fb1a915350311be26373bac0d457d49" }, + {"pbca26_NA", "03c18431bb6bc95672f640f19998a196becd2851d5dcba4795fe8d85b7d77eab81" }, + {"peer2cloud_AR", "0243958faf9ae4d43b598b859ddc595c170c4cf50f8e4517d660ae5bc72aeb821b" }, + {"phba2061_EU", "03369187ce134bd7793ee34af7756fe1ab27202e09306491cdd5d8ad2c71697937" }, + {"phm87_SH", "03889a10f9df2caef57220628515693cf25316fe1b0693b0241419e75d0d0e66ed" }, + {"pirate_EU", "0240011b95cde819f298fe0f507b2260c9fecdab784924076d4d1e54c522103cb1" }, + {"pirate_NA", "02ad7ef25d2dd461e361120cd3efe7cbce5e9512c361e9185aac33dd303d758613" }, + {"pungocloud_SH", "02641c36ae6747b88150a463a1fe65cf7a9d1c00a64387c73f296f0b64e77c7d3f" }, + {"smdmitry_AR", "0397b7584cb29717b721c0c587d4462477efc1f36a56921f133c9d17b0cd7f278a" }, + {"starfleet_EU", "03c6e047218f34644ccba67e317b9da5d28e68bbbb6b9973aef1281d2bafa46496" }, + {"strob_NA", "02285bf2f9e96068ecac14bc6f770e394927b4da9f5ba833eaa9468b5d47f203a3" }, + {"strob_SH", "0213751a1c59d3489ca85b3d62a3d606dcef7f0428aa021c1978ea16fb38a2fad6" }, + {"swisscertifiers_EU", "02e7722ebba9f8b5ebfb4e87d4fa58cc75aef677535b9cfc060c7d9471aacd9c9e" }, + {"titomane_AR", "03958bd8d13fe6946b8d0d0fbbc3861c72542560d0276e80a4c6b5fe55bc758b81" }, + {"titomane_EU", "02276090e483db1a01a802456b10831b3b6e0a6ad3ece9b2a01f4aad0e480c8edc" }, + {"titomane_SH", "02abf206bafc8048dbdc042b8eb6b1e356ea5dbe149eae3532b4811d4905e5cf01" }, + {"tonyl_AR", "0229e499e3f2e065ced402ceb8aaf3d5ab8bd3793aa074305e9fa30772ce604908" }, + {"tonyl_DEV", "0258b77d7dcfc6c2628b0b6b438951a6e74201fb2cd180a795e4c37fcf8e78a678" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"zatjum_SH", "0241c5660ca540780be66603b1791127a1261d56abbcb7562c297eec8e4fc078fb" } } }; From ff0ce2b69a16bf2fa7c39bf2bafec0a2199c53d6 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 29 May 2020 02:08:21 -0400 Subject: [PATCH 28/98] Fix warning --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 20d4a0355..c75f51a28 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1327,7 +1327,7 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde )) { librustzcash_sapling_verification_ctx_free(ctx); - fprintf(stderr,"%s: Invalid sapling binding sig! tx=%s valueBalance=%li, bindingSig.size=%d\n", __func__, tx.GetHash().ToString().c_str(), tx.valueBalance, tx.bindingSig.size() ); + fprintf(stderr,"%s: Invalid sapling binding sig! tx=%s valueBalance=%li, bindingSig.size=%li\n", __func__, tx.GetHash().ToString().c_str(), tx.valueBalance, tx.bindingSig.size() ); return state.DoS(100, error("ContextualCheckTransaction(): Sapling binding signature invalid"), REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid"); } From 9c5a4e682e67b08153a998072a8f20d69fd60f3f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 29 May 2020 23:10:05 -0400 Subject: [PATCH 29/98] desprout --- src/wallet/wallet.cpp | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8d56fdfae..4422cde7b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2105,27 +2105,6 @@ void CWallet::GetSproutNoteWitnesses(std::vector notes, std::vector>& witnesses, uint256 &final_anchor) { - LOCK(cs_wallet); - witnesses.resize(notes.size()); - boost::optional rt; - int i = 0; - for (JSOutPoint note : notes) { - if (mapWallet.count(note.hash) && - mapWallet[note.hash].mapSproutNoteData.count(note) && - mapWallet[note.hash].mapSproutNoteData[note].witnesses.size() > 0) { - witnesses[i] = mapWallet[note.hash].mapSproutNoteData[note].witnesses.front(); - if (!rt) { - rt = witnesses[i]->root(); - } else { - assert(*rt == witnesses[i]->root()); - } - } - i++; - } - // All returned witnesses have the same anchor - if (rt) { - final_anchor = *rt; - } } void CWallet::GetSaplingNoteWitnesses(std::vector notes, From e35b7e21b3cf64acbd671edd8d2ca7e12cdd5952 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 29 May 2020 23:13:15 -0400 Subject: [PATCH 30/98] Less typing is nice --- build.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..2ae8514c3 --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# Copyright (c) 2019-2020 The Hush developers + +set -eu -o pipefail +./zcutil/build.sh $@ From 1010c7e8e453032710519d741d578bbace3586d7 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 29 May 2020 23:32:41 -0400 Subject: [PATCH 31/98] Throw a logic error instead of asserting when we see weird witness shenanigans --- src/wallet/wallet.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4422cde7b..3145bbd88 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2123,7 +2123,12 @@ void CWallet::GetSaplingNoteWitnesses(std::vector notes, if (!rt) { rt = witnesses[i]->root(); } else { - assert(*rt == witnesses[i]->root()); + if(*rt == witnesses[i]->root()) { + // Something is fucky + std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root:" << rt.GetHash(); + throw std::logic_error(err); + } + } } i++; From d265f782e77e8e262dc668372a32d4f79af9ef45 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 29 May 2020 23:35:11 -0400 Subject: [PATCH 32/98] desprout --- src/wallet/wallet.cpp | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3145bbd88..558f2020a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -234,25 +234,7 @@ bool CWallet::AddSaplingIncomingViewingKey( // Add spending key to keystore and persist to disk bool CWallet::AddSproutZKey(const libzcash::SproutSpendingKey &key) { - AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata - auto addr = key.address(); - - if (!CCryptoKeyStore::AddSproutSpendingKey(key)) - return false; - - // check if we need to remove from viewing keys - if (HaveSproutViewingKey(addr)) - RemoveSproutViewingKey(key.viewing_key()); - - if (!fFileBacked) - return true; - - if (!IsCrypted()) { - return CWalletDB(strWalletFile).WriteZKey(addr, - key, - mapSproutZKeyMetadata[addr]); - } - return true; + return false; } CPubKey CWallet::GenerateNewKey() @@ -2344,13 +2326,6 @@ bool CWallet::IsFromMe(const CTransaction& tx) const if (GetDebit(tx, ISMINE_ALL) > 0) { return true; } - for (const JSDescription& jsdesc : tx.vjoinsplit) { - for (const uint256& nullifier : jsdesc.nullifiers) { - if (IsSproutNullifierFromMe(nullifier)) { - return true; - } - } - } for (const SpendDescription &spend : tx.vShieldedSpend) { if (IsSaplingNullifierFromMe(spend.nullifier)) { return true; @@ -2488,18 +2463,6 @@ bool CWallet::LoadCryptedHDSeed(const uint256& seedFp, const std::vector nd : noteData) { - if (nd.first.js < vjoinsplit.size() && - nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) { - // Store the address and nullifier for the Note - mapSproutNoteData[nd.first] = nd.second; - } else { - // If FindMySproutNotes() was used to obtain noteData, - // this should never happen - throw std::logic_error("CWalletTx::SetSproutNoteData(): Invalid note"); - } - } } void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t ¬eData) From ab0576a72e80c3ba2f9c0411ec69ca98d30504ee Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 29 May 2020 23:47:28 -0400 Subject: [PATCH 33/98] desprout --- src/wallet/wallet.cpp | 76 +------------------------------------------ src/wallet/wallet.h | 11 ------- 2 files changed, 1 insertion(+), 86 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 558f2020a..a455cc2fe 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -117,22 +117,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const // Generate a new spending key and return its public payment address libzcash::SproutPaymentAddress CWallet::GenerateNewSproutZKey() { - AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata - - auto k = SproutSpendingKey::random(); - auto addr = k.address(); - - // Check for collision, even though it is unlikely to ever occur - if (CCryptoKeyStore::HaveSproutSpendingKey(addr)) - throw std::runtime_error("CWallet::GenerateNewSproutZKey(): Collision detected"); - - // Create new metadata - int64_t nCreationTime = GetTime(); - mapSproutZKeyMetadata[addr] = CKeyMetadata(nCreationTime); - - if (!AddSproutZKey(k)) - throw std::runtime_error("CWallet::GenerateNewSproutZKey(): AddSproutZKey failed"); - return addr; + throw std::runtime_error("unsupported"); } // Generate a new Sapling spending key and return its public payment address @@ -313,24 +298,6 @@ bool CWallet::AddCryptedSproutSpendingKey( const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret) { - if (!CCryptoKeyStore::AddCryptedSproutSpendingKey(address, rk, vchCryptedSecret)) - return false; - if (!fFileBacked) - return true; - { - LOCK(cs_wallet); - if (pwalletdbEncryption) { - return pwalletdbEncryption->WriteCryptedZKey(address, - rk, - vchCryptedSecret, - mapSproutZKeyMetadata[address]); - } else { - return CWalletDB(strWalletFile).WriteCryptedZKey(address, - rk, - vchCryptedSecret, - mapSproutZKeyMetadata[address]); - } - } return false; } @@ -415,47 +382,6 @@ bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key) return CCryptoKeyStore::AddSproutSpendingKey(key); } -bool CWallet::AddSproutViewingKey(const libzcash::SproutViewingKey &vk) -{ - if (!CCryptoKeyStore::AddSproutViewingKey(vk)) { - return false; - } - nTimeFirstKey = 1; // No birthday information for viewing keys. - if (!fFileBacked) { - return true; - } - return CWalletDB(strWalletFile).WriteSproutViewingKey(vk); -} - -bool CWallet::RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk) -{ - AssertLockHeld(cs_wallet); - if (!CCryptoKeyStore::RemoveSproutViewingKey(vk)) { - return false; - } - if (fFileBacked) { - if (!CWalletDB(strWalletFile).EraseSproutViewingKey(vk)) { - return false; - } - } - - return true; -} - -bool CWallet::LoadSproutViewingKey(const libzcash::SproutViewingKey &vk) -{ - return CCryptoKeyStore::AddSproutViewingKey(vk); -} - -bool CWallet::AddCScript(const CScript& redeemScript) -{ - if (!CCryptoKeyStore::AddCScript(redeemScript)) - return false; - if (!fFileBacked) - return true; - return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript); -} - bool CWallet::LoadCScript(const CScript& redeemScript) { /* A sanity check was added in pull #3843 to avoid adding redeemScripts diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 205a49008..1c46f3f98 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1111,17 +1111,6 @@ public: bool LoadZKeyMetadata(const libzcash::SproutPaymentAddress &addr, const CKeyMetadata &meta); //! Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet) bool LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret); - //! Adds an encrypted spending key to the store, and saves it to disk (virtual method, declared in crypter.h) - bool AddCryptedSproutSpendingKey( - const libzcash::SproutPaymentAddress &address, - const libzcash::ReceivingKey &rk, - const std::vector &vchCryptedSecret); - - //! Adds a Sprout viewing key to the store, and saves it to disk. - bool AddSproutViewingKey(const libzcash::SproutViewingKey &vk); - bool RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk); - //! Adds a Sprout viewing key to the store, without saving it to disk (used by LoadWallet) - bool LoadSproutViewingKey(const libzcash::SproutViewingKey &dest); /** * Sapling ZKeys From eec2dd51fba8ee8db30055fc55786df9fc3829f2 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 30 May 2020 00:44:20 -0400 Subject: [PATCH 34/98] wallet desprout --- src/wallet/wallet.cpp | 291 +----------------------------------------- src/wallet/wallet.h | 37 ------ 2 files changed, 4 insertions(+), 324 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a455cc2fe..d0d82a0e8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -114,11 +114,6 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const return &(it->second); } -// Generate a new spending key and return its public payment address -libzcash::SproutPaymentAddress CWallet::GenerateNewSproutZKey() -{ - throw std::runtime_error("unsupported"); -} // Generate a new Sapling spending key and return its public payment address SaplingPaymentAddress CWallet::GenerateNewSaplingZKey() @@ -216,12 +211,6 @@ bool CWallet::AddSaplingIncomingViewingKey( } -// Add spending key to keystore and persist to disk -bool CWallet::AddSproutZKey(const libzcash::SproutSpendingKey &key) -{ - return false; -} - CPubKey CWallet::GenerateNewKey() { AssertLockHeld(cs_wallet); // mapKeyMetadata @@ -292,15 +281,6 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, return false; } - -bool CWallet::AddCryptedSproutSpendingKey( - const libzcash::SproutPaymentAddress &address, - const libzcash::ReceivingKey &rk, - const std::vector &vchCryptedSecret) -{ - return false; -} - bool CWallet::AddCryptedSaplingSpendingKey(const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector &vchCryptedSecret, const libzcash::SaplingPaymentAddress &defaultAddr) @@ -589,29 +569,6 @@ std::set> CWallet::GetNullifiersFor return nullifierSet; } -bool CWallet::IsNoteSproutChange( - const std::set> & nullifierSet, - const PaymentAddress & address, - const JSOutPoint & jsop) -{ - // A Note is marked as "change" if the address that received it - // also spent Notes in the same transaction. This will catch, - // for instance: - // - Change created by spending fractions of Notes (because - // z_sendmany sends change to the originating z-address). - // - "Chaining Notes" used to connect JoinSplits together. - // - Notes created by consolidation transactions (e.g. using - // z_mergetoaddress). - // - Notes sent from one address to itself. - for (const JSDescription & jsd : mapWallet[jsop.hash].vjoinsplit) { - for (const uint256 & nullifier : jsd.nullifiers) { - if (nullifierSet.count(std::make_pair(address, nullifier))) { - return true; - } - } - } - return false; -} bool CWallet::IsNoteSaplingChange(const std::set> & nullifierSet, const libzcash::PaymentAddress & address, @@ -849,38 +806,6 @@ unsigned int CWallet::GetSpendDepth(const uint256& hash, unsigned int n) const return 0; } -/** - * Note is spent if any non-conflicted transaction - * spends it: - */ -bool CWallet::IsSproutSpent(const uint256& nullifier) const { - pair range; - range = mapTxSproutNullifiers.equal_range(nullifier); - - for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) { - const uint256& wtxid = it->second; - std::map::const_iterator mit = mapWallet.find(wtxid); - if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) { - return true; // Spent - } - } - return false; -} - -unsigned int CWallet::GetSproutSpendDepth(const uint256& nullifier) const { - pair range; - range = mapTxSproutNullifiers.equal_range(nullifier); - - for (TxNullifiers::const_iterator it = range.first; it != range.second; ++it) { - const uint256& wtxid = it->second; - std::map::const_iterator mit = mapWallet.find(wtxid); - if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0) { - return mit->second.GetDepthInMainChain(); // Spent - } - } - return 0; -} - bool CWallet::IsSaplingSpent(const uint256& nullifier) const { pair range; range = mapTxSaplingNullifiers.equal_range(nullifier); @@ -918,15 +843,6 @@ void CWallet::AddToTransparentSpends(const COutPoint& outpoint, const uint256& w SyncMetaData(range); } -void CWallet::AddToSproutSpends(const uint256& nullifier, const uint256& wtxid) -{ - mapTxSproutNullifiers.insert(make_pair(nullifier, wtxid)); - - pair range; - range = mapTxSproutNullifiers.equal_range(nullifier); - SyncMetaData(range); -} - void CWallet::AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid) { mapTxSaplingNullifiers.insert(make_pair(nullifier, wtxid)); @@ -946,11 +862,6 @@ void CWallet::AddToSpends(const uint256& wtxid) for (const CTxIn& txin : thisTx.vin) { AddToTransparentSpends(txin.prevout, wtxid); } - for (const JSDescription& jsdesc : thisTx.vjoinsplit) { - for (const uint256& nullifier : jsdesc.nullifiers) { - AddToSproutSpends(nullifier, wtxid); - } - } for (const SpendDescription &spend : thisTx.vShieldedSpend) { AddToSaplingSpends(spend.nullifier, wtxid); } @@ -1006,21 +917,6 @@ void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) extern int32_t KOMODO_REWIND; for (std::pair& wtxItem : mapWallet) { - //Sprout - for (auto& item : wtxItem.second.mapSproutNoteData) { - auto* nd = &(item.second); - if (nd->nullifier && pwalletMain->GetSproutSpendDepth(*item.second.nullifier) <= WITNESS_CACHE_SIZE) { - // Only decrement witnesses that are not above the current height - if (nd->witnessHeight <= pindex->GetHeight()) { - if (nd->witnesses.size() > 1) { - // indexHeight is the height of the block being removed, so - // the new witness cache height is one below it. - nd->witnesses.pop_front(); - nd->witnessHeight = pindex->GetHeight() - 1; - } - } - } - } //Sapling for (auto& item : wtxItem.second.mapSaplingNoteData) { auto* nd = &(item.second); @@ -1048,14 +944,6 @@ void ClearSingleNoteWitnessCache(NoteData* nd) nd->witnessRootValidated = false; } -int CWallet::SproutWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight) -{ - if (GetSproutSpendDepth(nullifier) <= WITNESS_CACHE_SIZE) { - nMinimumHeight = min(nWitnessHeight, nMinimumHeight); - } - return nMinimumHeight; -} - int CWallet::SaplingWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight) { if (GetSaplingSpendDepth(nullifier) <= WITNESS_CACHE_SIZE) { @@ -1396,22 +1284,6 @@ bool CWallet::UpdateNullifierNoteMap() ZCNoteDecryption dec; for (std::pair& wtxItem : mapWallet) { - for (mapSproutNoteData_t::value_type& item : wtxItem.second.mapSproutNoteData) { - if (!item.second.nullifier) { - if (GetNoteDecryptor(item.second.address, dec)) { - auto i = item.first.js; - auto hSig = wtxItem.second.vjoinsplit[i].h_sig( - *pzcashParams, wtxItem.second.joinSplitPubKey); - item.second.nullifier = GetSproutNoteNullifier( - wtxItem.second.vjoinsplit[i], - item.second.address, - dec, - hSig, - item.first.n); - } - } - } - // TODO: Sapling. This method is only called from RPC walletpassphrase, which is currently unsupported // as RPC encryptwallet is hidden behind two flags: -developerencryptwallet -experimentalfeatures @@ -1422,7 +1294,7 @@ bool CWallet::UpdateNullifierNoteMap() } /** - * Update mapSproutNullifiersToNotes and mapSaplingNullifiersToNotes + * Update mapSaplingNullifiersToNotes * with the cached nullifiers in this tx. */ void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx) @@ -1438,48 +1310,6 @@ void CWallet::UpdateNullifierNoteMapWithTx(const CWalletTx& wtx) } } -/** - * Update mapSproutNullifiersToNotes, computing the nullifier from a cached witness if necessary. - */ -void CWallet::UpdateSproutNullifierNoteMapWithTx(CWalletTx& wtx) { - LOCK(cs_wallet); - - ZCNoteDecryption dec; - for (mapSproutNoteData_t::value_type& item : wtx.mapSproutNoteData) { - SproutNoteData nd = item.second; - - if (nd.witnesses.empty()) { - // If there are no witnesses, erase the nullifier and associated mapping. - if (nd.nullifier) { - mapSproutNullifiersToNotes.erase(nd.nullifier.get()); - } - nd.nullifier = boost::none; - } - else { - if (GetNoteDecryptor(nd.address, dec)) { - auto i = item.first.js; - auto hSig = wtx.vjoinsplit[i].h_sig( - *pzcashParams, wtx.joinSplitPubKey); - auto optNullifier = GetSproutNoteNullifier( - wtx.vjoinsplit[i], - item.second.address, - dec, - hSig, - item.first.n); - - if (!optNullifier) { - // This should not happen. If it does, maybe the position has been corrupted or miscalculated? - assert(false); - } - - uint256 nullifier = optNullifier.get(); - mapSproutNullifiersToNotes[nullifier] = item.first; - item.second.nullifier = nullifier; - } - } - } -} - /** * Update mapSaplingNullifiersToNotes, computing the nullifier from a cached witness if necessary. */ @@ -1577,6 +1407,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD int64_t latestEntry = 0; { // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future + // TODO: this is 2 blocktimes, which will become 150? int64_t latestTolerated = latestNow + 300; std::list acentries; TxItems txOrdered = OrderedTxItems(acentries); @@ -1670,21 +1501,6 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx) { - bool unchangedSproutFlag = (wtxIn.mapSproutNoteData.empty() || wtxIn.mapSproutNoteData == wtx.mapSproutNoteData); - if (!unchangedSproutFlag) { - auto tmp = wtxIn.mapSproutNoteData; - // Ensure we keep any cached witnesses we may already have - for (const std::pair nd : wtx.mapSproutNoteData) { - if (tmp.count(nd.first) && nd.second.witnesses.size() > 0) { - tmp.at(nd.first).witnesses.assign( - nd.second.witnesses.cbegin(), nd.second.witnesses.cend()); - } - tmp.at(nd.first).witnessHeight = nd.second.witnessHeight; - } - // Now copy over the updated note data - wtx.mapSproutNoteData = tmp; - } - bool unchangedSaplingFlag = (wtxIn.mapSaplingNoteData.empty() || wtxIn.mapSaplingNoteData == wtx.mapSaplingNoteData); if (!unchangedSaplingFlag) { auto tmp = wtxIn.mapSaplingNoteData; @@ -1702,7 +1518,7 @@ bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx) wtx.mapSaplingNoteData = tmp; } - return !unchangedSproutFlag || !unchangedSaplingFlag; + return !unchangedSaplingFlag; } /** @@ -1719,7 +1535,6 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl return false; bool fExisted = mapWallet.count(tx.GetHash()) != 0; if (fExisted && !fUpdate) return false; - auto sproutNoteData = FindMySproutNotes(tx); auto saplingNoteDataAndAddressesToAdd = FindMySaplingNotes(tx); auto saplingNoteData = saplingNoteDataAndAddressesToAdd.first; auto addressesToAdd = saplingNoteDataAndAddressesToAdd.second; @@ -1743,7 +1558,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl fprintf(stderr, " %s\n", wladdr.c_str()); } } - if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0) + if (fExisted || IsMine(tx) || IsFromMe(tx) || saplingNoteData.size() > 0) { // wallet filter for notary nodes. Enables by setting -whitelistaddress= as startup param or in conf file (works same as -addnode byut with R-address's) if ( !tx.IsCoinBase() && !vWhiteListAddress.empty() && !NotaryAddress.empty() ) @@ -1775,10 +1590,6 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl CWalletTx wtx(this,tx); - if (sproutNoteData.size() > 0) { - wtx.SetSproutNoteData(sproutNoteData); - } - if (saplingNoteData.size() > 0) { wtx.SetSaplingNoteData(saplingNoteData); } @@ -1850,82 +1661,6 @@ void CWallet::RescanWallet() } -/** - * Returns a nullifier if the SpendingKey is available - * Throws std::runtime_error if the decryptor doesn't match this note - */ -boost::optional CWallet::GetSproutNoteNullifier(const JSDescription &jsdesc, - const libzcash::SproutPaymentAddress &address, - const ZCNoteDecryption &dec, - const uint256 &hSig, - uint8_t n) const -{ - boost::optional ret; - auto note_pt = libzcash::SproutNotePlaintext::decrypt( - dec, - jsdesc.ciphertexts[n], - jsdesc.ephemeralKey, - hSig, - (unsigned char) n); - auto note = note_pt.note(address); - // SpendingKeys are only available if: - // - We have them (this isn't a viewing key) - // - The wallet is unlocked - libzcash::SproutSpendingKey key; - if (GetSproutSpendingKey(address, key)) { - ret = note.nullifier(key); - } - return ret; -} - -/** - * Finds all output notes in the given transaction that have been sent to - * PaymentAddresses in this wallet. - * - * It should never be necessary to call this method with a CWalletTx, because - * the result of FindMySproutNotes (for the addresses available at the time) will - * already have been cached in CWalletTx.mapSproutNoteData. - */ -mapSproutNoteData_t CWallet::FindMySproutNotes(const CTransaction &tx) const -{ - LOCK(cs_SpendingKeyStore); - uint256 hash = tx.GetHash(); - - mapSproutNoteData_t noteData; - for (size_t i = 0; i < tx.vjoinsplit.size(); i++) { - auto hSig = tx.vjoinsplit[i].h_sig(*pzcashParams, tx.joinSplitPubKey); - for (uint8_t j = 0; j < tx.vjoinsplit[i].ciphertexts.size(); j++) { - for (const NoteDecryptorMap::value_type& item : mapNoteDecryptors) { - try { - auto address = item.first; - JSOutPoint jsoutpt {hash, i, j}; - auto nullifier = GetSproutNoteNullifier( - tx.vjoinsplit[i], - address, - item.second, - hSig, j); - if (nullifier) { - SproutNoteData nd {address, *nullifier}; - noteData.insert(std::make_pair(jsoutpt, nd)); - } else { - SproutNoteData nd {address}; - noteData.insert(std::make_pair(jsoutpt, nd)); - } - break; - } catch (const note_decryption_failed &err) { - // Couldn't decrypt with this decryptor - } catch (const std::exception &exc) { - // Unexpected failure - LogPrintf("FindMySproutNotes(): Unexpected error while testing decrypt:\n"); - LogPrintf("%s\n", exc.what()); - } - } - } - } - return noteData; -} - - /** * Finds all output notes in the given transaction that have been sent to * SaplingPaymentAddresses in this wallet. @@ -1985,18 +1720,6 @@ std::pair CWallet::FindMySap return std::make_pair(noteData, viewingKeysToAdd); } -bool CWallet::IsSproutNullifierFromMe(const uint256& nullifier) const -{ - { - LOCK(cs_wallet); - if (mapSproutNullifiersToNotes.count(nullifier) && - mapWallet.count(mapSproutNullifiersToNotes.at(nullifier).hash)) { - return true; - } - } - return false; -} - bool CWallet::IsSaplingNullifierFromMe(const uint256& nullifier) const { { @@ -2009,12 +1732,6 @@ bool CWallet::IsSaplingNullifierFromMe(const uint256& nullifier) const return false; } -void CWallet::GetSproutNoteWitnesses(std::vector notes, - std::vector>& witnesses, - uint256 &final_anchor) -{ -} - void CWallet::GetSaplingNoteWitnesses(std::vector notes, std::vector>& witnesses, uint256 &final_anchor) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 1c46f3f98..d82e100ed 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -589,11 +589,8 @@ public: MarkDirty(); } - void SetSproutNoteData(mapSproutNoteData_t ¬eData); void SetSaplingNoteData(mapSaplingNoteData_t ¬eData); - std::pair DecryptSproutNote( - JSOutPoint jsop) const; boost::optional> DecryptSaplingNote(SaplingOutPoint op) const; @@ -801,14 +798,12 @@ private: * detect and report conflicts (double-spends). */ typedef TxSpendMap TxNullifiers; - TxNullifiers mapTxSproutNullifiers; TxNullifiers mapTxSaplingNullifiers; std::vector pendingSaplingConsolidationTxs; AsyncRPCOperationId saplingConsolidationOperationId; void AddToTransparentSpends(const COutPoint& outpoint, const uint256& wtxid); - void AddToSproutSpends(const uint256& nullifier, const uint256& wtxid); void AddToSaplingSpends(const uint256& nullifier, const uint256& wtxid); void AddToSpends(const uint256& wtxid); @@ -915,7 +910,6 @@ public: std::set setKeyPool; std::map mapKeyMetadata; - std::map mapSproutZKeyMetadata; std::map mapSaplingZKeyMetadata; typedef std::map MasterKeyMap; @@ -1033,8 +1027,6 @@ public: bool IsSpent(const uint256& hash, unsigned int n) const; unsigned int GetSpendDepth(const uint256& hash, unsigned int n) const; - bool IsSproutSpent(const uint256& nullifier) const; - unsigned int GetSproutSpendDepth(const uint256& nullifier) const; bool IsSaplingSpent(const uint256& nullifier) const; unsigned int GetSaplingSpendDepth(const uint256& nullifier) const; @@ -1047,8 +1039,6 @@ public: bool IsLockedNote(const JSOutPoint& outpt) const; void LockNote(const JSOutPoint& output); void UnlockNote(const JSOutPoint& output); - void UnlockAllSproutNotes(); - std::vector ListLockedSproutNotes(); bool IsLockedNote(const SaplingOutPoint& output) const; void LockNote(const SaplingOutPoint& output); @@ -1098,20 +1088,6 @@ public: void GetKeyBirthTimes(std::map &mapKeyBirth) const; - /** - * Sprout ZKeys - */ - //! Generates a new Sprout zaddr - libzcash::SproutPaymentAddress GenerateNewSproutZKey(); - //! Adds spending key to the store, and saves it to disk - bool AddSproutZKey(const libzcash::SproutSpendingKey &key); - //! Adds spending key to the store, without saving it to disk (used by LoadWallet) - bool LoadZKey(const libzcash::SproutSpendingKey &key); - //! Load spending key metadata (used by LoadWallet) - bool LoadZKeyMetadata(const libzcash::SproutPaymentAddress &addr, const CKeyMetadata &meta); - //! Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet) - bool LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret); - /** * Sapling ZKeys */ @@ -1160,7 +1136,6 @@ public: void MarkDirty(); bool UpdateNullifierNoteMap(); void UpdateNullifierNoteMapWithTx(const CWalletTx& wtx); - void UpdateSproutNullifierNoteMapWithTx(CWalletTx& wtx); void UpdateSaplingNullifierNoteMapWithTx(CWalletTx& wtx); void UpdateNullifierNoteMapForBlock(const CBlock* pblock); bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); @@ -1208,21 +1183,9 @@ public: std::set GetAccountAddresses(const std::string& strAccount) const; - boost::optional GetSproutNoteNullifier( - const JSDescription& jsdesc, - const libzcash::SproutPaymentAddress& address, - const ZCNoteDecryption& dec, - const uint256& hSig, - uint8_t n) const; - mapSproutNoteData_t FindMySproutNotes(const CTransaction& tx) const; std::pair FindMySaplingNotes(const CTransaction& tx) const; - bool IsSproutNullifierFromMe(const uint256& nullifier) const; bool IsSaplingNullifierFromMe(const uint256& nullifier) const; - void GetSproutNoteWitnesses( - std::vector notes, - std::vector>& witnesses, - uint256 &final_anchor); void GetSaplingNoteWitnesses( std::vector notes, std::vector>& witnesses, From c27264eb0ff0f4c29c828146f5dd3d704df256a8 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 1 Jun 2020 01:42:19 -0400 Subject: [PATCH 35/98] desprout --- .../asyncrpcoperation_mergetoaddress.cpp | 336 +----------------- src/zcbenchmarks.cpp | 177 --------- 2 files changed, 2 insertions(+), 511 deletions(-) diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 2e77195f3..488e7f5b7 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -430,6 +430,8 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() */ + UniValue obj(UniValue::VOBJ); + /** * SCENARIO #1 * @@ -438,7 +440,6 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() * There are no zaddrs or joinsplits involved. */ if (isPureTaddrOnlyTx) { - UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); sign_send_raw_transaction(obj); return true; @@ -447,335 +448,6 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() * END SCENARIO #1 */ - - // Prepare raw transaction to handle JoinSplits - CMutableTransaction mtx(tx_); - crypto_sign_keypair(joinSplitPubKey_.begin(), joinSplitPrivKey_); - mtx.joinSplitPubKey = joinSplitPubKey_; - tx_ = CTransaction(mtx); - std::string hexMemo = std::get<1>(recipient_); - - - /** - * SCENARIO #2 - * - * taddrs -> zaddr - * - * We only need a single JoinSplit. - */ - if (sproutNoteInputs_.empty() && isToZaddr_) { - // Create JoinSplit to target z-addr. - MergeToAddressJSInfo info; - info.vpub_old = sendAmount; - info.vpub_new = 0; - - JSOutput jso = JSOutput(boost::get(toPaymentAddress_), sendAmount); - if (hexMemo.size() > 0) { - jso.memo = get_memo_from_hex_string(hexMemo); - } - info.vjsout.push_back(jso); - - UniValue obj(UniValue::VOBJ); - obj = perform_joinsplit(info); - sign_send_raw_transaction(obj); - return true; - } - /** - * END SCENARIO #2 - */ - - - // Copy zinputs to more flexible containers - std::deque zInputsDeque; - for (const auto& o : sproutNoteInputs_) { - zInputsDeque.push_back(o); - } - - // When spending notes, take a snapshot of note witnesses and anchors as the treestate will - // change upon arrival of new blocks which contain joinsplit transactions. This is likely - // to happen as creating a chained joinsplit transaction can take longer than the block interval. - { - LOCK2(cs_main, pwalletMain->cs_wallet); - for (auto t : sproutNoteInputs_) { - JSOutPoint jso = std::get<0>(t); - std::vector vOutPoints = {jso}; - uint256 inputAnchor; - std::vector> vInputWitnesses; - pwalletMain->GetSproutNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor); - jsopWitnessAnchorMap[jso.ToString()] = MergeToAddressWitnessAnchorData{vInputWitnesses[0], inputAnchor}; - } - } - - /** - * SCENARIO #3 - * - * zaddrs -> zaddr - * taddrs -> - * - * zaddrs -> - * taddrs -> taddr - * - * Send to zaddr by chaining JoinSplits together and immediately consuming any change - * Send to taddr by creating dummy z outputs and accumulating value in a change note - * which is used to set vpub_new in the last chained joinsplit. - */ - UniValue obj(UniValue::VOBJ); - CAmount jsChange = 0; // this is updated after each joinsplit - int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0 - bool vpubOldProcessed = false; // updated when vpub_old for taddr inputs is set in first joinsplit - bool vpubNewProcessed = false; // updated when vpub_new for miner fee and taddr outputs is set in last joinsplit - - // At this point, we are guaranteed to have at least one input note. - // Use address of first input note as the temporary change address. - SproutSpendingKey changeKey = std::get<3>(zInputsDeque.front()); - SproutPaymentAddress changeAddress = changeKey.address(); - - CAmount vpubOldTarget = 0; - CAmount vpubNewTarget = 0; - if (isToTaddr_) { - vpubNewTarget = z_inputs_total; - } else { - if (utxoInputs_.empty()) { - vpubNewTarget = minersFee; - } else { - vpubOldTarget = t_inputs_total - minersFee; - } - } - - // Keep track of treestate within this transaction - boost::unordered_map intermediates; - std::vector previousCommitments; - - while (!vpubNewProcessed) { - MergeToAddressJSInfo info; - info.vpub_old = 0; - info.vpub_new = 0; - - // Set vpub_old in the first joinsplit - if (!vpubOldProcessed) { - if (t_inputs_total < vpubOldTarget) { - throw JSONRPCError(RPC_WALLET_ERROR, - strprintf("Insufficient transparent funds for vpub_old %s (miners fee %s, taddr inputs %s)", - FormatMoney(vpubOldTarget), FormatMoney(minersFee), FormatMoney(t_inputs_total))); - } - info.vpub_old += vpubOldTarget; // funds flowing from public pool - vpubOldProcessed = true; - } - - CAmount jsInputValue = 0; - uint256 jsAnchor; - std::vector> witnesses; - - JSDescription prevJoinSplit; - - // Keep track of previous JoinSplit and its commitments - if (tx_.vjoinsplit.size() > 0) { - prevJoinSplit = tx_.vjoinsplit.back(); - } - - // If there is no change, the chain has terminated so we can reset the tracked treestate. - if (jsChange == 0 && tx_.vjoinsplit.size() > 0) { - intermediates.clear(); - previousCommitments.clear(); - } - - // - // Consume change as the first input of the JoinSplit. - // - if (jsChange > 0) { - LOCK2(cs_main, pwalletMain->cs_wallet); - - // Update tree state with previous joinsplit - SproutMerkleTree tree; - auto it = intermediates.find(prevJoinSplit.anchor); - if (it != intermediates.end()) { - tree = it->second; - } else if (!pcoinsTip->GetSproutAnchorAt(prevJoinSplit.anchor, tree)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Could not find previous JoinSplit anchor"); - } - - assert(changeOutputIndex != -1); - boost::optional changeWitness; - int n = 0; - for (const uint256& commitment : prevJoinSplit.commitments) { - tree.append(commitment); - previousCommitments.push_back(commitment); - if (!changeWitness && changeOutputIndex == n++) { - changeWitness = tree.witness(); - } else if (changeWitness) { - changeWitness.get().append(commitment); - } - } - if (changeWitness) { - witnesses.push_back(changeWitness); - } - jsAnchor = tree.root(); - intermediates.insert(std::make_pair(tree.root(), tree)); // chained js are interstitial (found in between block boundaries) - - // Decrypt the change note's ciphertext to retrieve some data we need - ZCNoteDecryption decryptor(changeKey.receiving_key()); - auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey); - try { - SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt( - decryptor, - prevJoinSplit.ciphertexts[changeOutputIndex], - prevJoinSplit.ephemeralKey, - hSig, - (unsigned char)changeOutputIndex); - - SproutNote note = plaintext.note(changeAddress); - info.notes.push_back(note); - info.zkeys.push_back(changeKey); - - jsInputValue += plaintext.value(); - - LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n", - getId(), - FormatMoney(plaintext.value())); - - } catch (const std::exception& e) { - throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error decrypting output note of previous JoinSplit: %s", e.what())); - } - } - - - // - // Consume spendable non-change notes - // - std::vector vInputNotes; - std::vector vInputZKeys; - std::vector vOutPoints; - std::vector> vInputWitnesses; - uint256 inputAnchor; - int numInputsNeeded = (jsChange > 0) ? 1 : 0; - while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) { - MergeToAddressInputSproutNote t = zInputsDeque.front(); - JSOutPoint jso = std::get<0>(t); - SproutNote note = std::get<1>(t); - CAmount noteFunds = std::get<2>(t); - SproutSpendingKey zkey = std::get<3>(t); - zInputsDeque.pop_front(); - - MergeToAddressWitnessAnchorData wad = jsopWitnessAnchorMap[jso.ToString()]; - vInputWitnesses.push_back(wad.witness); - if (inputAnchor.IsNull()) { - inputAnchor = wad.anchor; - } else if (inputAnchor != wad.anchor) { - throw JSONRPCError(RPC_WALLET_ERROR, "Selected input notes do not share the same anchor"); - } - - vOutPoints.push_back(jso); - vInputNotes.push_back(note); - vInputZKeys.push_back(zkey); - - jsInputValue += noteFunds; - - int wtxHeight = -1; - int wtxDepth = -1; - { - LOCK2(cs_main, pwalletMain->cs_wallet); - const CWalletTx& wtx = pwalletMain->mapWallet[jso.hash]; - // Zero confirmation notes belong to transactions which have not yet been mined - if (mapBlockIndex.find(wtx.hashBlock) == mapBlockIndex.end()) { - throw JSONRPCError(RPC_WALLET_ERROR, strprintf("mapBlockIndex does not contain block hash %s", wtx.hashBlock.ToString())); - } - wtxHeight = komodo_blockheight(wtx.hashBlock); - wtxDepth = wtx.GetDepthInMainChain(); - } - LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n", - getId(), - jso.hash.ToString().substr(0, 10), - jso.js, - int(jso.n), // uint8_t - FormatMoney(noteFunds), - wtxHeight, - wtxDepth); - } - - // Add history of previous commitments to witness - if (vInputNotes.size() > 0) { - if (vInputWitnesses.size() == 0) { - throw JSONRPCError(RPC_WALLET_ERROR, "Could not find witness for note commitment"); - } - - for (auto& optionalWitness : vInputWitnesses) { - if (!optionalWitness) { - throw JSONRPCError(RPC_WALLET_ERROR, "Witness for note commitment is null"); - } - SproutWitness w = *optionalWitness; // could use .get(); - if (jsChange > 0) { - for (const uint256& commitment : previousCommitments) { - w.append(commitment); - } - if (jsAnchor != w.root()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Witness for spendable note does not have same anchor as change input"); - } - } - witnesses.push_back(w); - } - - // The jsAnchor is null if this JoinSplit is at the start of a new chain - if (jsAnchor.IsNull()) { - jsAnchor = inputAnchor; - } - - // Add spendable notes as inputs - std::copy(vInputNotes.begin(), vInputNotes.end(), std::back_inserter(info.notes)); - std::copy(vInputZKeys.begin(), vInputZKeys.end(), std::back_inserter(info.zkeys)); - } - - // Accumulate change - jsChange = jsInputValue + info.vpub_old; - - // Set vpub_new in the last joinsplit (when there are no more notes to spend) - if (zInputsDeque.empty()) { - assert(!vpubNewProcessed); - if (jsInputValue < vpubNewTarget) { - throw JSONRPCError(RPC_WALLET_ERROR, - strprintf("Insufficient funds for vpub_new %s (miners fee %s, taddr inputs %s)", - FormatMoney(vpubNewTarget), FormatMoney(minersFee), FormatMoney(t_inputs_total))); - } - info.vpub_new += vpubNewTarget; // funds flowing back to public pool - vpubNewProcessed = true; - jsChange -= vpubNewTarget; - // If we are merging to a t-addr, there should be no change - if (isToTaddr_) assert(jsChange == 0); - } - - // create dummy output - info.vjsout.push_back(JSOutput()); // dummy output while we accumulate funds into a change note for vpub_new - - // create output for any change - if (jsChange > 0) { - std::string outputType = "change"; - auto jso = JSOutput(changeAddress, jsChange); - // If this is the final output, set the target and memo - if (isToZaddr_ && vpubNewProcessed) { - outputType = "target"; - jso.addr = boost::get(toPaymentAddress_); - if (!hexMemo.empty()) { - jso.memo = get_memo_from_hex_string(hexMemo); - } - } - info.vjsout.push_back(jso); - - LogPrint("zrpcunsafe", "%s: generating note for %s (amount=%s)\n", - getId(), - outputType, - FormatMoney(jsChange)); - } - - obj = perform_joinsplit(info, witnesses, jsAnchor); - - if (jsChange > 0) { - changeOutputIndex = mta_find_output(obj, 1); - } - } - - // Sanity check in case changes to code block above exits loop by invoking 'break' - assert(zInputsDeque.size() == 0); - assert(vpubNewProcessed); - sign_send_raw_transaction(obj); return true; } @@ -866,10 +538,6 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(MergeToAddressJSInf { std::vector> witnesses; uint256 anchor; - { - LOCK(cs_main); - pwalletMain->GetSproutNoteWitnesses(outPoints, witnesses, anchor); - } return perform_joinsplit(info, witnesses, anchor); } diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 2f79e454b..9af3c184a 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -93,29 +93,6 @@ double benchmark_sleep() return timer_stop(tv_start); } -double benchmark_create_joinsplit() -{ - uint256 joinSplitPubKey; - - /* Get the anchor of an empty commitment tree. */ - uint256 anchor = SproutMerkleTree().root(); - - struct timeval tv_start; - timer_start(tv_start); - JSDescription jsdesc(*pzcashParams, - joinSplitPubKey, - anchor, - {JSInput(), JSInput()}, - {JSOutput(), JSOutput()}, - 0, - 0); - double ret = timer_stop(tv_start); - - auto verifier = libzcash::ProofVerifier::Strict(); - assert(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey)); - return ret; -} - std::vector benchmark_create_joinsplit_threaded(int nThreads) { std::vector ret; @@ -263,160 +240,6 @@ double benchmark_large_tx(size_t nInputs) return timer_stop(tv_start); } -double benchmark_try_decrypt_notes(size_t nAddrs) -{ - CWallet wallet; - for (int i = 0; i < nAddrs; i++) { - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - } - - auto sk = libzcash::SproutSpendingKey::random(); - auto tx = GetValidReceive(*pzcashParams, sk, 10, true); - - struct timeval tv_start; - timer_start(tv_start); - auto nd = wallet.FindMySproutNotes(tx); - return timer_stop(tv_start); -} - -double benchmark_increment_note_witnesses(size_t nTxs) -{ - CWallet wallet; - SproutMerkleTree sproutTree; - SaplingMerkleTree saplingTree; - - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - - // First block - CBlock block1; - for (int i = 0; i < nTxs; i++) { - auto wtx = GetValidReceive(*pzcashParams, sk, 10, true); - auto note = GetNote(*pzcashParams, sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - noteData[jsoutpt] = nd; - - wtx.SetSproutNoteData(noteData); - wallet.AddToWallet(wtx, true, NULL); - block1.vtx.push_back(wtx); - } - CBlockIndex index1(block1); - index1.SetHeight(1); - - // Increment to get transactions witnessed - wallet.ChainTip(&index1, &block1, std::make_pair(sproutTree, saplingTree)); - - // Second block - CBlock block2; - block2.hashPrevBlock = block1.GetHash(); - { - auto wtx = GetValidReceive(*pzcashParams, sk, 10, true); - auto note = GetNote(*pzcashParams, sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - noteData[jsoutpt] = nd; - - wtx.SetSproutNoteData(noteData); - wallet.AddToWallet(wtx, true, NULL); - block2.vtx.push_back(wtx); - } - CBlockIndex index2(block2); - index2.SetHeight(2); - - struct timeval tv_start; - timer_start(tv_start); - wallet.ChainTip(&index2, &block2, std::make_pair(sproutTree, saplingTree)); - return timer_stop(tv_start); -} - -// Fake the input of a given block -class FakeCoinsViewDB : public CCoinsViewDB { - uint256 hash; - SproutMerkleTree t; - -public: - FakeCoinsViewDB(std::string dbName, uint256& hash) : CCoinsViewDB(dbName, 100, false, false), hash(hash) {} - - bool GetAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { - if (rt == t.root()) { - tree = t; - return true; - } - return false; - } - - bool GetNullifier(const uint256 &nf, ShieldedType type) const { - return false; - } - - uint256 GetBestBlock() const { - return hash; - } - - uint256 GetBestAnchor() const { - return t.root(); - } - - bool BatchWrite(CCoinsMap &mapCoins, - const uint256 &hashBlock, - const uint256 &hashAnchor, - CAnchorsSproutMap &mapSproutAnchors, - CNullifiersMap &mapSproutNullifiers, - CNullifiersMap& mapSaplingNullifiers) { - return false; - } - - bool GetStats(CCoinsStats &stats) const { - return false; - } -}; - -double benchmark_connectblock_slow() -{ - // Test for issue 2017-05-01.a - SelectParams(CBaseChainParams::MAIN); - CBlock block; - FILE* fp = fopen((GetDataDir() / "benchmark/block-107134.dat").string().c_str(), "rb"); - if (!fp) throw new std::runtime_error("Failed to open block data file"); - CAutoFile blkFile(fp, SER_DISK, CLIENT_VERSION); - blkFile >> block; - blkFile.fclose(); - - // Fake its inputs - auto hashPrev = uint256S("00000000159a41f468e22135942a567781c3f3dc7ad62257993eb3c69c3f95ef"); - FakeCoinsViewDB fakeDB("benchmark/block-107134-inputs", hashPrev); - CCoinsViewCache view(&fakeDB); - - // Fake the chain - CBlockIndex index(block); - index.SetHeight(107134); - CBlockIndex indexPrev; - indexPrev.phashBlock = &hashPrev; - indexPrev.SetHeight(index.GetHeight() - 1); - index.pprev = &indexPrev; - mapBlockIndex.insert(std::make_pair(hashPrev, &indexPrev)); - - CValidationState state; - struct timeval tv_start; - timer_start(tv_start); - assert(ConnectBlock(block, state, &index, view, true)); - auto duration = timer_stop(tv_start); - - // Undo alterations to global state - mapBlockIndex.erase(hashPrev); - SelectParamsFromCommandLine(); - - return duration; -} - extern UniValue getnewaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp extern UniValue sendtoaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); From 00bf3255eb4c39586288a4ddd95855986ce2252d Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 1 Jun 2020 10:54:50 -0400 Subject: [PATCH 36/98] desprout --- .../asyncrpcoperation_mergetoaddress.cpp | 7 +- src/wallet/asyncrpcoperation_sendmany.cpp | 631 +----------------- 2 files changed, 4 insertions(+), 634 deletions(-) diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 488e7f5b7..4dace19bb 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -429,9 +429,6 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() * END SCENARIO #0 */ - - UniValue obj(UniValue::VOBJ); - /** * SCENARIO #1 * @@ -440,6 +437,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() * There are no zaddrs or joinsplits involved. */ if (isPureTaddrOnlyTx) { + UniValue obj(UniValue::VOBJ); obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); sign_send_raw_transaction(obj); return true; @@ -448,8 +446,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() * END SCENARIO #1 */ - sign_send_raw_transaction(obj); - return true; + return false; } diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index db7f7bd66..a1ecb296d 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -1,7 +1,7 @@ // Copyright (c) 2016 The Zcash developers // Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * @@ -566,430 +566,7 @@ bool AsyncRPCOperation_sendmany::main_impl() { * END SCENARIO #0 */ - - // Grab the current consensus branch ID - { - LOCK(cs_main); - consensusBranchId_ = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - } - - /** - * SCENARIO #1 - * - * taddr -> taddrs - * - * There are no zaddrs or joinsplits involved. - */ - if (isPureTaddrOnlyTx) { - add_taddr_outputs_to_tx(); - - CAmount funds = selectedUTXOAmount; - CAmount fundsSpent = t_outputs_total + minersFee; - CAmount change = funds - fundsSpent; - - if (change > 0) { - add_taddr_change_output_to_tx(0,change); - - LogPrint("zrpc", "%s: transparent change in transaction output (amount=%s)\n", - getId(), - FormatMoney(change) - ); - } - - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("rawtxn", EncodeHexTx(tx_))); - sign_send_raw_transaction(obj); - return true; - } - /** - * END SCENARIO #1 - */ - - - // Prepare raw transaction to handle JoinSplits - CMutableTransaction mtx(tx_); - crypto_sign_keypair(joinSplitPubKey_.begin(), joinSplitPrivKey_); - mtx.joinSplitPubKey = joinSplitPubKey_; - //if ((uint32_t)chainActive.LastTip()->nTime < ASSETCHAINS_STAKED_HF_TIMESTAMP) - if ( !hush_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) - mtx.nLockTime = (uint32_t)time(NULL) - 60; // jl777 - else - mtx.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); - - tx_ = CTransaction(mtx); - - // Copy zinputs and zoutputs to more flexible containers - std::deque zInputsDeque; // zInputsDeque stores minimum numbers of notes for target amount - CAmount tmp = 0; - for (auto o : z_sprout_inputs_) { - zInputsDeque.push_back(o); - tmp += std::get<2>(o); - if (tmp >= targetAmount) { - break; - } - } - std::deque zOutputsDeque; - for (auto o : z_outputs_) { - zOutputsDeque.push_back(o); - } - - // When spending notes, take a snapshot of note witnesses and anchors as the treestate will - // change upon arrival of new blocks which contain joinsplit transactions. This is likely - // to happen as creating a chained joinsplit transaction can take longer than the block interval. - if (z_sprout_inputs_.size() > 0) { - LOCK2(cs_main, pwalletMain->cs_wallet); - for (auto t : z_sprout_inputs_) { - JSOutPoint jso = std::get<0>(t); - std::vector vOutPoints = { jso }; - uint256 inputAnchor; - std::vector> vInputWitnesses; - pwalletMain->GetSproutNoteWitnesses(vOutPoints, vInputWitnesses, inputAnchor); - jsopWitnessAnchorMap[ jso.ToString() ] = WitnessAnchorData{ vInputWitnesses[0], inputAnchor }; - } - } - - - /** - * SCENARIO #2 - * - * taddr -> taddrs - * -> zaddrs - * - * Note: Consensus rule states that coinbase utxos can only be sent to a zaddr. TODO: Do they? - * Local wallet rule does not allow any change when sending coinbase utxos - * since there is currently no way to specify a change address and we don't - * want users accidentally sending excess funds to a recipient. - */ - if (isfromtaddr_) { - add_taddr_outputs_to_tx(); - - CAmount funds = selectedUTXOAmount; - CAmount fundsSpent = t_outputs_total + minersFee + z_outputs_total; - CAmount change = funds - fundsSpent; - - if (change > 0) { - if (selectedUTXOCoinbase) { - assert(isSingleZaddrOutput); - throw JSONRPCError(RPC_WALLET_ERROR, strprintf( - "Change %s not allowed. When shielding coinbase funds, the wallet does not " - "allow any change as there is currently no way to specify a change address " - "in z_sendmany.", FormatMoney(change))); - } else { - CBitcoinAddress ba = CBitcoinAddress(fromtaddr_); - add_taddr_change_output_to_tx(&ba,change); - LogPrint("zrpc", "%s: transparent change in transaction output (amount=%s)\n", - getId(), - FormatMoney(change) - ); - } - } - - // Create joinsplits, where each output represents a zaddr recipient. - UniValue obj(UniValue::VOBJ); - while (zOutputsDeque.size() > 0) { - AsyncJoinSplitInfo info; - info.vpub_old = 0; - info.vpub_new = 0; - int n = 0; - while (n++ 0) { - SendManyRecipient smr = zOutputsDeque.front(); - std::string address = std::get<0>(smr); - CAmount value = std::get<1>(smr); - std::string hexMemo = std::get<2>(smr); - zOutputsDeque.pop_front(); - - PaymentAddress pa = DecodePaymentAddress(address); - JSOutput jso = JSOutput(boost::get(pa), value); - if (hexMemo.size() > 0) { - jso.memo = get_memo_from_hex_string(hexMemo); - } - info.vjsout.push_back(jso); - - // Funds are removed from the value pool and enter the private pool - info.vpub_old += value; - } - obj = perform_joinsplit(info); - } - sign_send_raw_transaction(obj); - return true; - } - /** - * END SCENARIO #2 - */ - - - - /** - * SCENARIO #3 - * - * zaddr -> taddrs - * -> zaddrs - * - * Send to zaddrs by chaining JoinSplits together and immediately consuming any change - * Send to taddrs by creating dummy z outputs and accumulating value in a change note - * which is used to set vpub_new in the last chained joinsplit. - */ - UniValue obj(UniValue::VOBJ); - CAmount jsChange = 0; // this is updated after each joinsplit - int changeOutputIndex = -1; // this is updated after each joinsplit if jsChange > 0 - bool vpubNewProcessed = false; // updated when vpub_new for miner fee and taddr outputs is set in last joinsplit - CAmount vpubNewTarget = minersFee; - if (t_outputs_total > 0) { - add_taddr_outputs_to_tx(); - vpubNewTarget += t_outputs_total; - } - - // Keep track of treestate within this transaction - boost::unordered_map intermediates; - std::vector previousCommitments; - - while (!vpubNewProcessed) { - AsyncJoinSplitInfo info; - info.vpub_old = 0; - info.vpub_new = 0; - - CAmount jsInputValue = 0; - uint256 jsAnchor; - std::vector> witnesses; - - JSDescription prevJoinSplit; - - // Keep track of previous JoinSplit and its commitments - if (tx_.vjoinsplit.size() > 0) { - prevJoinSplit = tx_.vjoinsplit.back(); - } - - // If there is no change, the chain has terminated so we can reset the tracked treestate. - if (jsChange==0 && tx_.vjoinsplit.size() > 0) { - intermediates.clear(); - previousCommitments.clear(); - } - - // - // Consume change as the first input of the JoinSplit. - // - if (jsChange > 0) { - LOCK2(cs_main, pwalletMain->cs_wallet); - - // Update tree state with previous joinsplit - SproutMerkleTree tree; - auto it = intermediates.find(prevJoinSplit.anchor); - if (it != intermediates.end()) { - tree = it->second; - } else if (!pcoinsTip->GetSproutAnchorAt(prevJoinSplit.anchor, tree)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Could not find previous JoinSplit anchor"); - } - - assert(changeOutputIndex != -1); - boost::optional changeWitness; - int n = 0; - for (const uint256& commitment : prevJoinSplit.commitments) { - tree.append(commitment); - previousCommitments.push_back(commitment); - if (!changeWitness && changeOutputIndex == n++) { - changeWitness = tree.witness(); - } else if (changeWitness) { - changeWitness.get().append(commitment); - } - } - if (changeWitness) { - witnesses.push_back(changeWitness); - } - jsAnchor = tree.root(); - intermediates.insert(std::make_pair(tree.root(), tree)); // chained js are interstitial (found in between block boundaries) - - // Decrypt the change note's ciphertext to retrieve some data we need - ZCNoteDecryption decryptor(boost::get(spendingkey_).receiving_key()); - auto hSig = prevJoinSplit.h_sig(*pzcashParams, tx_.joinSplitPubKey); - try { - SproutNotePlaintext plaintext = SproutNotePlaintext::decrypt( - decryptor, - prevJoinSplit.ciphertexts[changeOutputIndex], - prevJoinSplit.ephemeralKey, - hSig, - (unsigned char) changeOutputIndex); - - SproutNote note = plaintext.note(boost::get(frompaymentaddress_)); - info.notes.push_back(note); - - jsInputValue += plaintext.value(); - - LogPrint("zrpcunsafe", "%s: spending change (amount=%s)\n", - getId(), - FormatMoney(plaintext.value()) - ); - - } catch (const std::exception& e) { - throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error decrypting output note of previous JoinSplit: %s", e.what())); - } - } - - - // - // Consume spendable non-change notes - // - std::vector vInputNotes; - std::vector vOutPoints; - std::vector> vInputWitnesses; - uint256 inputAnchor; - int numInputsNeeded = (jsChange>0) ? 1 : 0; - while (numInputsNeeded++ < ZC_NUM_JS_INPUTS && zInputsDeque.size() > 0) { - SendManyInputJSOP t = zInputsDeque.front(); - JSOutPoint jso = std::get<0>(t); - SproutNote note = std::get<1>(t); - CAmount noteFunds = std::get<2>(t); - zInputsDeque.pop_front(); - - WitnessAnchorData wad = jsopWitnessAnchorMap[ jso.ToString() ]; - vInputWitnesses.push_back(wad.witness); - if (inputAnchor.IsNull()) { - inputAnchor = wad.anchor; - } else if (inputAnchor != wad.anchor) { - throw JSONRPCError(RPC_WALLET_ERROR, "Selected input notes do not share the same anchor"); - } - - vOutPoints.push_back(jso); - vInputNotes.push_back(note); - - jsInputValue += noteFunds; - - int wtxHeight = -1; - int wtxDepth = -1; - { - LOCK2(cs_main, pwalletMain->cs_wallet); - const CWalletTx& wtx = pwalletMain->mapWallet[jso.hash]; - // Zero-confirmation notes belong to transactions which have not yet been mined - if (mapBlockIndex.find(wtx.hashBlock) == mapBlockIndex.end()) { - throw JSONRPCError(RPC_WALLET_ERROR, strprintf("mapBlockIndex does not contain block hash %s", wtx.hashBlock.ToString())); - } - wtxHeight = komodo_blockheight(wtx.hashBlock); - wtxDepth = wtx.GetDepthInMainChain(); - } - LogPrint("zrpcunsafe", "%s: spending note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, height=%d, confirmations=%d)\n", - getId(), - jso.hash.ToString().substr(0, 10), - jso.js, - int(jso.n), // uint8_t - FormatMoney(noteFunds), - wtxHeight, - wtxDepth - ); - } - - // Add history of previous commitments to witness - if (vInputNotes.size() > 0) { - - if (vInputWitnesses.size()==0) { - throw JSONRPCError(RPC_WALLET_ERROR, "Could not find witness for note commitment"); - } - - for (auto & optionalWitness : vInputWitnesses) { - if (!optionalWitness) { - throw JSONRPCError(RPC_WALLET_ERROR, "Witness for note commitment is null"); - } - SproutWitness w = *optionalWitness; // could use .get(); - if (jsChange > 0) { - for (const uint256& commitment : previousCommitments) { - w.append(commitment); - } - if (jsAnchor != w.root()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Witness for spendable note does not have same anchor as change input"); - } - } - witnesses.push_back(w); - } - - // The jsAnchor is null if this JoinSplit is at the start of a new chain - if (jsAnchor.IsNull()) { - jsAnchor = inputAnchor; - } - - // Add spendable notes as inputs - std::copy(vInputNotes.begin(), vInputNotes.end(), std::back_inserter(info.notes)); - } - - // Find recipient to transfer funds to - std::string address, hexMemo; - CAmount value = 0; - if (zOutputsDeque.size() > 0) { - SendManyRecipient smr = zOutputsDeque.front(); - address = std::get<0>(smr); - value = std::get<1>(smr); - hexMemo = std::get<2>(smr); - zOutputsDeque.pop_front(); - } - - // Reset change - jsChange = 0; - CAmount outAmount = value; - - // Set vpub_new in the last joinsplit (when there are no more notes to spend or zaddr outputs to satisfy) - if (zOutputsDeque.size() == 0 && zInputsDeque.size() == 0) { - assert(!vpubNewProcessed); - if (jsInputValue < vpubNewTarget) { - throw JSONRPCError(RPC_WALLET_ERROR, - strprintf("Insufficient funds for vpub_new %s (miners fee %s, taddr outputs %s)", - FormatMoney(vpubNewTarget), FormatMoney(minersFee), FormatMoney(t_outputs_total))); - } - outAmount += vpubNewTarget; - info.vpub_new += vpubNewTarget; // funds flowing back to public pool - vpubNewProcessed = true; - jsChange = jsInputValue - outAmount; - assert(jsChange >= 0); - } - else { - // This is not the last joinsplit, so compute change and any amount still due to the recipient - if (jsInputValue > outAmount) { - jsChange = jsInputValue - outAmount; - } else if (outAmount > jsInputValue) { - // Any amount due is owed to the recipient. Let the miners fee get paid first. - CAmount due = outAmount - jsInputValue; - SendManyRecipient r = SendManyRecipient(address, due, hexMemo); - zOutputsDeque.push_front(r); - - // reduce the amount being sent right now to the value of all inputs - value = jsInputValue; - } - } - - // create output for recipient - if (address.empty()) { - assert(value==0); - info.vjsout.push_back(JSOutput()); // dummy output while we accumulate funds into a change note for vpub_new - } else { - PaymentAddress pa = DecodePaymentAddress(address); - // If we are here, we know we have no Sapling outputs. - JSOutput jso = JSOutput(boost::get(pa), value); - if (hexMemo.size() > 0) { - jso.memo = get_memo_from_hex_string(hexMemo); - } - info.vjsout.push_back(jso); - } - - // create output for any change - if (jsChange>0) { - info.vjsout.push_back(JSOutput(boost::get(frompaymentaddress_), jsChange)); - - LogPrint("zrpcunsafe", "%s: generating note for change (amount=%s)\n", - getId(), - FormatMoney(jsChange) - ); - } - - obj = perform_joinsplit(info, witnesses, jsAnchor); - - if (jsChange > 0) { - changeOutputIndex = find_output(obj, 1); - } - } - - // Sanity check in case changes to code block above exits loop by invoking 'break' - assert(zInputsDeque.size() == 0); - assert(zOutputsDeque.size() == 0); - assert(vpubNewProcessed); - - sign_send_raw_transaction(obj); - return true; + return false; } @@ -1143,19 +720,6 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { saplingEntries.clear(); } - for (CSproutNotePlaintextEntry & entry : sproutEntries) { - z_sprout_inputs_.push_back(SendManyInputJSOP(entry.jsop, entry.plaintext.note(boost::get(frompaymentaddress_)), CAmount(entry.plaintext.value()))); - std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end()); - LogPrint("zrpcunsafe", "%s: found unspent Sprout note (txid=%s, vjoinsplit=%d, ciphertext=%d, amount=%s, memo=%s)\n", - getId(), - entry.jsop.hash.ToString().substr(0, 10), - entry.jsop.js, - int(entry.jsop.n), // uint8_t - FormatMoney(entry.plaintext.value()), - HexStr(data).substr(0, 10) - ); - } - for (auto entry : saplingEntries) { z_sapling_inputs_.push_back(entry); std::string data(entry.memo.begin(), entry.memo.end()); @@ -1167,15 +731,7 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { HexStr(data).substr(0, 10)); } - if (z_sprout_inputs_.empty() && z_sapling_inputs_.empty()) { - return false; - } - // sort in descending order, so big notes appear first - std::sort(z_sprout_inputs_.begin(), z_sprout_inputs_.end(), - [](SendManyInputJSOP i, SendManyInputJSOP j) -> bool { - return std::get<2>(i) > std::get<2>(j); - }); std::sort(z_sapling_inputs_.begin(), z_sapling_inputs_.end(), [](SaplingNoteEntry i, SaplingNoteEntry j) -> bool { return i.note.value() > j.note.value(); @@ -1184,189 +740,6 @@ bool AsyncRPCOperation_sendmany::find_unspent_notes() { return true; } -UniValue AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info) { - std::vector> witnesses; - uint256 anchor; - { - LOCK(cs_main); - anchor = pcoinsTip->GetBestAnchor(SPROUT); // As there are no inputs, ask the wallet for the best anchor - } - return perform_joinsplit(info, witnesses, anchor); -} - - -UniValue AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info, std::vector & outPoints) { - std::vector> witnesses; - uint256 anchor; - { - LOCK(cs_main); - pwalletMain->GetSproutNoteWitnesses(outPoints, witnesses, anchor); - } - return perform_joinsplit(info, witnesses, anchor); -} - -UniValue AsyncRPCOperation_sendmany::perform_joinsplit( - AsyncJoinSplitInfo & info, - std::vector> witnesses, - uint256 anchor) -{ - if (anchor.IsNull()) { - throw std::runtime_error("anchor is null"); - } - - if (!(witnesses.size() == info.notes.size())) { - throw runtime_error("number of notes and witnesses do not match"); - } - - for (size_t i = 0; i < witnesses.size(); i++) { - if (!witnesses[i]) { - throw runtime_error("joinsplit input could not be found in tree"); - } - info.vjsin.push_back(JSInput(*witnesses[i], info.notes[i], boost::get(spendingkey_))); - } - - // Make sure there are two inputs and two outputs - while (info.vjsin.size() < ZC_NUM_JS_INPUTS) { - info.vjsin.push_back(JSInput()); - } - - while (info.vjsout.size() < ZC_NUM_JS_OUTPUTS) { - info.vjsout.push_back(JSOutput()); - } - - if (info.vjsout.size() != ZC_NUM_JS_INPUTS || info.vjsin.size() != ZC_NUM_JS_OUTPUTS) { - throw runtime_error("unsupported joinsplit input/output counts"); - } - - CMutableTransaction mtx(tx_); - - LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", - getId(), - tx_.vjoinsplit.size(), - FormatMoney(info.vpub_old), FormatMoney(info.vpub_new), - FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()), - FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value) - ); - - // Generate the proof, this can take over a minute. - std::array inputs - {info.vjsin[0], info.vjsin[1]}; - std::array outputs - {info.vjsout[0], info.vjsout[1]}; - std::array inputMap; - std::array outputMap; - uint256 esk; // payment disclosure - secret - - JSDescription jsdesc = JSDescription::Randomized( - *pzcashParams, - joinSplitPubKey_, - anchor, - inputs, - outputs, - inputMap, - outputMap, - info.vpub_old, - info.vpub_new, - !this->testmode, - &esk); // parameter expects pointer to esk, so pass in address - { - auto verifier = libzcash::ProofVerifier::Strict(); - if (!(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey_))) { - throw std::runtime_error("error verifying joinsplit"); - } - } - - mtx.vjoinsplit.push_back(jsdesc); - - // Empty output script. - CScript scriptCode; - CTransaction signTx(mtx); - uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_); - - // Add the signature - if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, - dataToBeSigned.begin(), 32, - joinSplitPrivKey_ - ) == 0)) - { - throw std::runtime_error("crypto_sign_detached failed"); - } - - // Sanity check - if (!(crypto_sign_verify_detached(&mtx.joinSplitSig[0], - dataToBeSigned.begin(), 32, - mtx.joinSplitPubKey.begin() - ) == 0)) - { - throw std::runtime_error("crypto_sign_verify_detached failed"); - } - - CTransaction rawTx(mtx); - tx_ = rawTx; - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << rawTx; - - std::string encryptedNote1; - std::string encryptedNote2; - { - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << ((unsigned char) 0x00); - ss2 << jsdesc.ephemeralKey; - ss2 << jsdesc.ciphertexts[0]; - ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey_); - - encryptedNote1 = HexStr(ss2.begin(), ss2.end()); - } - { - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << ((unsigned char) 0x01); - ss2 << jsdesc.ephemeralKey; - ss2 << jsdesc.ciphertexts[1]; - ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey_); - - encryptedNote2 = HexStr(ss2.begin(), ss2.end()); - } - - UniValue arrInputMap(UniValue::VARR); - UniValue arrOutputMap(UniValue::VARR); - for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) { - arrInputMap.push_back(static_cast(inputMap[i])); - } - for (size_t i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - arrOutputMap.push_back(static_cast(outputMap[i])); - } - - - // !!! Payment disclosure START - unsigned char buffer[32] = {0}; - memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer - std::vector vch(&buffer[0], &buffer[0] + 32); - uint256 joinSplitPrivKey = uint256(vch); - size_t js_index = tx_.vjoinsplit.size() - 1; - uint256 placeholder; - for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - uint8_t mapped_index = outputMap[i]; - // placeholder for txid will be filled in later when tx has been finalized and signed. - PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index}; - JSOutput output = outputs[mapped_index]; - libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output - PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; - paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); - - LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr)); - } - // !!! Payment disclosure END - - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("encryptednote1", encryptedNote1)); - obj.push_back(Pair("encryptednote2", encryptedNote2)); - obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end()))); - obj.push_back(Pair("inputmap", arrInputMap)); - obj.push_back(Pair("outputmap", arrOutputMap)); - return obj; -} - void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() { CMutableTransaction rawTx(tx_); From 5be12774f4e61f79969b967f458b52424e1657df Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 2 Jun 2020 02:40:18 -0400 Subject: [PATCH 37/98] desprout --- .../asyncrpcoperation_mergetoaddress.cpp | 186 ----------------- .../asyncrpcoperation_shieldcoinbase.cpp | 189 +----------------- src/wallet/wallet.cpp | 140 +------------ src/wallet/walletdb.cpp | 76 ++----- 4 files changed, 22 insertions(+), 569 deletions(-) diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 4dace19bb..ed4efc014 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -518,186 +518,6 @@ void AsyncRPCOperation_mergetoaddress::sign_send_raw_transaction(UniValue obj) tx_ = tx; } - -UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(MergeToAddressJSInfo& info) -{ - std::vector> witnesses; - uint256 anchor; - { - LOCK(cs_main); - anchor = pcoinsTip->GetBestAnchor(SPROUT); // As there are no inputs, ask the wallet for the best anchor - } - return perform_joinsplit(info, witnesses, anchor); -} - - -UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(MergeToAddressJSInfo& info, std::vector& outPoints) -{ - std::vector> witnesses; - uint256 anchor; - return perform_joinsplit(info, witnesses, anchor); -} - -UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit( - MergeToAddressJSInfo& info, - std::vector> witnesses, - uint256 anchor) -{ - if (anchor.IsNull()) { - throw std::runtime_error("anchor is null"); - } - - if (witnesses.size() != info.notes.size()) { - throw runtime_error("number of notes and witnesses do not match"); - } - - if (info.notes.size() != info.zkeys.size()) { - throw runtime_error("number of notes and spending keys do not match"); - } - - for (size_t i = 0; i < witnesses.size(); i++) { - if (!witnesses[i]) { - throw runtime_error("joinsplit input could not be found in tree"); - } - info.vjsin.push_back(JSInput(*witnesses[i], info.notes[i], info.zkeys[i])); - } - - // Make sure there are two inputs and two outputs - while (info.vjsin.size() < ZC_NUM_JS_INPUTS) { - info.vjsin.push_back(JSInput()); - } - - while (info.vjsout.size() < ZC_NUM_JS_OUTPUTS) { - info.vjsout.push_back(JSOutput()); - } - - if (info.vjsout.size() != ZC_NUM_JS_INPUTS || info.vjsin.size() != ZC_NUM_JS_OUTPUTS) { - throw runtime_error("unsupported joinsplit input/output counts"); - } - - CMutableTransaction mtx(tx_); - - LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", - getId(), - tx_.vjoinsplit.size(), - FormatMoney(info.vpub_old), FormatMoney(info.vpub_new), - FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()), - FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value)); - - // Generate the proof, this can take over a minute. - std::array inputs{info.vjsin[0], info.vjsin[1]}; - std::array outputs{info.vjsout[0], info.vjsout[1]}; - std::array inputMap; - std::array outputMap; - - uint256 esk; // payment disclosure - secret - - JSDescription jsdesc = JSDescription::Randomized( - *pzcashParams, - joinSplitPubKey_, - anchor, - inputs, - outputs, - inputMap, - outputMap, - info.vpub_old, - info.vpub_new, - !this->testmode, - &esk); // parameter expects pointer to esk, so pass in address - { - auto verifier = libzcash::ProofVerifier::Strict(); - if (!(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey_))) { - throw std::runtime_error("error verifying joinsplit"); - } - } - - mtx.vjoinsplit.push_back(jsdesc); - - // Empty output script. - CScript scriptCode; - CTransaction signTx(mtx); - uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_); - - // Add the signature - if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, - dataToBeSigned.begin(), 32, - joinSplitPrivKey_) == 0)) { - throw std::runtime_error("crypto_sign_detached failed"); - } - - // Sanity check - if (!(crypto_sign_verify_detached(&mtx.joinSplitSig[0], - dataToBeSigned.begin(), 32, - mtx.joinSplitPubKey.begin()) == 0)) { - throw std::runtime_error("crypto_sign_verify_detached failed"); - } - - CTransaction rawTx(mtx); - tx_ = rawTx; - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << rawTx; - - std::string encryptedNote1; - std::string encryptedNote2; - { - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << ((unsigned char)0x00); - ss2 << jsdesc.ephemeralKey; - ss2 << jsdesc.ciphertexts[0]; - ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey_); - - encryptedNote1 = HexStr(ss2.begin(), ss2.end()); - } - { - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << ((unsigned char)0x01); - ss2 << jsdesc.ephemeralKey; - ss2 << jsdesc.ciphertexts[1]; - ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey_); - - encryptedNote2 = HexStr(ss2.begin(), ss2.end()); - } - - UniValue arrInputMap(UniValue::VARR); - UniValue arrOutputMap(UniValue::VARR); - for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) { - arrInputMap.push_back(static_cast(inputMap[i])); - } - for (size_t i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - arrOutputMap.push_back(static_cast(outputMap[i])); - } - - - // !!! Payment disclosure START - unsigned char buffer[32] = {0}; - memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer - std::vector vch(&buffer[0], &buffer[0] + 32); - uint256 joinSplitPrivKey = uint256(vch); - size_t js_index = tx_.vjoinsplit.size() - 1; - uint256 placeholder; - for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - uint8_t mapped_index = outputMap[i]; - // placeholder for txid will be filled in later when tx has been finalized and signed. - PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index}; - JSOutput output = outputs[mapped_index]; - libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output - PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; - paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); - - LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr)); - } - // !!! Payment disclosure END - - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("encryptednote1", encryptedNote1)); - obj.push_back(Pair("encryptednote2", encryptedNote2)); - obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end()))); - obj.push_back(Pair("inputmap", arrInputMap)); - obj.push_back(Pair("outputmap", arrOutputMap)); - return obj; -} - std::array AsyncRPCOperation_mergetoaddress::get_memo_from_hex_string(std::string s) { std::array memo = {{0x00}}; @@ -764,9 +584,6 @@ void AsyncRPCOperation_mergetoaddress::unlock_utxos() { */ void AsyncRPCOperation_mergetoaddress::lock_notes() { LOCK2(cs_main, pwalletMain->cs_wallet); - for (auto note : sproutNoteInputs_) { - pwalletMain->LockNote(std::get<0>(note)); - } for (auto note : saplingNoteInputs_) { pwalletMain->LockNote(std::get<0>(note)); } @@ -777,9 +594,6 @@ void AsyncRPCOperation_mergetoaddress::lock_notes() { */ void AsyncRPCOperation_mergetoaddress::unlock_notes() { LOCK2(cs_main, pwalletMain->cs_wallet); - for (auto note : sproutNoteInputs_) { - pwalletMain->UnlockNote(std::get<0>(note)); - } for (auto note : saplingNoteInputs_) { pwalletMain->UnlockNote(std::get<0>(note)); } diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 55feb2cbf..5db0ca51b 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2017 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -234,37 +235,6 @@ bool AsyncRPCOperation_shieldcoinbase::main_impl() { return boost::apply_visitor(ShieldToAddress(this, sendAmount), tozaddr_); } -bool ShieldToAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const { - // update the transaction with these inputs - CMutableTransaction rawTx(m_op->tx_); - for (ShieldCoinbaseUTXO & t : m_op->inputs_) { - CTxIn in(COutPoint(t.txid, t.vout)); - if (t.amount >= ASSETCHAINS_TIMELOCKGTE) - in.nSequence = 0xfffffffe; - rawTx.vin.push_back(in); - } - m_op->tx_ = CTransaction(rawTx); - - // Prepare raw transaction to handle JoinSplits - CMutableTransaction mtx(m_op->tx_); - crypto_sign_keypair(m_op->joinSplitPubKey_.begin(), m_op->joinSplitPrivKey_); - mtx.joinSplitPubKey = m_op->joinSplitPubKey_; - m_op->tx_ = CTransaction(mtx); - - // Create joinsplit - UniValue obj(UniValue::VOBJ); - ShieldCoinbaseJSInfo info; - info.vpub_old = sendAmount; - info.vpub_new = 0; - JSOutput jso = JSOutput(zaddr, sendAmount); - info.vjsout.push_back(jso); - obj = m_op->perform_joinsplit(info); - - m_op->sign_send_raw_transaction(obj); - return true; -} - - extern UniValue signrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue sendrawtransaction(const UniValue& params, bool fHelp, const CPubKey& mypk); @@ -406,163 +376,6 @@ void AsyncRPCOperation_shieldcoinbase::sign_send_raw_transaction(UniValue obj) } -UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInfo & info) { - uint32_t consensusBranchId; - uint256 anchor; - { - LOCK(cs_main); - consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - anchor = pcoinsTip->GetBestAnchor(SPROUT); - } - - - if (anchor.IsNull()) { - throw std::runtime_error("anchor is null"); - } - - // Make sure there are two inputs and two outputs - while (info.vjsin.size() < ZC_NUM_JS_INPUTS) { - info.vjsin.push_back(JSInput()); - } - - while (info.vjsout.size() < ZC_NUM_JS_OUTPUTS) { - info.vjsout.push_back(JSOutput()); - } - - if (info.vjsout.size() != ZC_NUM_JS_INPUTS || info.vjsin.size() != ZC_NUM_JS_OUTPUTS) { - throw runtime_error("unsupported joinsplit input/output counts"); - } - - CMutableTransaction mtx(tx_); - - LogPrint("zrpcunsafe", "%s: creating joinsplit at index %d (vpub_old=%s, vpub_new=%s, in[0]=%s, in[1]=%s, out[0]=%s, out[1]=%s)\n", - getId(), - tx_.vjoinsplit.size(), - FormatMoney(info.vpub_old), FormatMoney(info.vpub_new), - FormatMoney(info.vjsin[0].note.value()), FormatMoney(info.vjsin[1].note.value()), - FormatMoney(info.vjsout[0].value), FormatMoney(info.vjsout[1].value) - ); - - // Generate the proof, this can take over a minute. - std::array inputs - {info.vjsin[0], info.vjsin[1]}; - std::array outputs - {info.vjsout[0], info.vjsout[1]}; - - std::array inputMap; - std::array outputMap; - - uint256 esk; // payment disclosure - secret - - JSDescription jsdesc = JSDescription::Randomized( - *pzcashParams, - joinSplitPubKey_, - anchor, - inputs, - outputs, - inputMap, - outputMap, - info.vpub_old, - info.vpub_new, - !this->testmode, - &esk); // parameter expects pointer to esk, so pass in address - { - auto verifier = libzcash::ProofVerifier::Strict(); - if (!(jsdesc.Verify(*pzcashParams, verifier, joinSplitPubKey_))) { - throw std::runtime_error("error verifying joinsplit"); - } - } - - mtx.vjoinsplit.push_back(jsdesc); - - // Empty output script. - CScript scriptCode; - CTransaction signTx(mtx); - uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); - - // Add the signature - if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, - dataToBeSigned.begin(), 32, - joinSplitPrivKey_ - ) == 0)) - { - throw std::runtime_error("crypto_sign_detached failed"); - } - - // Sanity check - if (!(crypto_sign_verify_detached(&mtx.joinSplitSig[0], - dataToBeSigned.begin(), 32, - mtx.joinSplitPubKey.begin() - ) == 0)) - { - throw std::runtime_error("crypto_sign_verify_detached failed"); - } - - CTransaction rawTx(mtx); - tx_ = rawTx; - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << rawTx; - - std::string encryptedNote1; - std::string encryptedNote2; - { - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << ((unsigned char) 0x00); - ss2 << jsdesc.ephemeralKey; - ss2 << jsdesc.ciphertexts[0]; - ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey_); - - encryptedNote1 = HexStr(ss2.begin(), ss2.end()); - } - { - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << ((unsigned char) 0x01); - ss2 << jsdesc.ephemeralKey; - ss2 << jsdesc.ciphertexts[1]; - ss2 << jsdesc.h_sig(*pzcashParams, joinSplitPubKey_); - - encryptedNote2 = HexStr(ss2.begin(), ss2.end()); - } - - UniValue arrInputMap(UniValue::VARR); - UniValue arrOutputMap(UniValue::VARR); - for (size_t i = 0; i < ZC_NUM_JS_INPUTS; i++) { - arrInputMap.push_back(static_cast(inputMap[i])); - } - for (size_t i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - arrOutputMap.push_back(static_cast(outputMap[i])); - } - - // !!! Payment disclosure START - unsigned char buffer[32] = {0}; - memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer - std::vector vch(&buffer[0], &buffer[0] + 32); - uint256 joinSplitPrivKey = uint256(vch); - size_t js_index = tx_.vjoinsplit.size() - 1; - uint256 placeholder; - for (int i = 0; i < ZC_NUM_JS_OUTPUTS; i++) { - uint8_t mapped_index = outputMap[i]; - // placeholder for txid will be filled in later when tx has been finalized and signed. - PaymentDisclosureKey pdKey = {placeholder, js_index, mapped_index}; - JSOutput output = outputs[mapped_index]; - libzcash::SproutPaymentAddress zaddr = output.addr; // randomized output - PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr}; - paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo)); - - LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr)); - } - // !!! Payment disclosure END - - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("encryptednote1", encryptedNote1)); - obj.push_back(Pair("encryptednote2", encryptedNote2)); - obj.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end()))); - obj.push_back(Pair("inputmap", arrInputMap)); - obj.push_back(Pair("outputmap", arrOutputMap)); - return obj; -} - /** * Override getStatus() to append the operation's context object to the default status object. */ diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d0d82a0e8..4be804abb 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers -// Copyright (c) 2019 The Hush developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -314,22 +314,11 @@ bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta) return true; } -bool CWallet::LoadZKeyMetadata(const SproutPaymentAddress &addr, const CKeyMetadata &meta) -{ - AssertLockHeld(cs_wallet); // mapSproutZKeyMetadata - mapSproutZKeyMetadata[addr] = meta; - return true; -} - bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); } -bool CWallet::LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector &vchCryptedSecret) -{ - return CCryptoKeyStore::AddCryptedSproutSpendingKey(addr, rk, vchCryptedSecret); -} bool CWallet::LoadCryptedSaplingZKey( const libzcash::SaplingExtendedFullViewingKey &extfvk, @@ -357,10 +346,6 @@ bool CWallet::LoadSaplingPaymentAddress( return CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr); } -bool CWallet::LoadZKey(const libzcash::SproutSpendingKey &key) -{ - return CCryptoKeyStore::AddSproutSpendingKey(key); -} bool CWallet::LoadCScript(const CScript& redeemScript) { @@ -650,20 +635,6 @@ set CWallet::GetConflicts(const uint256& txid) const result.insert(it->second); } - std::pair range_n; - - for (const JSDescription& jsdesc : wtx.vjoinsplit) { - for (const uint256& nullifier : jsdesc.nullifiers) { - if (mapTxSproutNullifiers.count(nullifier) <= 1) { - continue; // No conflict if zero or one spends - } - range_n = mapTxSproutNullifiers.equal_range(nullifier); - for (TxNullifiers::const_iterator it = range_n.first; it != range_n.second; ++it) { - result.insert(it->second); - } - } - } - std::pair range_o; for (const SpendDescription &spend : wtx.vShieldedSpend) { @@ -1367,7 +1338,6 @@ void CWallet::UpdateNullifierNoteMapForBlock(const CBlock *pblock) { auto hash = tx.GetHash(); bool txIsOurs = mapWallet.count(hash); if (txIsOurs) { - UpdateSproutNullifierNoteMapWithTx(mapWallet[hash]); UpdateSaplingNullifierNoteMapWithTx(mapWallet[hash]); } } @@ -1750,7 +1720,7 @@ void CWallet::GetSaplingNoteWitnesses(std::vector notes, } else { if(*rt == witnesses[i]->root()) { // Something is fucky - std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root:" << rt.GetHash(); + std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root!"; throw std::logic_error(err); } @@ -2104,10 +2074,6 @@ bool CWallet::LoadCryptedHDSeed(const uint256& seedFp, const std::vector& listReceived, if (isFromMyTaddr) { CAmount myVpubOld = 0; CAmount myVpubNew = 0; - for (const JSDescription& js : vjoinsplit) { - bool fMyJSDesc = false; - - // Check input side - for (const uint256& nullifier : js.nullifiers) { - if (pwallet->IsSproutNullifierFromMe(nullifier)) { - fMyJSDesc = true; - break; - } - } - - // Check output side - if (!fMyJSDesc) { - for (const std::pair nd : this->mapSproutNoteData) { - if (nd.first.js < vjoinsplit.size() && nd.first.n < vjoinsplit[nd.first.js].ciphertexts.size()) { - fMyJSDesc = true; - break; - } - } - } - - if (fMyJSDesc) { - myVpubOld += js.vpub_old; - myVpubNew += js.vpub_new; - } - - if (!MoneyRange(js.vpub_old) || !MoneyRange(js.vpub_new) || !MoneyRange(myVpubOld) || !MoneyRange(myVpubNew)) { - throw std::runtime_error("CWalletTx::GetAmounts: value out of range"); - } - } // Create an output for the value taken from or added to the transparent value pool by JoinSplits if (myVpubOld > myVpubNew) { @@ -4580,38 +4516,6 @@ void CWallet::ListLockedCoins(std::vector& vOutpts) // Note Locking Operations -void CWallet::LockNote(const JSOutPoint& output) -{ - AssertLockHeld(cs_wallet); // setLockedSproutNotes - setLockedSproutNotes.insert(output); -} - -void CWallet::UnlockNote(const JSOutPoint& output) -{ - AssertLockHeld(cs_wallet); // setLockedSproutNotes - setLockedSproutNotes.erase(output); -} - -void CWallet::UnlockAllSproutNotes() -{ - AssertLockHeld(cs_wallet); // setLockedSproutNotes - setLockedSproutNotes.clear(); -} - -bool CWallet::IsLockedNote(const JSOutPoint& outpt) const -{ - AssertLockHeld(cs_wallet); // setLockedSproutNotes - - return (setLockedSproutNotes.count(outpt) > 0); -} - -std::vector CWallet::ListLockedSproutNotes() -{ - AssertLockHeld(cs_wallet); // setLockedSproutNotes - std::vector vOutpts(setLockedSproutNotes.begin(), setLockedSproutNotes.end()); - return vOutpts; -} - void CWallet::LockNote(const SaplingOutPoint& output) { AssertLockHeld(cs_wallet); @@ -4988,11 +4892,6 @@ void CWallet::GetFilteredNotes( // Shielded key and address generalizations // -bool IncomingViewingKeyBelongsToWallet::operator()(const libzcash::SproutPaymentAddress &zaddr) const -{ - return m_wallet->HaveSproutViewingKey(zaddr); -} - bool IncomingViewingKeyBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const { libzcash::SaplingIncomingViewingKey ivk; @@ -5004,11 +4903,6 @@ bool IncomingViewingKeyBelongsToWallet::operator()(const libzcash::InvalidEncodi return false; } -bool PaymentAddressBelongsToWallet::operator()(const libzcash::SproutPaymentAddress &zaddr) const -{ - return m_wallet->HaveSproutSpendingKey(zaddr) || m_wallet->HaveSproutViewingKey(zaddr); -} - bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const { libzcash::SaplingIncomingViewingKey ivk; @@ -5024,11 +4918,6 @@ bool PaymentAddressBelongsToWallet::operator()(const libzcash::InvalidEncoding& return false; } -bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const -{ - return m_wallet->HaveSproutSpendingKey(zaddr); -} - bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const { libzcash::SaplingIncomingViewingKey ivk; @@ -5044,17 +4933,6 @@ bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::InvalidEncodin return false; } -boost::optional GetSpendingKeyForPaymentAddress::operator()( - const libzcash::SproutPaymentAddress &zaddr) const -{ - libzcash::SproutSpendingKey k; - if (m_wallet->GetSproutSpendingKey(zaddr, k)) { - return libzcash::SpendingKey(k); - } else { - return boost::none; - } -} - boost::optional GetSpendingKeyForPaymentAddress::operator()( const libzcash::SaplingPaymentAddress &zaddr) const { @@ -5073,20 +4951,6 @@ boost::optional GetSpendingKeyForPaymentAddress::operator return libzcash::SpendingKey(); } -SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const { - auto addr = sk.address(); - if (log){ - LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr)); - } - if (m_wallet->HaveSproutSpendingKey(addr)) { - return KeyAlreadyExists; - } else if (m_wallet-> AddSproutZKey(sk)) { - m_wallet->mapSproutZKeyMetadata[addr].nCreateTime = nTime; - return KeyAdded; - } else { - return KeyNotAdded; - } -} SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const { auto fvk = sk.expsk.full_viewing_key(); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 952a76735..1177bbedd 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers -// Copyright (c) 2019 The Hush developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -124,26 +124,6 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, return true; } -bool CWalletDB::WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr, - const libzcash::ReceivingKey &rk, - const std::vector& vchCryptedSecret, - const CKeyMetadata &keyMeta) -{ - const bool fEraseUnencryptedKey = true; - nWalletDBUpdated++; - - if (!Write(std::make_pair(std::string("zkeymeta"), addr), keyMeta)) - return false; - - if (!Write(std::make_pair(std::string("czkey"), addr), std::make_pair(rk, vchCryptedSecret), false)) - return false; - if (fEraseUnencryptedKey) - { - Erase(std::make_pair(std::string("zkey"), addr)); - } - return true; -} - bool CWalletDB::WriteCryptedSaplingZKey( const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector& vchCryptedSecret, @@ -172,16 +152,6 @@ bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); } -bool CWalletDB::WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta) -{ - nWalletDBUpdated++; - - if (!Write(std::make_pair(std::string("zkeymeta"), addr), keyMeta)) - return false; - - // pair is: tuple_key("zkey", paymentaddress) --> secretkey - return Write(std::make_pair(std::string("zkey"), addr), key, false); -} bool CWalletDB::WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk, const libzcash::SaplingExtendedSpendingKey &key, const CKeyMetadata &keyMeta) @@ -203,18 +173,6 @@ bool CWalletDB::WriteSaplingPaymentAddress( return Write(std::make_pair(std::string("sapzaddr"), addr), ivk, false); } -bool CWalletDB::WriteSproutViewingKey(const libzcash::SproutViewingKey &vk) -{ - nWalletDBUpdated++; - return Write(std::make_pair(std::string("vkey"), vk), '1'); -} - -bool CWalletDB::EraseSproutViewingKey(const libzcash::SproutViewingKey &vk) -{ - nWalletDBUpdated++; - return Erase(std::make_pair(std::string("vkey"), vk)); -} - bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) { nWalletDBUpdated++; @@ -552,6 +510,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "vkey") { + /* libzcash::SproutViewingKey vk; ssKey >> vk; char fYes; @@ -559,24 +518,27 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, if (fYes == '1') pwallet->LoadSproutViewingKey(vk); - // Viewing keys have no birthday information for now, - // so set the wallet birthday to the beginning of time. + Viewing keys have no birthday information for now, + so set the wallet birthday to the beginning of time. pwallet->nTimeFirstKey = 1; + */ } else if (strType == "zkey") { + /* libzcash::SproutPaymentAddress addr; ssKey >> addr; libzcash::SproutSpendingKey key; ssValue >> key; - if (!pwallet->LoadZKey(key)) - { - strErr = "Error reading wallet database: LoadZKey failed"; - return false; - } + //if (!pwallet->LoadZKey(key)) + //{ + // strErr = "Error reading wallet database: LoadZKey failed"; + // return false; + //} wss.nZKeys++; + */ } else if (strType == "sapzkey") { @@ -701,12 +663,12 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssValue >> vchCryptedSecret; wss.nCKeys++; - if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret)) - { - strErr = "Error reading wallet database: LoadCryptedZKey failed"; - return false; - } - wss.fIsEncrypted = true; + //if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret)) + //{ + // strErr = "Error reading wallet database: LoadCryptedZKey failed"; + // return false; + //} + //wss.fIsEncrypted = true; } else if (strType == "csapzkey") { @@ -748,7 +710,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssValue >> keyMeta; wss.nZKeyMeta++; - pwallet->LoadZKeyMetadata(addr, keyMeta); + // pwallet->LoadZKeyMetadata(addr, keyMeta); // ignore earliest key creation time as taddr will exist before any zaddr } From 62d438e0de9efca81ca6d0de3cec348fea8edfdf Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 2 Jun 2020 02:52:19 -0400 Subject: [PATCH 38/98] desprout --- src/gtest/test_joinsplit.cpp | 585 ------------------ src/gtest/test_keystore.cpp | 95 --- src/keystore.h | 85 +-- ...asyncrpcoperation_saplingconsolidation.cpp | 4 +- 4 files changed, 6 insertions(+), 763 deletions(-) delete mode 100644 src/gtest/test_joinsplit.cpp diff --git a/src/gtest/test_joinsplit.cpp b/src/gtest/test_joinsplit.cpp deleted file mode 100644 index 8032fc972..000000000 --- a/src/gtest/test_joinsplit.cpp +++ /dev/null @@ -1,585 +0,0 @@ -#include - -#include "utilstrencodings.h" - -#include -#include - -#include "zcash/prf.h" -#include "util.h" -#include "streams.h" -#include "version.h" -#include "serialize.h" -#include "primitives/transaction.h" -#include "zcash/JoinSplit.hpp" -#include "zcash/Note.hpp" -#include "zcash/NoteEncryption.hpp" -#include "zcash/IncrementalMerkleTree.hpp" - -#include - -using namespace libzcash; - -extern ZCJoinSplit* params; - -// Make the Groth proof for a Sprout statement, -// and store the result in a JSDescription object. -JSDescription makeSproutProof( - ZCJoinSplit& js, - const std::array& inputs, - const std::array& outputs, - const uint256& joinSplitPubKey, - uint64_t vpub_old, - uint64_t vpub_new, - const uint256& rt -){ - return JSDescription(js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); -} - -bool verifySproutProof( - ZCJoinSplit& js, - const JSDescription& jsdesc, - const uint256& joinSplitPubKey -) -{ - auto verifier = libzcash::ProofVerifier::Strict(); - return jsdesc.Verify(js, verifier, joinSplitPubKey); -} - - -void test_full_api(ZCJoinSplit* js) -{ - // Create verification context. - auto verifier = libzcash::ProofVerifier::Strict(); - - // The recipient's information. - SproutSpendingKey recipient_key = SproutSpendingKey::random(); - SproutPaymentAddress recipient_addr = recipient_key.address(); - - // Create the commitment tree - SproutMerkleTree tree; - - // Set up a JoinSplit description - uint64_t vpub_old = 10; - uint64_t vpub_new = 0; - uint256 joinSplitPubKey = random_uint256(); - uint256 rt = tree.root(); - JSDescription jsdesc; - - { - std::array inputs = { - JSInput(), // dummy input - JSInput() // dummy input - }; - - std::array outputs = { - JSOutput(recipient_addr, 10), - JSOutput() // dummy output - }; - - std::array output_notes; - - // Perform the proofs - jsdesc = makeSproutProof( - *js, - inputs, - outputs, - joinSplitPubKey, - vpub_old, - vpub_new, - rt - ); - } - - // Verify both PHGR and Groth Proof: - ASSERT_TRUE(verifySproutProof(*js, jsdesc, joinSplitPubKey)); - - { - SproutMerkleTree tree; - JSDescription jsdesc2; - // Recipient should decrypt - // Now the recipient should spend the money again - auto h_sig = js->h_sig(jsdesc.randomSeed, jsdesc.nullifiers, joinSplitPubKey); - ZCNoteDecryption decryptor(recipient_key.receiving_key()); - - auto note_pt = SproutNotePlaintext::decrypt( - decryptor, - jsdesc.ciphertexts[0], - jsdesc.ephemeralKey, - h_sig, - 0 - ); - - auto decrypted_note = note_pt.note(recipient_addr); - - ASSERT_TRUE(decrypted_note.value() == 10); - - // Insert the commitments from the last tx into the tree - tree.append(jsdesc.commitments[0]); - auto witness_recipient = tree.witness(); - tree.append(jsdesc.commitments[1]); - witness_recipient.append(jsdesc.commitments[1]); - vpub_old = 0; - vpub_new = 1; - rt = tree.root(); - auto joinSplitPubKey2 = random_uint256(); - - { - std::array inputs = { - JSInput(), // dummy input - JSInput(witness_recipient, decrypted_note, recipient_key) - }; - - SproutSpendingKey second_recipient = SproutSpendingKey::random(); - SproutPaymentAddress second_addr = second_recipient.address(); - - std::array outputs = { - JSOutput(second_addr, 9), - JSOutput() // dummy output - }; - - std::array output_notes; - - - // Perform the proofs - jsdesc2 = makeSproutProof( - *js, - inputs, - outputs, - joinSplitPubKey2, - vpub_old, - vpub_new, - rt - ); - - } - - - // Verify Groth Proof: - ASSERT_TRUE(verifySproutProof(*js, jsdesc2, joinSplitPubKey2)); - } -} - -// Invokes the API (but does not compute a proof) -// to test exceptions -void invokeAPI( - ZCJoinSplit* js, - const std::array& inputs, - const std::array& outputs, - uint64_t vpub_old, - uint64_t vpub_new, - const uint256& rt -) { - uint256 ephemeralKey; - uint256 randomSeed; - uint256 joinSplitPubKey = random_uint256(); - std::array macs; - std::array nullifiers; - std::array commitments; - std::array ciphertexts; - - std::array output_notes; - - // Groth - SproutProof proof = js->prove( - inputs, - outputs, - output_notes, - ciphertexts, - ephemeralKey, - joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new, - rt, - false - ); -} - -void invokeAPIFailure( - ZCJoinSplit* js, - const std::array& inputs, - const std::array& outputs, - uint64_t vpub_old, - uint64_t vpub_new, - const uint256& rt, - std::string reason -) -{ - try { - invokeAPI(js, inputs, outputs, vpub_old, vpub_new, rt); - FAIL() << "It worked, when it shouldn't have!"; - } catch(std::invalid_argument const & err) { - EXPECT_EQ(err.what(), reason); - } catch(...) { - FAIL() << "Expected invalid_argument exception."; - } -} - -TEST(joinsplit, h_sig) -{ -/* -// by Taylor Hornby - -import pyblake2 -import binascii - -def hSig(randomSeed, nf1, nf2, joinSplitPubKey): - return pyblake2.blake2b( - data=(randomSeed + nf1 + nf2 + joinSplitPubKey), - digest_size=32, - person=b"ZcashComputehSig" - ).digest() - -INCREASING = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" - -TEST_VECTORS = [ - [b"a" * 32, b"b" * 32, b"c" * 32, b"d" * 32], - [b"\x00" * 32, b"\x00" * 32, b"\x00" * 32, b"\x00" * 32], - [b"\xFF" * 32, b"\xFF" * 32, b"\xFF" * 32, b"\xFF" * 32], - [INCREASING, INCREASING, INCREASING, INCREASING] -] - -for test_input in TEST_VECTORS: - print "---" - print "\"" + binascii.hexlify(test_input[0][::-1]) + "\"" - print "\"" + binascii.hexlify(test_input[1][::-1]) + "\"" - print "\"" + binascii.hexlify(test_input[2][::-1]) + "\"" - print "\"" + binascii.hexlify(test_input[3][::-1]) + "\"" - print "\"" + binascii.hexlify(hSig(test_input[0], test_input[1], test_input[2], test_input[3])[::-1]) + "\"" -*/ - - std::vector> tests = { - { - "6161616161616161616161616161616161616161616161616161616161616161", - "6262626262626262626262626262626262626262626262626262626262626262", - "6363636363636363636363636363636363636363636363636363636363636363", - "6464646464646464646464646464646464646464646464646464646464646464", - "a8cba69f1fa329c055756b4af900f8a00b61e44f4cb8a1824ceb58b90a5b8113" - }, - { - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000000", - "697322276b5dd93b12fb1fcbd2144b2960f24c73aac6c6a0811447be1e7f1e19" - }, - { - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "4961048919f0ca79d49c9378c36a91a8767060001f4212fe6f7d426f3ccf9f32" - }, - { - "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100", - "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100", - "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100", - "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100", - "b61110ec162693bc3d9ca7fb0eec3afd2e278e2f41394b3ff11d7cb761ad4b27" - } - }; - - BOOST_FOREACH(std::vector& v, tests) { - auto expected = ZCJoinSplit::h_sig( - uint256S(v[0]), - {uint256S(v[1]), uint256S(v[2])}, - uint256S(v[3]) - ); - - EXPECT_EQ(expected, uint256S(v[4])); - } -} - -void increment_note_witnesses( - const uint256& element, - std::vector& witnesses, - SproutMerkleTree& tree -) -{ - tree.append(element); - for (SproutWitness& w : witnesses) { - w.append(element); - } - witnesses.push_back(tree.witness()); -} - -TEST(joinsplit, full_api_test) -{ - { - std::vector witnesses; - SproutMerkleTree tree; - increment_note_witnesses(uint256(), witnesses, tree); - SproutSpendingKey sk = SproutSpendingKey::random(); - SproutPaymentAddress addr = sk.address(); - SproutNote note1(addr.a_pk, 100, random_uint256(), random_uint256()); - increment_note_witnesses(note1.cm(), witnesses, tree); - SproutNote note2(addr.a_pk, 100, random_uint256(), random_uint256()); - increment_note_witnesses(note2.cm(), witnesses, tree); - SproutNote note3(addr.a_pk, 2100000000000001, random_uint256(), random_uint256()); - increment_note_witnesses(note3.cm(), witnesses, tree); - SproutNote note4(addr.a_pk, 1900000000000000, random_uint256(), random_uint256()); - increment_note_witnesses(note4.cm(), witnesses, tree); - SproutNote note5(addr.a_pk, 1900000000000000, random_uint256(), random_uint256()); - increment_note_witnesses(note5.cm(), witnesses, tree); - - // Should work - invokeAPI(params, - { - JSInput(), - JSInput() - }, - { - JSOutput(), - JSOutput() - }, - 0, - 0, - tree.root()); - - // lhs > MAX_MONEY - invokeAPIFailure(params, - { - JSInput(), - JSInput() - }, - { - JSOutput(), - JSOutput() - }, - 2100000000000001, - 0, - tree.root(), - "nonsensical vpub_old value"); - - // rhs > MAX_MONEY - invokeAPIFailure(params, - { - JSInput(), - JSInput() - }, - { - JSOutput(), - JSOutput() - }, - 0, - 2100000000000001, - tree.root(), - "nonsensical vpub_new value"); - - // input witness for the wrong element - invokeAPIFailure(params, - { - JSInput(witnesses[0], note1, sk), - JSInput() - }, - { - JSOutput(), - JSOutput() - }, - 0, - 100, - tree.root(), - "witness of wrong element for joinsplit input"); - - // input witness doesn't match up with - // real root - invokeAPIFailure(params, - { - JSInput(witnesses[1], note1, sk), - JSInput() - }, - { - JSOutput(), - JSOutput() - }, - 0, - 100, - uint256(), - "joinsplit not anchored to the correct root"); - - // input is in the tree now! this should work - invokeAPI(params, - { - JSInput(witnesses[1], note1, sk), - JSInput() - }, - { - JSOutput(), - JSOutput() - }, - 0, - 100, - tree.root()); - - // Wrong secret key - invokeAPIFailure(params, - { - JSInput(witnesses[1], note1, SproutSpendingKey::random()), - JSInput() - }, - { - JSOutput(), - JSOutput() - }, - 0, - 0, - tree.root(), - "input note not authorized to spend with given key"); - - // Absurd input value - invokeAPIFailure(params, - { - JSInput(witnesses[3], note3, sk), - JSInput() - }, - { - JSOutput(), - JSOutput() - }, - 0, - 0, - tree.root(), - "nonsensical input note value"); - - // Absurd total input value - invokeAPIFailure(params, - { - JSInput(witnesses[4], note4, sk), - JSInput(witnesses[5], note5, sk) - }, - { - JSOutput(), - JSOutput() - }, - 0, - 0, - tree.root(), - "nonsensical left hand size of joinsplit balance"); - - // Absurd output value - invokeAPIFailure(params, - { - JSInput(), - JSInput() - }, - { - JSOutput(addr, 2100000000000001), - JSOutput() - }, - 0, - 0, - tree.root(), - "nonsensical output value"); - - // Absurd total output value - invokeAPIFailure(params, - { - JSInput(), - JSInput() - }, - { - JSOutput(addr, 1900000000000000), - JSOutput(addr, 1900000000000000) - }, - 0, - 0, - tree.root(), - "nonsensical right hand side of joinsplit balance"); - - // Absurd total output value - invokeAPIFailure(params, - { - JSInput(), - JSInput() - }, - { - JSOutput(addr, 1900000000000000), - JSOutput() - }, - 0, - 0, - tree.root(), - "invalid joinsplit balance"); - } - - test_full_api(params); -} - -TEST(joinsplit, note_plaintexts) -{ - uint252 a_sk = uint252(uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516840e")); - uint256 a_pk = PRF_addr_a_pk(a_sk); - uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk); - uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc); - SproutPaymentAddress addr_pk(a_pk, pk_enc); - - uint256 h_sig; - - ZCNoteEncryption encryptor(h_sig); - uint256 epk = encryptor.get_epk(); - - SproutNote note(a_pk, - 1945813, - random_uint256(), - random_uint256() - ); - - std::array memo; - - SproutNotePlaintext note_pt(note, memo); - - ZCNoteEncryption::Ciphertext ct = note_pt.encrypt(encryptor, pk_enc); - - ZCNoteDecryption decryptor(sk_enc); - - auto decrypted = SproutNotePlaintext::decrypt(decryptor, ct, epk, h_sig, 0); - auto decrypted_note = decrypted.note(addr_pk); - - ASSERT_TRUE(decrypted_note.a_pk == note.a_pk); - ASSERT_TRUE(decrypted_note.rho == note.rho); - ASSERT_TRUE(decrypted_note.r == note.r); - ASSERT_TRUE(decrypted_note.value() == note.value()); - - ASSERT_TRUE(decrypted.memo() == note_pt.memo()); - - // Check memo() returns by reference, not return by value, for use cases such as: - // std::string data(plaintext.memo().begin(), plaintext.memo().end()); - ASSERT_TRUE(decrypted.memo().data() == decrypted.memo().data()); - - // Check serialization of note plaintext - CDataStream ss(SER_DISK, PROTOCOL_VERSION); - ss << note_pt; - SproutNotePlaintext note_pt2; - ss >> note_pt2; - ASSERT_EQ(note_pt.value(), note.value()); - ASSERT_EQ(note_pt.value(), note_pt2.value()); - ASSERT_EQ(note_pt.memo(), note_pt2.memo()); - ASSERT_EQ(note_pt.rho, note_pt2.rho); - ASSERT_EQ(note_pt.r, note_pt2.r); -} - -TEST(joinsplit, note_class) -{ - uint252 a_sk = uint252(uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516840e")); - uint256 a_pk = PRF_addr_a_pk(a_sk); - uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk); - uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc); - SproutPaymentAddress addr_pk(a_pk, pk_enc); - - SproutNote note(a_pk, - 1945813, - random_uint256(), - random_uint256()); - - SproutNote clone = note; - ASSERT_NE(¬e, &clone); - ASSERT_EQ(note.value(), clone.value()); - ASSERT_EQ(note.cm(), clone.cm()); - ASSERT_EQ(note.rho, clone.rho); - ASSERT_EQ(note.r, clone.r); - ASSERT_EQ(note.a_pk, clone.a_pk); -} diff --git a/src/gtest/test_keystore.cpp b/src/gtest/test_keystore.cpp index ccf9cb9ba..a6237a0e4 100644 --- a/src/gtest/test_keystore.cpp +++ b/src/gtest/test_keystore.cpp @@ -95,101 +95,6 @@ TEST(keystore_tests, sapling_keys) { } } -TEST(keystore_tests, store_and_retrieve_spending_key) { - CBasicKeyStore keyStore; - libzcash::SproutSpendingKey skOut; - - std::set addrs; - keyStore.GetSproutPaymentAddresses(addrs); - EXPECT_EQ(0, addrs.size()); - - auto sk = libzcash::SproutSpendingKey::random(); - auto addr = sk.address(); - - // Sanity-check: we can't get a key we haven't added - EXPECT_FALSE(keyStore.HaveSproutSpendingKey(addr)); - EXPECT_FALSE(keyStore.GetSproutSpendingKey(addr, skOut)); - - keyStore.AddSproutSpendingKey(sk); - EXPECT_TRUE(keyStore.HaveSproutSpendingKey(addr)); - EXPECT_TRUE(keyStore.GetSproutSpendingKey(addr, skOut)); - EXPECT_EQ(sk, skOut); - - keyStore.GetSproutPaymentAddresses(addrs); - EXPECT_EQ(1, addrs.size()); - EXPECT_EQ(1, addrs.count(addr)); -} - -TEST(keystore_tests, store_and_retrieve_note_decryptor) { - CBasicKeyStore keyStore; - ZCNoteDecryption decOut; - - auto sk = libzcash::SproutSpendingKey::random(); - auto addr = sk.address(); - - EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut)); - - keyStore.AddSproutSpendingKey(sk); - EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut)); - EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut); -} - -TEST(keystore_tests, StoreAndRetrieveViewingKey) { - CBasicKeyStore keyStore; - libzcash::SproutViewingKey vkOut; - libzcash::SproutSpendingKey skOut; - ZCNoteDecryption decOut; - - auto sk = libzcash::SproutSpendingKey::random(); - auto vk = sk.viewing_key(); - auto addr = sk.address(); - - // Sanity-check: we can't get a viewing key we haven't added - EXPECT_FALSE(keyStore.HaveSproutViewingKey(addr)); - EXPECT_FALSE(keyStore.GetSproutViewingKey(addr, vkOut)); - - // and we shouldn't have a spending key or decryptor either - EXPECT_FALSE(keyStore.HaveSproutSpendingKey(addr)); - EXPECT_FALSE(keyStore.GetSproutSpendingKey(addr, skOut)); - EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut)); - - // and we can't find it in our list of addresses - std::set addresses; - keyStore.GetSproutPaymentAddresses(addresses); - EXPECT_FALSE(addresses.count(addr)); - - keyStore.AddSproutViewingKey(vk); - EXPECT_TRUE(keyStore.HaveSproutViewingKey(addr)); - EXPECT_TRUE(keyStore.GetSproutViewingKey(addr, vkOut)); - EXPECT_EQ(vk, vkOut); - - // We should still not have the spending key... - EXPECT_FALSE(keyStore.HaveSproutSpendingKey(addr)); - EXPECT_FALSE(keyStore.GetSproutSpendingKey(addr, skOut)); - - // ... but we should have a decryptor - EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut)); - EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut); - - // ... and we should find it in our list of addresses - addresses.clear(); - keyStore.GetSproutPaymentAddresses(addresses); - EXPECT_TRUE(addresses.count(addr)); - - keyStore.RemoveSproutViewingKey(vk); - EXPECT_FALSE(keyStore.HaveSproutViewingKey(addr)); - EXPECT_FALSE(keyStore.GetSproutViewingKey(addr, vkOut)); - EXPECT_FALSE(keyStore.HaveSproutSpendingKey(addr)); - EXPECT_FALSE(keyStore.GetSproutSpendingKey(addr, skOut)); - addresses.clear(); - keyStore.GetSproutPaymentAddresses(addresses); - EXPECT_FALSE(addresses.count(addr)); - - // We still have a decryptor because those are cached in memory - // (and also we only remove viewing keys when adding a spending key) - EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut)); - EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut); -} // Sapling TEST(keystore_tests, StoreAndRetrieveSaplingSpendingKey) { diff --git a/src/keystore.h b/src/keystore.h index c2e1f25d9..ac2ccf233 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -70,14 +71,6 @@ public: virtual bool HaveWatchOnly(const CScript &dest) const =0; virtual bool HaveWatchOnly() const =0; - //! Add a spending key to the store. - virtual bool AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk) =0; - - //! Check whether a spending key corresponding to a given payment address is present in the store. - virtual bool HaveSproutSpendingKey(const libzcash::SproutPaymentAddress &address) const =0; - virtual bool GetSproutSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey& skOut) const =0; - virtual void GetSproutPaymentAddresses(std::set &setAddress) const =0; - //! Add a Sapling spending key to the store. virtual bool AddSaplingSpendingKey( const libzcash::SaplingExtendedSpendingKey &sk, @@ -106,21 +99,11 @@ public: libzcash::SaplingIncomingViewingKey& ivkOut) const =0; virtual void GetSaplingPaymentAddresses(std::set &setAddress) const =0; - //! Support for Sprout viewing keys - virtual bool AddSproutViewingKey(const libzcash::SproutViewingKey &vk) =0; - virtual bool RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk) =0; - virtual bool HaveSproutViewingKey(const libzcash::SproutPaymentAddress &address) const =0; - virtual bool GetSproutViewingKey( - const libzcash::SproutPaymentAddress &address, - libzcash::SproutViewingKey& vkOut) const =0; }; typedef std::map KeyMap; typedef std::map ScriptMap; typedef std::set WatchOnlySet; -typedef std::map SproutSpendingKeyMap; -typedef std::map SproutViewingKeyMap; -typedef std::map NoteDecryptorMap; // Full viewing key has equivalent functionality to a transparent address // When encrypting wallet, encrypt SaplingSpendingKeyMap, while leaving SaplingFullViewingKeyMap unencrypted @@ -137,9 +120,11 @@ protected: KeyMap mapKeys; ScriptMap mapScripts; WatchOnlySet setWatchOnly; + /* SproutSpendingKeyMap mapSproutSpendingKeys; SproutViewingKeyMap mapSproutViewingKeys; NoteDecryptorMap mapNoteDecryptors; + */ SaplingSpendingKeyMap mapSaplingSpendingKeys; SaplingFullViewingKeyMap mapSaplingFullViewingKeys; @@ -195,62 +180,6 @@ public: virtual bool HaveWatchOnly(const CScript &dest) const; virtual bool HaveWatchOnly() const; - bool AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk); - bool HaveSproutSpendingKey(const libzcash::SproutPaymentAddress &address) const - { - bool result; - { - LOCK(cs_SpendingKeyStore); - result = (mapSproutSpendingKeys.count(address) > 0); - } - return result; - } - bool GetSproutSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const - { - { - LOCK(cs_SpendingKeyStore); - SproutSpendingKeyMap::const_iterator mi = mapSproutSpendingKeys.find(address); - if (mi != mapSproutSpendingKeys.end()) - { - skOut = mi->second; - return true; - } - } - return false; - } - bool GetNoteDecryptor(const libzcash::SproutPaymentAddress &address, ZCNoteDecryption &decOut) const - { - { - LOCK(cs_SpendingKeyStore); - NoteDecryptorMap::const_iterator mi = mapNoteDecryptors.find(address); - if (mi != mapNoteDecryptors.end()) - { - decOut = mi->second; - return true; - } - } - return false; - } - void GetSproutPaymentAddresses(std::set &setAddress) const - { - setAddress.clear(); - { - LOCK(cs_SpendingKeyStore); - SproutSpendingKeyMap::const_iterator mi = mapSproutSpendingKeys.begin(); - while (mi != mapSproutSpendingKeys.end()) - { - setAddress.insert((*mi).first); - mi++; - } - SproutViewingKeyMap::const_iterator mvi = mapSproutViewingKeys.begin(); - while (mvi != mapSproutViewingKeys.end()) - { - setAddress.insert((*mvi).first); - mvi++; - } - } - } - //! Sapling bool AddSaplingSpendingKey( const libzcash::SaplingExtendedSpendingKey &sk, @@ -313,17 +242,11 @@ public: } } - virtual bool AddSproutViewingKey(const libzcash::SproutViewingKey &vk); - virtual bool RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk); - virtual bool HaveSproutViewingKey(const libzcash::SproutPaymentAddress &address) const; - virtual bool GetSproutViewingKey( - const libzcash::SproutPaymentAddress &address, - libzcash::SproutViewingKey& vkOut) const; }; typedef std::vector > CKeyingMaterial; typedef std::map > > CryptedKeyMap; -typedef std::map > CryptedSproutSpendingKeyMap; +//typedef std::map > CryptedSproutSpendingKeyMap; //! Sapling typedef std::map > CryptedSaplingSpendingKeyMap; diff --git a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp index 8f7078c81..0a57b8948 100644 --- a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp +++ b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Hush developers +// Copyright (c) 2019-2020 The Hush developers // Copyright (c) 2019 CryptoForge // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -93,7 +93,7 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() { { LOCK2(cs_main, pwalletMain->cs_wallet); // We set minDepth to 11 to avoid unconfirmed notes and in anticipation of specifying - // an anchor at height N-10 for each Sprout JoinSplit description + // an anchor at height N-10 for each SpendDescription // Consider, should notes be sorted? pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 11); if (fConsolidationMapUsed) { From 2134269e7676b1bac6e0a61c76dde6e01791251c Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 3 Jun 2020 00:12:54 -0400 Subject: [PATCH 39/98] desprout --- src/gtest/test_keystore.cpp | 77 ----------------------------------- src/rpc/misc.cpp | 14 +------ src/test/rpc_wallet_tests.cpp | 57 +++++--------------------- src/txdb.cpp | 12 ------ src/wallet/crypter.h | 34 +--------------- src/wallet/rpcdump.cpp | 77 ++++++++++------------------------- 6 files changed, 34 insertions(+), 237 deletions(-) diff --git a/src/gtest/test_keystore.cpp b/src/gtest/test_keystore.cpp index a6237a0e4..a8c984984 100644 --- a/src/gtest/test_keystore.cpp +++ b/src/gtest/test_keystore.cpp @@ -185,9 +185,6 @@ TEST(keystore_tests, StoreAndRetrieveHDSeedInEncryptedStore) { // 3) Test adding a new seed to an already-encrypted key store TestCCryptoKeyStore keyStore2; - // Add a Sprout address so the wallet has something to test when decrypting - ASSERT_TRUE(keyStore2.AddSproutSpendingKey(libzcash::SproutSpendingKey::random())); - ASSERT_TRUE(keyStore2.EncryptKeys(vMasterKey)); ASSERT_TRUE(keyStore2.Unlock(vMasterKey)); @@ -201,78 +198,4 @@ TEST(keystore_tests, StoreAndRetrieveHDSeedInEncryptedStore) { EXPECT_EQ(seed3, seedOut); } -TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) { - TestCCryptoKeyStore keyStore; - uint256 r {GetRandHash()}; - CKeyingMaterial vMasterKey (r.begin(), r.end()); - libzcash::SproutSpendingKey keyOut; - ZCNoteDecryption decOut; - std::set addrs; - - // 1) Test adding a key to an unencrypted key store, then encrypting it - auto sk = libzcash::SproutSpendingKey::random(); - auto addr = sk.address(); - EXPECT_FALSE(keyStore.GetNoteDecryptor(addr, decOut)); - - keyStore.AddSproutSpendingKey(sk); - ASSERT_TRUE(keyStore.HaveSproutSpendingKey(addr)); - ASSERT_TRUE(keyStore.GetSproutSpendingKey(addr, keyOut)); - ASSERT_EQ(sk, keyOut); - EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut)); - EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut); - - ASSERT_TRUE(keyStore.EncryptKeys(vMasterKey)); - ASSERT_TRUE(keyStore.HaveSproutSpendingKey(addr)); - ASSERT_FALSE(keyStore.GetSproutSpendingKey(addr, keyOut)); - EXPECT_TRUE(keyStore.GetNoteDecryptor(addr, decOut)); - EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut); - - // Unlocking with a random key should fail - uint256 r2 {GetRandHash()}; - CKeyingMaterial vRandomKey (r2.begin(), r2.end()); - EXPECT_FALSE(keyStore.Unlock(vRandomKey)); - - // Unlocking with a slightly-modified vMasterKey should fail - CKeyingMaterial vModifiedKey (r.begin(), r.end()); - vModifiedKey[0] += 1; - EXPECT_FALSE(keyStore.Unlock(vModifiedKey)); - - // Unlocking with vMasterKey should succeed - ASSERT_TRUE(keyStore.Unlock(vMasterKey)); - ASSERT_TRUE(keyStore.GetSproutSpendingKey(addr, keyOut)); - ASSERT_EQ(sk, keyOut); - - keyStore.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(1, addrs.size()); - ASSERT_EQ(1, addrs.count(addr)); - - // 2) Test adding a spending key to an already-encrypted key store - auto sk2 = libzcash::SproutSpendingKey::random(); - auto addr2 = sk2.address(); - EXPECT_FALSE(keyStore.GetNoteDecryptor(addr2, decOut)); - - keyStore.AddSproutSpendingKey(sk2); - ASSERT_TRUE(keyStore.HaveSproutSpendingKey(addr2)); - ASSERT_TRUE(keyStore.GetSproutSpendingKey(addr2, keyOut)); - ASSERT_EQ(sk2, keyOut); - EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut)); - EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut); - - ASSERT_TRUE(keyStore.Lock()); - ASSERT_TRUE(keyStore.HaveSproutSpendingKey(addr2)); - ASSERT_FALSE(keyStore.GetSproutSpendingKey(addr2, keyOut)); - EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut)); - EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut); - - ASSERT_TRUE(keyStore.Unlock(vMasterKey)); - ASSERT_TRUE(keyStore.GetSproutSpendingKey(addr2, keyOut)); - ASSERT_EQ(sk2, keyOut); - EXPECT_TRUE(keyStore.GetNoteDecryptor(addr2, decOut)); - EXPECT_EQ(ZCNoteDecryption(sk2.receiving_key()), decOut); - - keyStore.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(2, addrs.size()); - ASSERT_EQ(1, addrs.count(addr)); - ASSERT_EQ(1, addrs.count(addr2)); -} #endif diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index fc4b39ef0..a0248c2de 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -594,19 +595,6 @@ class DescribePaymentAddressVisitor : public boost::static_visitor public: UniValue operator()(const libzcash::InvalidEncoding &zaddr) const { return UniValue(UniValue::VOBJ); } - UniValue operator()(const libzcash::SproutPaymentAddress &zaddr) const { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("type", "sprout")); - obj.push_back(Pair("payingkey", zaddr.a_pk.GetHex())); - obj.push_back(Pair("transmissionkey", zaddr.pk_enc.GetHex())); -#ifdef ENABLE_WALLET - if (pwalletMain) { - obj.push_back(Pair("ismine", pwalletMain->HaveSproutSpendingKey(zaddr))); - } -#endif - return obj; - } - UniValue operator()(const libzcash::SaplingPaymentAddress &zaddr) const { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("type", "sapling")); diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 1eaade55b..f68bf8b79 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2013-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php #include "rpc/server.h" #include "rpc/client.h" @@ -341,38 +342,12 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress) BOOST_CHECK_THROW(CallRPC("z_validateaddress"), runtime_error); BOOST_CHECK_THROW(CallRPC("z_validateaddress toomany args"), runtime_error); - // Wallet should be empty - std::set addrs; - pwalletMain->GetSproutPaymentAddresses(addrs); - BOOST_CHECK(addrs.size()==0); - // This address is not valid, it belongs to another network BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztaaga95QAPyp1kSQ1hD2kguCpzyMHjxWZqaYDEkzbvo7uYQYAw2S8X4Kx98AvhhofMtQL8PAXKHuZsmhRcanavKRKmdCzk")); UniValue resultObj = retValue.get_obj(); bool b = find_value(resultObj, "isvalid").get_bool(); BOOST_CHECK_EQUAL(b, false); - // This address is valid, but the spending key is not in this wallet - BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zcfA19SDAKRYHLoRDoShcoz4nPohqWxuHcqg8WAxsiB2jFrrs6k7oSvst3UZvMYqpMNSRBkxBsnyjjngX5L55FxMzLKach8")); - resultObj = retValue.get_obj(); - b = find_value(resultObj, "isvalid").get_bool(); - BOOST_CHECK_EQUAL(b, true); - BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sprout"); - b = find_value(resultObj, "ismine").get_bool(); - BOOST_CHECK_EQUAL(b, false); - - // Let's import a spending key to the wallet and validate its payment address - BOOST_CHECK_NO_THROW(CallRPC("z_importkey SKxoWv77WGwFnUJitQKNEcD636bL4X5Gd6wWmgaA4Q9x8jZBPJXT")); - BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zcWsmqT4X2V4jgxbgiCzyrAfRT1vi1F4sn7M5Pkh66izzw8Uk7LBGAH3DtcSMJeUb2pi3W4SQF8LMKkU2cUuVP68yAGcomL")); - resultObj = retValue.get_obj(); - b = find_value(resultObj, "isvalid").get_bool(); - BOOST_CHECK_EQUAL(b, true); - BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sprout"); - b = find_value(resultObj, "ismine").get_bool(); - BOOST_CHECK_EQUAL(b, true); - BOOST_CHECK_EQUAL(find_value(resultObj, "payingkey").get_str(), "f5bb3c888ccc9831e3f6ba06e7528e26a312eec3acc1823be8918b6a3a5e20ad"); - BOOST_CHECK_EQUAL(find_value(resultObj, "transmissionkey").get_str(), "7a58c7132446564e6b810cf895c20537b3528357dc00150a8e201f491efa9c1a"); - // This Sapling address is not valid, it belongs to another network BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztestsapling1knww2nyjc62njkard0jmx7hlsj6twxmxwprn7anvrv4dc2zxanl3nemc0qx2hvplxmd2uau8gyw")); resultObj = retValue.get_obj(); @@ -398,16 +373,6 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) { LOCK2(cs_main, pwalletMain->cs_wallet); - // wallet should be empty - std::set addrs; - pwalletMain->GetSproutPaymentAddresses(addrs); - BOOST_CHECK(addrs.size()==0); - - // wallet should have one key - libzcash::SproutPaymentAddress addr = pwalletMain->GenerateNewSproutZKey(); - pwalletMain->GetSproutPaymentAddresses(addrs); - BOOST_CHECK(addrs.size()==1); - // Set up paths boost::filesystem::path tmppath = boost::filesystem::temp_directory_path(); boost::filesystem::path tmpfilename = boost::filesystem::unique_path("%%%%%%%%"); @@ -429,9 +394,6 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet) BOOST_CHECK_NO_THROW(CallRPC(string("z_exportwallet ") + tmpfilename.string())); - libzcash::SproutSpendingKey key; - BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, key)); - std::string s1 = EncodePaymentAddress(addr); std::string s2 = EncodeSpendingKey(key); @@ -474,13 +436,13 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) BOOST_CHECK_THROW(CallRPC("z_importwallet toomany args"), runtime_error); // create a random key locally - auto testSpendingKey = libzcash::SproutSpendingKey::random(); + auto testSpendingKey = libzcash::SaplingSpendingKey::random(); auto testPaymentAddress = testSpendingKey.address(); std::string testAddr = EncodePaymentAddress(testPaymentAddress); std::string testKey = EncodeSpendingKey(testSpendingKey); // create test data using the random key - std::string format_str = "# Wallet dump created by Komodo v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n" + std::string format_str = "# Wallet dump created by Hush v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n" "# * Created on 2016-08-12T21:55:36Z\n" "# * Best block at time of backup was 0 (0de0a3851fef2d433b9b4f51d4342bdd24c5ddd793eb8fba57189f07e9235d52),\n" "# mined on 2009-01-03T18:15:05Z\n" @@ -504,14 +466,14 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) // wallet should currently be empty std::set addrs; - pwalletMain->GetSproutPaymentAddresses(addrs); + pwalletMain->GetSaplingPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==0); // import test data from file into wallet BOOST_CHECK_NO_THROW(CallRPC(string("z_importwallet ") + path)); // wallet should now have one zkey - pwalletMain->GetSproutPaymentAddresses(addrs); + pwalletMain->GetSaplingPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==1); // check that we have the spending key for the address @@ -521,10 +483,11 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) auto addr = boost::get(address); BOOST_CHECK(pwalletMain->HaveSproutSpendingKey(addr)); + // Verify the spending key is the same as the test data - libzcash::SproutSpendingKey k; - BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, k)); - BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k)); + //libzcash::SproutSpendingKey k; + //BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, k)); + //BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k)); } diff --git a/src/txdb.cpp b/src/txdb.cpp index 46140f546..6fe8bd575 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -67,18 +67,6 @@ CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(Get } -bool CCoinsViewDB::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { - if (rt == SproutMerkleTree::empty_root()) { - SproutMerkleTree new_tree; - tree = new_tree; - return true; - } - - bool read = db.Read(make_pair(DB_SPROUT_ANCHOR, rt), tree); - - return read; -} - bool CCoinsViewDB::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { if (rt == SaplingMerkleTree::empty_root()) { SaplingMerkleTree new_tree; diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index f42a762af..8a7de32b4 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -1,4 +1,5 @@ // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -145,7 +146,7 @@ class CCryptoKeyStore : public CBasicKeyStore private: std::pair> cryptedHDSeed; CryptedKeyMap mapCryptedKeys; - CryptedSproutSpendingKeyMap mapCryptedSproutSpendingKeys; + //CryptedSproutSpendingKeyMap mapCryptedSproutSpendingKeys; CryptedSaplingSpendingKeyMap mapCryptedSaplingSpendingKeys; CKeyingMaterial vMasterKey; @@ -223,37 +224,6 @@ public: mi++; } } - virtual bool AddCryptedSproutSpendingKey( - const libzcash::SproutPaymentAddress &address, - const libzcash::ReceivingKey &rk, - const std::vector &vchCryptedSecret); - bool AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk); - bool HaveSproutSpendingKey(const libzcash::SproutPaymentAddress &address) const - { - { - LOCK(cs_SpendingKeyStore); - if (!IsCrypted()) - return CBasicKeyStore::HaveSproutSpendingKey(address); - return mapCryptedSproutSpendingKeys.count(address) > 0; - } - return false; - } - bool GetSproutSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const; - void GetSproutPaymentAddresses(std::set &setAddress) const - { - if (!IsCrypted()) - { - CBasicKeyStore::GetSproutPaymentAddresses(setAddress); - return; - } - setAddress.clear(); - CryptedSproutSpendingKeyMap::const_iterator mi = mapCryptedSproutSpendingKeys.begin(); - while (mi != mapCryptedSproutSpendingKeys.end()) - { - setAddress.insert((*mi).first); - mi++; - } - } //! Sapling virtual bool AddCryptedSaplingSpendingKey( const libzcash::SaplingExtendedFullViewingKey &extfvk, diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 44639f663..1499a58b9 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -856,48 +856,27 @@ UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& m throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid viewing key"); } - if (boost::get(&viewingkey) == nullptr) { - if (params.size() < 4) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Missing zaddr for Sapling viewing key."); - } - string strAddress = params[3].get_str(); - auto address = DecodePaymentAddress(strAddress); - if (!IsValidPaymentAddress(address)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr"); - } - - auto addr = boost::get(address); - auto ivk = boost::get(viewingkey); + if (params.size() < 4) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Missing zaddr for Sapling viewing key."); + } + string strAddress = params[3].get_str(); + auto address = DecodePaymentAddress(strAddress); + if (!IsValidPaymentAddress(address)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr"); + } - if (pwalletMain->HaveSaplingIncomingViewingKey(addr)) { - if (fIgnoreExistingKey) { - return NullUniValue; - } - } else { - pwalletMain->MarkDirty(); + auto addr = boost::get(address); + auto ivk = boost::get(viewingkey); - if (!pwalletMain->AddSaplingIncomingViewingKey(ivk, addr)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding viewing key to wallet"); - } + if (pwalletMain->HaveSaplingIncomingViewingKey(addr)) { + if (fIgnoreExistingKey) { + return NullUniValue; } } else { - auto vkey = boost::get(viewingkey); - auto addr = vkey.address(); - if (pwalletMain->HaveSproutSpendingKey(addr)) { - throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this viewing key"); - } - - // Don't throw error in case a viewing key is already there - if (pwalletMain->HaveSproutViewingKey(addr)) { - if (fIgnoreExistingKey) { - return NullUniValue; - } - } else { - pwalletMain->MarkDirty(); + pwalletMain->MarkDirty(); - if (!pwalletMain->AddSproutViewingKey(vkey)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding viewing key to wallet"); - } + if (!pwalletMain->AddSaplingIncomingViewingKey(ivk, addr)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding viewing key to wallet"); } } @@ -977,26 +956,12 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPubKey& m throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr"); } - if (boost::get(&address) == nullptr) { - auto addr = boost::get(address); - libzcash::SaplingIncomingViewingKey ivk; - if(!pwalletMain->GetSaplingIncomingViewingKey(addr, ivk)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold viewing key for this zaddr"); - } - return EncodeViewingKey(ivk); + auto addr = boost::get(address); + libzcash::SaplingIncomingViewingKey ivk; + if(!pwalletMain->GetSaplingIncomingViewingKey(addr, ivk)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold viewing key for this zaddr"); } - - auto addr = boost::get(address); - libzcash::SproutViewingKey vk; - if (!pwalletMain->GetSproutViewingKey(addr, vk)) { - libzcash::SproutSpendingKey k; - if (!pwalletMain->GetSproutSpendingKey(addr, k)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private key or viewing key for this zaddr"); - } - vk = k.viewing_key(); - } - - return EncodeViewingKey(vk); + return EncodeViewingKey(ivk); } extern int32_t KOMODO_NSPV; From 52e373967199152a6e2e60d090f919d1e831d54b Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 3 Jun 2020 21:59:49 -0400 Subject: [PATCH 40/98] desprout --- src/rpc/misc.cpp | 8 +- src/test/rpc_wallet_tests.cpp | 4 +- src/wallet/gtest/test_wallet_zkeys.cpp | 297 ------------------------- src/wallet/rpcdisclosure.cpp | 7 +- 4 files changed, 13 insertions(+), 303 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index a0248c2de..fb3e21137 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -537,14 +537,14 @@ UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk { if (fHelp || params.size() != 1) throw runtime_error( - "validateaddress \"komodoaddress\"\n" - "\nReturn information about the given Komodo address.\n" + "validateaddress \"hushaddress\"\n" + "\nReturn information about the given Hush address.\n" "\nArguments:\n" - "1. \"komodoaddress\" (string, required) The Komodo address to validate\n" + "1. \"hushaddress\" (string, required) The Hush address to validate\n" "\nResult:\n" "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" - " \"address\" : \"komodoaddress\", (string) The Komodo address validated\n" + " \"address\" : \"hushaddress\", (string) The Hush address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" " \"ismine\" : true|false, (boolean) If the address is yours or not\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index f68bf8b79..107188779 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -465,7 +465,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) file << std::flush; // wallet should currently be empty - std::set addrs; + std::set addrs; pwalletMain->GetSaplingPaymentAddresses(addrs); BOOST_CHECK(addrs.size()==0); @@ -477,11 +477,13 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet) BOOST_CHECK(addrs.size()==1); // check that we have the spending key for the address + /* auto address = DecodePaymentAddress(testAddr); BOOST_CHECK(IsValidPaymentAddress(address)); BOOST_ASSERT(boost::get(&address) != nullptr); auto addr = boost::get(address); BOOST_CHECK(pwalletMain->HaveSproutSpendingKey(addr)); + */ // Verify the spending key is the same as the test data diff --git a/src/wallet/gtest/test_wallet_zkeys.cpp b/src/wallet/gtest/test_wallet_zkeys.cpp index 365533b6c..7811c9c8a 100644 --- a/src/wallet/gtest/test_wallet_zkeys.cpp +++ b/src/wallet/gtest/test_wallet_zkeys.cpp @@ -106,303 +106,6 @@ TEST(wallet_zkeys_tests, StoreAndLoadSaplingZkeys) { EXPECT_TRUE(wallet.HaveSaplingIncomingViewingKey(dpa2)); } -/** - * This test covers methods on CWallet - * GenerateNewSproutZKey() - * AddSproutZKey() - * LoadZKey() - * LoadZKeyMetadata() - */ -TEST(wallet_zkeys_tests, store_and_load_zkeys) { - SelectParams(CBaseChainParams::MAIN); - - CWallet wallet; - - // wallet should be empty - std::set addrs; - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(0, addrs.size()); - - // wallet should have one key - auto addr = wallet.GenerateNewSproutZKey(); - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(1, addrs.size()); - - // verify wallet has spending key for the address - ASSERT_TRUE(wallet.HaveSproutSpendingKey(addr)); - - // manually add new spending key to wallet - auto sk = libzcash::SproutSpendingKey::random(); - ASSERT_TRUE(wallet.AddSproutZKey(sk)); - - // verify wallet did add it - addr = sk.address(); - ASSERT_TRUE(wallet.HaveSproutSpendingKey(addr)); - - // verify spending key stored correctly - libzcash::SproutSpendingKey keyOut; - wallet.GetSproutSpendingKey(addr, keyOut); - ASSERT_EQ(sk, keyOut); - - // verify there are two keys - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(2, addrs.size()); - ASSERT_EQ(1, addrs.count(addr)); - - // Load a third key into the wallet - sk = libzcash::SproutSpendingKey::random(); - ASSERT_TRUE(wallet.LoadZKey(sk)); - - // attach metadata to this third key - addr = sk.address(); - int64_t now = GetTime(); - CKeyMetadata meta(now); - ASSERT_TRUE(wallet.LoadZKeyMetadata(addr, meta)); - - // check metadata is the same - CKeyMetadata m= wallet.mapSproutZKeyMetadata[addr]; - ASSERT_EQ(m.nCreateTime, now); -} - -/** - * This test covers methods on CWallet - * AddSproutViewingKey() - * RemoveSproutViewingKey() - * LoadSproutViewingKey() - */ -TEST(wallet_zkeys_tests, StoreAndLoadViewingKeys) { - SelectParams(CBaseChainParams::MAIN); - - CWallet wallet; - - // wallet should be empty - std::set addrs; - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(0, addrs.size()); - - // manually add new viewing key to wallet - auto sk = libzcash::SproutSpendingKey::random(); - auto vk = sk.viewing_key(); - ASSERT_TRUE(wallet.AddSproutViewingKey(vk)); - - // verify wallet did add it - auto addr = sk.address(); - ASSERT_TRUE(wallet.HaveSproutViewingKey(addr)); - // and that we don't have the corresponding spending key - ASSERT_FALSE(wallet.HaveSproutSpendingKey(addr)); - - // verify viewing key stored correctly - libzcash::SproutViewingKey vkOut; - wallet.GetSproutViewingKey(addr, vkOut); - ASSERT_EQ(vk, vkOut); - - // Load a second viewing key into the wallet - auto sk2 = libzcash::SproutSpendingKey::random(); - ASSERT_TRUE(wallet.LoadSproutViewingKey(sk2.viewing_key())); - - // verify wallet did add it - auto addr2 = sk2.address(); - ASSERT_TRUE(wallet.HaveSproutViewingKey(addr2)); - ASSERT_FALSE(wallet.HaveSproutSpendingKey(addr2)); - - // Remove the first viewing key - ASSERT_TRUE(wallet.RemoveSproutViewingKey(vk)); - ASSERT_FALSE(wallet.HaveSproutViewingKey(addr)); - ASSERT_TRUE(wallet.HaveSproutViewingKey(addr2)); -} - -/** - * This test covers methods on CWalletDB - * WriteZKey() - */ -TEST(wallet_zkeys_tests, write_zkey_direct_to_db) { - SelectParams(CBaseChainParams::TESTNET); - - // Get temporary and unique path for file. - // Note: / operator to append paths - boost::filesystem::path pathTemp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); - boost::filesystem::create_directories(pathTemp); - mapArgs["-datadir"] = pathTemp.string(); - - bool fFirstRun; - CWallet wallet("wallet.dat"); - ASSERT_EQ(DB_LOAD_OK, wallet.LoadWallet(fFirstRun)); - - // No default CPubKey set - ASSERT_TRUE(fFirstRun); - - // wallet should be empty - std::set addrs; - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(0, addrs.size()); - - // Add random key to the wallet - auto paymentAddress = wallet.GenerateNewSproutZKey(); - - // wallet should have one key - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(1, addrs.size()); - - // create random key and add it to database directly, bypassing wallet - auto sk = libzcash::SproutSpendingKey::random(); - auto addr = sk.address(); - int64_t now = GetTime(); - CKeyMetadata meta(now); - CWalletDB db("wallet.dat"); - db.WriteZKey(addr, sk, meta); - - // wallet should not be aware of key - ASSERT_FALSE(wallet.HaveSproutSpendingKey(addr)); - - // wallet sees one key - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(1, addrs.size()); - - // wallet should have default metadata for addr with null createtime - CKeyMetadata m = wallet.mapSproutZKeyMetadata[addr]; - ASSERT_EQ(m.nCreateTime, 0); - ASSERT_NE(m.nCreateTime, now); - - // load the wallet again - ASSERT_EQ(DB_LOAD_OK, wallet.LoadWallet(fFirstRun)); - - // wallet can now see the spending key - ASSERT_TRUE(wallet.HaveSproutSpendingKey(addr)); - - // check key is the same - libzcash::SproutSpendingKey keyOut; - wallet.GetSproutSpendingKey(addr, keyOut); - ASSERT_EQ(sk, keyOut); - - // wallet should have two keys - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(2, addrs.size()); - - // check metadata is now the same - m = wallet.mapSproutZKeyMetadata[addr]; - ASSERT_EQ(m.nCreateTime, now); -} - -/** - * This test covers methods on CWalletDB - * WriteSproutViewingKey() - */ -TEST(wallet_zkeys_tests, WriteViewingKeyDirectToDB) { - SelectParams(CBaseChainParams::TESTNET); - - // Get temporary and unique path for file. - // Note: / operator to append paths - boost::filesystem::path pathTemp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); - boost::filesystem::create_directories(pathTemp); - mapArgs["-datadir"] = pathTemp.string(); - - bool fFirstRun; - CWallet wallet("wallet-vkey.dat"); - ASSERT_EQ(DB_LOAD_OK, wallet.LoadWallet(fFirstRun)); - - // No default CPubKey set - ASSERT_TRUE(fFirstRun); - - // create random viewing key and add it to database directly, bypassing wallet - auto sk = libzcash::SproutSpendingKey::random(); - auto vk = sk.viewing_key(); - auto addr = sk.address(); - int64_t now = GetTime(); - CKeyMetadata meta(now); - CWalletDB db("wallet-vkey.dat"); - db.WriteSproutViewingKey(vk); - - // wallet should not be aware of viewing key - ASSERT_FALSE(wallet.HaveSproutViewingKey(addr)); - - // load the wallet again - ASSERT_EQ(DB_LOAD_OK, wallet.LoadWallet(fFirstRun)); - - // wallet can now see the viewing key - ASSERT_TRUE(wallet.HaveSproutViewingKey(addr)); - - // check key is the same - libzcash::SproutViewingKey vkOut; - wallet.GetSproutViewingKey(addr, vkOut); - ASSERT_EQ(vk, vkOut); -} - - - -/** - * This test covers methods on CWalletDB to load/save crypted z keys. - */ -TEST(wallet_zkeys_tests, write_cryptedzkey_direct_to_db) { - SelectParams(CBaseChainParams::TESTNET); - - // Get temporary and unique path for file. - // Note: / operator to append paths - boost::filesystem::path pathTemp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); - boost::filesystem::create_directories(pathTemp); - mapArgs["-datadir"] = pathTemp.string(); - - bool fFirstRun; - CWallet wallet("wallet_crypted.dat"); - ASSERT_EQ(DB_LOAD_OK, wallet.LoadWallet(fFirstRun)); - - // No default CPubKey set - ASSERT_TRUE(fFirstRun); - - // wallet should be empty - std::set addrs; - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(0, addrs.size()); - - // Add random key to the wallet - auto paymentAddress = wallet.GenerateNewSproutZKey(); - - // wallet should have one key - wallet.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(1, addrs.size()); - - // encrypt wallet - SecureString strWalletPass; - strWalletPass.reserve(100); - strWalletPass = "hello"; - ASSERT_TRUE(wallet.EncryptWallet(strWalletPass)); - - // adding a new key will fail as the wallet is locked - EXPECT_ANY_THROW(wallet.GenerateNewSproutZKey()); - - // unlock wallet and then add - wallet.Unlock(strWalletPass); - auto paymentAddress2 = wallet.GenerateNewSproutZKey(); - - // Create a new wallet from the existing wallet path - CWallet wallet2("wallet_crypted.dat"); - ASSERT_EQ(DB_LOAD_OK, wallet2.LoadWallet(fFirstRun)); - - // Confirm it's not the same as the other wallet - ASSERT_TRUE(&wallet != &wallet2); - - // wallet should have two keys - wallet2.GetSproutPaymentAddresses(addrs); - ASSERT_EQ(2, addrs.size()); - - // check we have entries for our payment addresses - ASSERT_TRUE(addrs.count(paymentAddress)); - ASSERT_TRUE(addrs.count(paymentAddress2)); - - // spending key is crypted, so we can't extract valid payment address - libzcash::SproutSpendingKey keyOut; - wallet2.GetSproutSpendingKey(paymentAddress, keyOut); - ASSERT_FALSE(paymentAddress == keyOut.address()); - - // unlock wallet to get spending keys and verify payment addresses - wallet2.Unlock(strWalletPass); - - wallet2.GetSproutSpendingKey(paymentAddress, keyOut); - ASSERT_EQ(paymentAddress, keyOut.address()); - - wallet2.GetSproutSpendingKey(paymentAddress2, keyOut); - ASSERT_EQ(paymentAddress2, keyOut.address()); -} - /** * This test covers methods on CWalletDB to load/save crypted sapling z keys. */ diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp index cd0cc42a6..918e70cbc 100644 --- a/src/wallet/rpcdisclosure.cpp +++ b/src/wallet/rpcdisclosure.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2017 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -187,6 +188,8 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const C throw JSONRPCError(RPC_WALLET_ERROR, "Error: payment disclosure is disabled."); } + throw JSONRPCError(RPC_WALLET_ERROR, "Error: payment disclosures not implemented for Sapling yet"); + LOCK2(cs_main, pwalletMain->cs_wallet); EnsureWalletIsUnlocked(); @@ -269,8 +272,9 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const C errs.push_back("Payment disclosure signature does not match transaction signature"); } + /* // Check the payment address is valid - SproutPaymentAddress zaddr = pd.payload.zaddr; + PaymentAddress zaddr = pd.payload.zaddr; { o.push_back(Pair("paymentAddress", EncodePaymentAddress(zaddr))); @@ -308,6 +312,7 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const C errs.push_back(string("Error while decrypting payment disclosure note: ") + string(e.what()) ); } } + */ bool isValid = errs.empty(); o.push_back(Pair("valid", isValid)); From 7c6c7150c61e2183bc0af5449b18d8a48266f266 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 3 Jun 2020 22:20:10 -0400 Subject: [PATCH 41/98] desprout --- src/coins.cpp | 27 ----- src/primitives/transaction.cpp | 77 -------------- src/primitives/transaction.h | 177 --------------------------------- src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.h | 5 - src/wallet/walletdb.cpp | 4 + src/wallet/walletdb.h | 10 +- 7 files changed, 6 insertions(+), 296 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 38fac8252..f183c99a0 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -628,33 +628,6 @@ bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const { boost::unordered_map intermediates; - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) - { - BOOST_FOREACH(const uint256& nullifier, joinsplit.nullifiers) - { - if (GetNullifier(nullifier, SPROUT)) { - // If the nullifier is set, this transaction - // double-spends! - return false; - } - } - - SproutMerkleTree tree; - auto it = intermediates.find(joinsplit.anchor); - if (it != intermediates.end()) { - tree = it->second; - } else if (!GetSproutAnchorAt(joinsplit.anchor, tree)) { - return false; - } - - BOOST_FOREACH(const uint256& commitment, joinsplit.commitments) - { - tree.append(commitment); - } - - intermediates.insert(std::make_pair(tree.root(), tree)); - } - for (const SpendDescription &spendDescription : tx.vShieldedSpend) { if (GetNullifier(spendDescription.nullifier, SAPLING)) { // Prevent double spends LogPrintf("%s: sapling nullifier %s exists, preventing double spend\n", __FUNCTION__, spendDescription.nullifier.GetHex().c_str()); diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 2cde04f2c..01c95adc3 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -26,83 +26,6 @@ #include "librustzcash.h" -JSDescription::JSDescription( - ZCJoinSplit& params, - const uint256& joinSplitPubKey, - const uint256& anchor, - const std::array& inputs, - const std::array& outputs, - CAmount vpub_old, - CAmount vpub_new, - bool computeProof, - uint256 *esk // payment disclosure -) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor) -{ - std::array notes; - - proof = params.prove( - inputs, - outputs, - notes, - ciphertexts, - ephemeralKey, - joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new, - anchor, - computeProof, - esk // payment disclosure - ); -} - -JSDescription JSDescription::Randomized( - ZCJoinSplit& params, - const uint256& joinSplitPubKey, - const uint256& anchor, - std::array& inputs, - std::array& outputs, - std::array& inputMap, - std::array& outputMap, - CAmount vpub_old, - CAmount vpub_new, - bool computeProof, - uint256 *esk, // payment disclosure - std::function gen -) -{ - // Randomize the order of the inputs and outputs - inputMap = {0, 1}; - outputMap = {0, 1}; - - assert(gen); - - MappedShuffle(inputs.begin(), inputMap.begin(), ZC_NUM_JS_INPUTS, gen); - MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, gen); - - return JSDescription( - params, joinSplitPubKey, anchor, inputs, outputs, - vpub_old, vpub_new, computeProof, - esk // payment disclosure - ); -} - -bool JSDescription::Verify( - ZCJoinSplit& params, - libzcash::ProofVerifier& verifier, - const uint256& joinSplitPubKey -) const { - return false; -} - -uint256 JSDescription::h_sig(ZCJoinSplit& params, const uint256& joinSplitPubKey) const -{ - return params.h_sig(randomSeed, nullifiers, joinSplitPubKey); -} - std::string COutPoint::ToString() const { return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n); diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 2ece7b255..b3afecd87 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -159,183 +159,6 @@ public: } }; -template -class SproutProofSerializer : public boost::static_visitor<> -{ - Stream& s; - bool useGroth; - -public: - SproutProofSerializer(Stream& s, bool useGroth) : s(s), useGroth(useGroth) {} - - void operator()(const libzcash::PHGRProof& proof) const - { - if (useGroth) { - throw std::ios_base::failure("Invalid Sprout proof for transaction format (expected GrothProof, found PHGRProof)"); - } - ::Serialize(s, proof); - } - - void operator()(const libzcash::GrothProof& proof) const - { - if (!useGroth) { - throw std::ios_base::failure("Invalid Sprout proof for transaction format (expected PHGRProof, found GrothProof)"); - } - ::Serialize(s, proof); - } -}; - -template -inline void SerReadWriteSproutProof(Stream& s, const T& proof, bool useGroth, CSerActionSerialize ser_action) -{ - auto ps = SproutProofSerializer(s, useGroth); - boost::apply_visitor(ps, proof); -} - -template -inline void SerReadWriteSproutProof(Stream& s, T& proof, bool useGroth, CSerActionUnserialize ser_action) -{ - if (useGroth) { - libzcash::GrothProof grothProof; - ::Unserialize(s, grothProof); - proof = grothProof; - } else { - libzcash::PHGRProof pghrProof; - ::Unserialize(s, pghrProof); - proof = pghrProof; - } -} - -class JSDescription -{ -public: - // These values 'enter from' and 'exit to' the value - // pool, respectively. - CAmount vpub_old; - CAmount vpub_new; - - // JoinSplits are always anchored to a root in the note - // commitment tree at some point in the blockchain - // history or in the history of the current - // transaction. - uint256 anchor; - - // Nullifiers are used to prevent double-spends. They - // are derived from the secrets placed in the note - // and the secret spend-authority key known by the - // spender. - std::array nullifiers; - - // Note commitments are introduced into the commitment - // tree, blinding the public about the values and - // destinations involved in the JoinSplit. The presence of - // a commitment in the note commitment tree is required - // to spend it. - std::array commitments; - - // Ephemeral key - uint256 ephemeralKey; - - // Ciphertexts - // These contain trapdoors, values and other information - // that the recipient needs, including a memo field. It - // is encrypted using the scheme implemented in crypto/NoteEncryption.cpp - std::array ciphertexts = {{ {{0}} }}; - - // Random seed - uint256 randomSeed; - - // MACs - // The verification of the JoinSplit requires these MACs - // to be provided as an input. - std::array macs; - - // JoinSplit proof - // This is a zk-SNARK which ensures that this JoinSplit is valid. - libzcash::SproutProof proof; - - JSDescription(): vpub_old(0), vpub_new(0) { } - - JSDescription( - ZCJoinSplit& params, - const uint256& joinSplitPubKey, - const uint256& rt, - const std::array& inputs, - const std::array& outputs, - CAmount vpub_old, - CAmount vpub_new, - bool computeProof = true, // Set to false in some tests - uint256 *esk = nullptr // payment disclosure - ); - - static JSDescription Randomized( - ZCJoinSplit& params, - const uint256& joinSplitPubKey, - const uint256& rt, - std::array& inputs, - std::array& outputs, - std::array& inputMap, - std::array& outputMap, - CAmount vpub_old, - CAmount vpub_new, - bool computeProof = true, // Set to false in some tests - uint256 *esk = nullptr, // payment disclosure - std::function gen = GetRandInt - ); - - // Verifies that the JoinSplit proof is correct. - bool Verify( - ZCJoinSplit& params, - libzcash::ProofVerifier& verifier, - const uint256& joinSplitPubKey - ) const; - - // Returns the calculated h_sig - uint256 h_sig(ZCJoinSplit& params, const uint256& joinSplitPubKey) const; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - // nVersion is set by CTransaction and CMutableTransaction to - // (tx.fOverwintered << 31) | tx.nVersion - bool fOverwintered = s.GetVersion() >> 31; - int32_t txVersion = s.GetVersion() & 0x7FFFFFFF; - bool useGroth = fOverwintered && txVersion >= SAPLING_TX_VERSION; - - READWRITE(vpub_old); - READWRITE(vpub_new); - READWRITE(anchor); - READWRITE(nullifiers); - READWRITE(commitments); - READWRITE(ephemeralKey); - READWRITE(randomSeed); - READWRITE(macs); - ::SerReadWriteSproutProof(s, proof, useGroth, ser_action); - READWRITE(ciphertexts); - } - - friend bool operator==(const JSDescription& a, const JSDescription& b) - { - return ( - a.vpub_old == b.vpub_old && - a.vpub_new == b.vpub_new && - a.anchor == b.anchor && - a.nullifiers == b.nullifiers && - a.commitments == b.commitments && - a.ephemeralKey == b.ephemeralKey && - a.ciphertexts == b.ciphertexts && - a.randomSeed == b.randomSeed && - a.macs == b.macs && - a.proof == b.proof - ); - } - - friend bool operator!=(const JSDescription& a, const JSDescription& b) - { - return !(a == b); - } -}; class BaseOutPoint { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 37f67042b..604e21799 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4268,7 +4268,7 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& my "\nResult:\n" "{\n" " \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n" - " \"private\": xxxxx, (numeric) the total balance of private funds (in both Sprout and Sapling addresses)\n" + " \"private\": xxxxx, (numeric) the total balance of private funds (in Sapling addresses)\n" " \"total\": xxxxx, (numeric) the total balance of both transparent and private funds\n" "}\n" "\nExamples:\n" diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d82e100ed..f3526c583 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1408,7 +1408,6 @@ private: public: PaymentAddressBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {} - bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1421,7 +1420,6 @@ private: public: IncomingViewingKeyBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {} - bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1433,7 +1431,6 @@ private: public: HaveSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} - bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1445,7 +1442,6 @@ private: public: GetSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} - boost::optional operator()(const libzcash::SproutPaymentAddress &zaddr) const; boost::optional operator()(const libzcash::SaplingPaymentAddress &zaddr) const; boost::optional operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1517,7 +1513,6 @@ public: ) : m_wallet(wallet), params(params), nTime(_nTime), hdKeypath(_hdKeypath), seedFpStr(_seedFp), log(_log) {} - SpendingKeyAddResult operator()(const libzcash::SproutSpendingKey &sk) const; SpendingKeyAddResult operator()(const libzcash::SaplingExtendedSpendingKey &sk) const; SpendingKeyAddResult operator()(const libzcash::InvalidEncoding& no) const; }; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 1177bbedd..4f6942bb7 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -653,6 +653,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "czkey") { + /* libzcash::SproutPaymentAddress addr; ssKey >> addr; // Deserialization of a pair is just one item after another @@ -662,6 +663,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, vector vchCryptedSecret; ssValue >> vchCryptedSecret; wss.nCKeys++; + */ //if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret)) //{ @@ -704,11 +706,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "zkeymeta") { + /* libzcash::SproutPaymentAddress addr; ssKey >> addr; CKeyMetadata keyMeta; ssValue >> keyMeta; wss.nZKeyMeta++; + */ // pwallet->LoadZKeyMetadata(addr, keyMeta); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 9069e3a08..8c34588ec 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -199,23 +200,14 @@ public: bool WriteHDChain(const CHDChain& chain); /// Write spending key to wallet database, where key is payment address and value is spending key. - bool WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta); bool WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk, const libzcash::SaplingExtendedSpendingKey &key, const CKeyMetadata &keyMeta); bool WriteSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr, const libzcash::SaplingIncomingViewingKey &ivk); - bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr, - const libzcash::ReceivingKey & rk, - const std::vector& vchCryptedSecret, - const CKeyMetadata &keyMeta); bool WriteCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector& vchCryptedSecret, const CKeyMetadata &keyMeta); - - bool WriteSproutViewingKey(const libzcash::SproutViewingKey &vk); - bool EraseSproutViewingKey(const libzcash::SproutViewingKey &vk); - private: CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); From b32bf1f82c0c4ded804b2b0f009f339677b7a931 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 4 Jun 2020 21:51:21 -0400 Subject: [PATCH 42/98] Revert "desprout" This reverts commit 7c6c7150c61e2183bc0af5449b18d8a48266f266. --- src/coins.cpp | 27 +++++ src/primitives/transaction.cpp | 77 ++++++++++++++ src/primitives/transaction.h | 177 +++++++++++++++++++++++++++++++++ src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.h | 5 + src/wallet/walletdb.cpp | 4 - src/wallet/walletdb.h | 10 +- 7 files changed, 296 insertions(+), 6 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index f183c99a0..38fac8252 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -628,6 +628,33 @@ bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const { boost::unordered_map intermediates; + BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) + { + BOOST_FOREACH(const uint256& nullifier, joinsplit.nullifiers) + { + if (GetNullifier(nullifier, SPROUT)) { + // If the nullifier is set, this transaction + // double-spends! + return false; + } + } + + SproutMerkleTree tree; + auto it = intermediates.find(joinsplit.anchor); + if (it != intermediates.end()) { + tree = it->second; + } else if (!GetSproutAnchorAt(joinsplit.anchor, tree)) { + return false; + } + + BOOST_FOREACH(const uint256& commitment, joinsplit.commitments) + { + tree.append(commitment); + } + + intermediates.insert(std::make_pair(tree.root(), tree)); + } + for (const SpendDescription &spendDescription : tx.vShieldedSpend) { if (GetNullifier(spendDescription.nullifier, SAPLING)) { // Prevent double spends LogPrintf("%s: sapling nullifier %s exists, preventing double spend\n", __FUNCTION__, spendDescription.nullifier.GetHex().c_str()); diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 01c95adc3..2cde04f2c 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -26,6 +26,83 @@ #include "librustzcash.h" +JSDescription::JSDescription( + ZCJoinSplit& params, + const uint256& joinSplitPubKey, + const uint256& anchor, + const std::array& inputs, + const std::array& outputs, + CAmount vpub_old, + CAmount vpub_new, + bool computeProof, + uint256 *esk // payment disclosure +) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor) +{ + std::array notes; + + proof = params.prove( + inputs, + outputs, + notes, + ciphertexts, + ephemeralKey, + joinSplitPubKey, + randomSeed, + macs, + nullifiers, + commitments, + vpub_old, + vpub_new, + anchor, + computeProof, + esk // payment disclosure + ); +} + +JSDescription JSDescription::Randomized( + ZCJoinSplit& params, + const uint256& joinSplitPubKey, + const uint256& anchor, + std::array& inputs, + std::array& outputs, + std::array& inputMap, + std::array& outputMap, + CAmount vpub_old, + CAmount vpub_new, + bool computeProof, + uint256 *esk, // payment disclosure + std::function gen +) +{ + // Randomize the order of the inputs and outputs + inputMap = {0, 1}; + outputMap = {0, 1}; + + assert(gen); + + MappedShuffle(inputs.begin(), inputMap.begin(), ZC_NUM_JS_INPUTS, gen); + MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, gen); + + return JSDescription( + params, joinSplitPubKey, anchor, inputs, outputs, + vpub_old, vpub_new, computeProof, + esk // payment disclosure + ); +} + +bool JSDescription::Verify( + ZCJoinSplit& params, + libzcash::ProofVerifier& verifier, + const uint256& joinSplitPubKey +) const { + return false; +} + +uint256 JSDescription::h_sig(ZCJoinSplit& params, const uint256& joinSplitPubKey) const +{ + return params.h_sig(randomSeed, nullifiers, joinSplitPubKey); +} + std::string COutPoint::ToString() const { return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n); diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index b3afecd87..2ece7b255 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -159,6 +159,183 @@ public: } }; +template +class SproutProofSerializer : public boost::static_visitor<> +{ + Stream& s; + bool useGroth; + +public: + SproutProofSerializer(Stream& s, bool useGroth) : s(s), useGroth(useGroth) {} + + void operator()(const libzcash::PHGRProof& proof) const + { + if (useGroth) { + throw std::ios_base::failure("Invalid Sprout proof for transaction format (expected GrothProof, found PHGRProof)"); + } + ::Serialize(s, proof); + } + + void operator()(const libzcash::GrothProof& proof) const + { + if (!useGroth) { + throw std::ios_base::failure("Invalid Sprout proof for transaction format (expected PHGRProof, found GrothProof)"); + } + ::Serialize(s, proof); + } +}; + +template +inline void SerReadWriteSproutProof(Stream& s, const T& proof, bool useGroth, CSerActionSerialize ser_action) +{ + auto ps = SproutProofSerializer(s, useGroth); + boost::apply_visitor(ps, proof); +} + +template +inline void SerReadWriteSproutProof(Stream& s, T& proof, bool useGroth, CSerActionUnserialize ser_action) +{ + if (useGroth) { + libzcash::GrothProof grothProof; + ::Unserialize(s, grothProof); + proof = grothProof; + } else { + libzcash::PHGRProof pghrProof; + ::Unserialize(s, pghrProof); + proof = pghrProof; + } +} + +class JSDescription +{ +public: + // These values 'enter from' and 'exit to' the value + // pool, respectively. + CAmount vpub_old; + CAmount vpub_new; + + // JoinSplits are always anchored to a root in the note + // commitment tree at some point in the blockchain + // history or in the history of the current + // transaction. + uint256 anchor; + + // Nullifiers are used to prevent double-spends. They + // are derived from the secrets placed in the note + // and the secret spend-authority key known by the + // spender. + std::array nullifiers; + + // Note commitments are introduced into the commitment + // tree, blinding the public about the values and + // destinations involved in the JoinSplit. The presence of + // a commitment in the note commitment tree is required + // to spend it. + std::array commitments; + + // Ephemeral key + uint256 ephemeralKey; + + // Ciphertexts + // These contain trapdoors, values and other information + // that the recipient needs, including a memo field. It + // is encrypted using the scheme implemented in crypto/NoteEncryption.cpp + std::array ciphertexts = {{ {{0}} }}; + + // Random seed + uint256 randomSeed; + + // MACs + // The verification of the JoinSplit requires these MACs + // to be provided as an input. + std::array macs; + + // JoinSplit proof + // This is a zk-SNARK which ensures that this JoinSplit is valid. + libzcash::SproutProof proof; + + JSDescription(): vpub_old(0), vpub_new(0) { } + + JSDescription( + ZCJoinSplit& params, + const uint256& joinSplitPubKey, + const uint256& rt, + const std::array& inputs, + const std::array& outputs, + CAmount vpub_old, + CAmount vpub_new, + bool computeProof = true, // Set to false in some tests + uint256 *esk = nullptr // payment disclosure + ); + + static JSDescription Randomized( + ZCJoinSplit& params, + const uint256& joinSplitPubKey, + const uint256& rt, + std::array& inputs, + std::array& outputs, + std::array& inputMap, + std::array& outputMap, + CAmount vpub_old, + CAmount vpub_new, + bool computeProof = true, // Set to false in some tests + uint256 *esk = nullptr, // payment disclosure + std::function gen = GetRandInt + ); + + // Verifies that the JoinSplit proof is correct. + bool Verify( + ZCJoinSplit& params, + libzcash::ProofVerifier& verifier, + const uint256& joinSplitPubKey + ) const; + + // Returns the calculated h_sig + uint256 h_sig(ZCJoinSplit& params, const uint256& joinSplitPubKey) const; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + // nVersion is set by CTransaction and CMutableTransaction to + // (tx.fOverwintered << 31) | tx.nVersion + bool fOverwintered = s.GetVersion() >> 31; + int32_t txVersion = s.GetVersion() & 0x7FFFFFFF; + bool useGroth = fOverwintered && txVersion >= SAPLING_TX_VERSION; + + READWRITE(vpub_old); + READWRITE(vpub_new); + READWRITE(anchor); + READWRITE(nullifiers); + READWRITE(commitments); + READWRITE(ephemeralKey); + READWRITE(randomSeed); + READWRITE(macs); + ::SerReadWriteSproutProof(s, proof, useGroth, ser_action); + READWRITE(ciphertexts); + } + + friend bool operator==(const JSDescription& a, const JSDescription& b) + { + return ( + a.vpub_old == b.vpub_old && + a.vpub_new == b.vpub_new && + a.anchor == b.anchor && + a.nullifiers == b.nullifiers && + a.commitments == b.commitments && + a.ephemeralKey == b.ephemeralKey && + a.ciphertexts == b.ciphertexts && + a.randomSeed == b.randomSeed && + a.macs == b.macs && + a.proof == b.proof + ); + } + + friend bool operator!=(const JSDescription& a, const JSDescription& b) + { + return !(a == b); + } +}; class BaseOutPoint { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 604e21799..37f67042b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4268,7 +4268,7 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& my "\nResult:\n" "{\n" " \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n" - " \"private\": xxxxx, (numeric) the total balance of private funds (in Sapling addresses)\n" + " \"private\": xxxxx, (numeric) the total balance of private funds (in both Sprout and Sapling addresses)\n" " \"total\": xxxxx, (numeric) the total balance of both transparent and private funds\n" "}\n" "\nExamples:\n" diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index f3526c583..d82e100ed 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1408,6 +1408,7 @@ private: public: PaymentAddressBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {} + bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1420,6 +1421,7 @@ private: public: IncomingViewingKeyBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {} + bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1431,6 +1433,7 @@ private: public: HaveSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} + bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1442,6 +1445,7 @@ private: public: GetSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} + boost::optional operator()(const libzcash::SproutPaymentAddress &zaddr) const; boost::optional operator()(const libzcash::SaplingPaymentAddress &zaddr) const; boost::optional operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1513,6 +1517,7 @@ public: ) : m_wallet(wallet), params(params), nTime(_nTime), hdKeypath(_hdKeypath), seedFpStr(_seedFp), log(_log) {} + SpendingKeyAddResult operator()(const libzcash::SproutSpendingKey &sk) const; SpendingKeyAddResult operator()(const libzcash::SaplingExtendedSpendingKey &sk) const; SpendingKeyAddResult operator()(const libzcash::InvalidEncoding& no) const; }; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 4f6942bb7..1177bbedd 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -653,7 +653,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "czkey") { - /* libzcash::SproutPaymentAddress addr; ssKey >> addr; // Deserialization of a pair is just one item after another @@ -663,7 +662,6 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, vector vchCryptedSecret; ssValue >> vchCryptedSecret; wss.nCKeys++; - */ //if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret)) //{ @@ -706,13 +704,11 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "zkeymeta") { - /* libzcash::SproutPaymentAddress addr; ssKey >> addr; CKeyMetadata keyMeta; ssValue >> keyMeta; wss.nZKeyMeta++; - */ // pwallet->LoadZKeyMetadata(addr, keyMeta); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 8c34588ec..9069e3a08 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -1,6 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers -// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -200,14 +199,23 @@ public: bool WriteHDChain(const CHDChain& chain); /// Write spending key to wallet database, where key is payment address and value is spending key. + bool WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta); bool WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk, const libzcash::SaplingExtendedSpendingKey &key, const CKeyMetadata &keyMeta); bool WriteSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr, const libzcash::SaplingIncomingViewingKey &ivk); + bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr, + const libzcash::ReceivingKey & rk, + const std::vector& vchCryptedSecret, + const CKeyMetadata &keyMeta); bool WriteCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector& vchCryptedSecret, const CKeyMetadata &keyMeta); + + bool WriteSproutViewingKey(const libzcash::SproutViewingKey &vk); + bool EraseSproutViewingKey(const libzcash::SproutViewingKey &vk); + private: CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); From da6c0028a3e497e4c00f1dc11148be9717cf7108 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 4 Jun 2020 21:51:49 -0400 Subject: [PATCH 43/98] desprout --- src/coins.cpp | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 38fac8252..c0039120a 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -626,35 +626,6 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const { - boost::unordered_map intermediates; - - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) - { - BOOST_FOREACH(const uint256& nullifier, joinsplit.nullifiers) - { - if (GetNullifier(nullifier, SPROUT)) { - // If the nullifier is set, this transaction - // double-spends! - return false; - } - } - - SproutMerkleTree tree; - auto it = intermediates.find(joinsplit.anchor); - if (it != intermediates.end()) { - tree = it->second; - } else if (!GetSproutAnchorAt(joinsplit.anchor, tree)) { - return false; - } - - BOOST_FOREACH(const uint256& commitment, joinsplit.commitments) - { - tree.append(commitment); - } - - intermediates.insert(std::make_pair(tree.root(), tree)); - } - for (const SpendDescription &spendDescription : tx.vShieldedSpend) { if (GetNullifier(spendDescription.nullifier, SAPLING)) { // Prevent double spends LogPrintf("%s: sapling nullifier %s exists, preventing double spend\n", __FUNCTION__, spendDescription.nullifier.GetHex().c_str()); From ed91f0188bba048e0b50197a23853bf14a22afd8 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 4 Jun 2020 21:56:04 -0400 Subject: [PATCH 44/98] We aint got no JoinSplits around here --- src/coins.cpp | 2 +- src/coins.h | 2 +- src/main.cpp | 6 +++--- src/test/coins_tests.cpp | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index c0039120a..602d153ec 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -624,7 +624,7 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr } -bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const +bool CCoinsViewCache::HaveShieldedRequirements(const CTransaction& tx) const { for (const SpendDescription &spendDescription : tx.vShieldedSpend) { if (GetNullifier(spendDescription.nullifier, SAPLING)) { // Prevent double spends diff --git a/src/coins.h b/src/coins.h index cc8b19f68..1211e7e07 100644 --- a/src/coins.h +++ b/src/coins.h @@ -563,7 +563,7 @@ public: bool HaveInputs(const CTransaction& tx) const; //! Check whether all joinsplit requirements (anchors/nullifiers) are satisfied - bool HaveJoinSplitRequirements(const CTransaction& tx) const; + bool HaveShieldedRequirements(const CTransaction& tx) const; //! Return priority of tx at height nHeight double GetPriority(const CTransaction &tx, int nHeight) const; diff --git a/src/main.cpp b/src/main.cpp index c75f51a28..f31847b04 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1894,7 +1894,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } // are the joinsplit's requirements met? - if (!view.HaveJoinSplitRequirements(tx)) + if (!view.HaveShieldedRequirements(tx)) { //fprintf(stderr,"accept failure.2\n"); return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); @@ -2719,7 +2719,7 @@ namespace Consensus { return state.Invalid(error("CheckInputs(): %s inputs unavailable", tx.GetHash().ToString())); // are the JoinSplit's requirements met? - if (!inputs.HaveJoinSplitRequirements(tx)) + if (!inputs.HaveShieldedRequirements(tx)) return state.Invalid(error("CheckInputs(): %s JoinSplit requirements not met", tx.GetHash().ToString())); CAmount nValueIn = 0; @@ -3536,7 +3536,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin REJECT_INVALID, "bad-txns-inputs-missingorspent"); } // are the JoinSplit's requirements met? - if (!view.HaveJoinSplitRequirements(tx)) + if (!view.HaveShieldedRequirements(tx)) return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"), REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met"); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index dc795ad7a..bb6432a81 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -632,7 +632,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) CMutableTransaction mtx; mtx.vjoinsplit.push_back(js2); - BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx)); + BOOST_CHECK(!cache.HaveShieldedRequirements(mtx)); } { @@ -642,7 +642,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js1); - BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx)); + BOOST_CHECK(!cache.HaveShieldedRequirements(mtx)); } { @@ -650,7 +650,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js1); mtx.vjoinsplit.push_back(js2); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + BOOST_CHECK(cache.HaveShieldedRequirements(mtx)); } { @@ -659,7 +659,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js3); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + BOOST_CHECK(cache.HaveShieldedRequirements(mtx)); } { @@ -669,7 +669,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js3); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + BOOST_CHECK(cache.HaveShieldedRequirements(mtx)); } } From ed2c9450f9032833f459816c3f6f91893fc8fcbe Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 01:20:37 -0400 Subject: [PATCH 45/98] desprout --- src/Makefile.am | 2 - src/gtest/test_transaction.cpp | 90 --- src/key_io.cpp | 44 +- src/keystore.cpp | 42 +- src/keystore.h | 8 +- src/paymentdisclosure.h | 1 + src/rpc/misc.cpp | 54 +- src/test/rpc_wallet_tests.cpp | 6 +- src/utiltest.cpp | 154 ----- src/utiltest.h | 19 - src/wallet/asyncrpcoperation_shieldcoinbase.h | 2 +- src/wallet/crypter.cpp | 111 +--- src/wallet/gtest/test_wallet.cpp | 570 +----------------- src/wallet/rpcwallet.cpp | 28 - src/wallet/wallet.h | 5 - src/wallet/walletdb.cpp | 16 +- src/wallet/walletdb.h | 11 +- src/zcash/Address.cpp | 38 +- src/zcbenchmarks.cpp | 34 +- 19 files changed, 52 insertions(+), 1183 deletions(-) delete mode 100644 src/gtest/test_transaction.cpp delete mode 100644 src/utiltest.cpp delete mode 100644 src/utiltest.h diff --git a/src/Makefile.am b/src/Makefile.am index 6277e0f98..2d2d7a691 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -347,8 +347,6 @@ endif libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ - utiltest.cpp \ - utiltest.h \ zcbenchmarks.cpp \ zcbenchmarks.h \ wallet/asyncrpcoperation_mergetoaddress.cpp \ diff --git a/src/gtest/test_transaction.cpp b/src/gtest/test_transaction.cpp deleted file mode 100644 index 1350768ff..000000000 --- a/src/gtest/test_transaction.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include - -#include "primitives/transaction.h" -#include "zcash/Note.hpp" -#include "zcash/Address.hpp" - -#include - -extern ZCJoinSplit* params; -extern int GenZero(int n); -extern int GenMax(int n); - -TEST(Transaction, JSDescriptionRandomized) { - // construct a merkle tree - SproutMerkleTree merkleTree; - - libzcash::SproutSpendingKey k = libzcash::SproutSpendingKey::random(); - libzcash::SproutPaymentAddress addr = k.address(); - - libzcash::SproutNote note(addr.a_pk, 100, uint256(), uint256()); - - // commitment from coin - uint256 commitment = note.cm(); - - // insert commitment into the merkle tree - merkleTree.append(commitment); - - // compute the merkle root we will be working with - uint256 rt = merkleTree.root(); - - auto witness = merkleTree.witness(); - - // create JSDescription - uint256 joinSplitPubKey; - std::array inputs = { - libzcash::JSInput(witness, note, k), - libzcash::JSInput() // dummy input of zero value - }; - std::array outputs = { - libzcash::JSOutput(addr, 50), - libzcash::JSOutput(addr, 50) - }; - std::array inputMap; - std::array outputMap; - - { - auto jsdesc = JSDescription::Randomized( - false, - *params, joinSplitPubKey, rt, - inputs, outputs, - inputMap, outputMap, - 0, 0, false); - - std::set inputSet(inputMap.begin(), inputMap.end()); - std::set expectedInputSet {0, 1}; - EXPECT_EQ(expectedInputSet, inputSet); - - std::set outputSet(outputMap.begin(), outputMap.end()); - std::set expectedOutputSet {0, 1}; - EXPECT_EQ(expectedOutputSet, outputSet); - } - - { - auto jsdesc = JSDescription::Randomized( - false, - *params, joinSplitPubKey, rt, - inputs, outputs, - inputMap, outputMap, - 0, 0, false, nullptr, GenZero); - - std::array expectedInputMap {1, 0}; - std::array expectedOutputMap {1, 0}; - EXPECT_EQ(expectedInputMap, inputMap); - EXPECT_EQ(expectedOutputMap, outputMap); - } - - { - auto jsdesc = JSDescription::Randomized( - false, - *params, joinSplitPubKey, rt, - inputs, outputs, - inputMap, outputMap, - 0, 0, false, nullptr, GenMax); - - std::array expectedInputMap {0, 1}; - std::array expectedOutputMap {0, 1}; - EXPECT_EQ(expectedInputMap, inputMap); - EXPECT_EQ(expectedOutputMap, outputMap); - } -} diff --git a/src/key_io.cpp b/src/key_io.cpp index dd4176fee..dd4bf884c 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2014-2016 The Bitcoin Core developers // Copyright (c) 2016-2018 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -84,15 +85,6 @@ private: public: PaymentAddressEncoder(const CChainParams& params) : m_params(params) {} - std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const - { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << zaddr; - std::vector data = m_params.Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS); - data.insert(data.end(), ss.begin(), ss.end()); - return EncodeBase58Check(data); - } - std::string operator()(const libzcash::SaplingPaymentAddress& zaddr) const { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -117,17 +109,6 @@ private: public: ViewingKeyEncoder(const CChainParams& params) : m_params(params) {} - std::string operator()(const libzcash::SproutViewingKey& vk) const - { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << vk; - std::vector data = m_params.Base58Prefix(CChainParams::ZCVIEWING_KEY); - data.insert(data.end(), ss.begin(), ss.end()); - std::string ret = EncodeBase58Check(data); - memory_cleanse(data.data(), data.size()); - return ret; - } - std::string operator()(const libzcash::SaplingIncomingViewingKey& vk) const { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -152,17 +133,6 @@ private: public: SpendingKeyEncoder(const CChainParams& params) : m_params(params) {} - std::string operator()(const libzcash::SproutSpendingKey& zkey) const - { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << zkey; - std::vector data = m_params.Base58Prefix(CChainParams::ZCSPENDING_KEY); - data.insert(data.end(), ss.begin(), ss.end()); - std::string ret = EncodeBase58Check(data); - memory_cleanse(data.data(), data.size()); - return ret; - } - std::string operator()(const libzcash::SaplingExtendedSpendingKey& zkey) const { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -324,18 +294,6 @@ std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr) libzcash::PaymentAddress DecodePaymentAddress(const std::string& str) { std::vector data; - if (DecodeBase58Check(str, data)) { - const std::vector& zaddr_prefix = Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS); - if ((data.size() == libzcash::SerializedSproutPaymentAddressSize + zaddr_prefix.size()) && - std::equal(zaddr_prefix.begin(), zaddr_prefix.end(), data.begin())) { - CSerializeData serialized(data.begin() + zaddr_prefix.size(), data.end()); - CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); - libzcash::SproutPaymentAddress ret; - ss >> ret; - return ret; - } - } - data.clear(); auto bech = bech32::Decode(str); if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) && bech.second.size() == ConvertedSaplingPaymentAddressSize) { diff --git a/src/keystore.cpp b/src/keystore.cpp index 34bab456c..ca4fa3712 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -128,15 +129,6 @@ bool CBasicKeyStore::HaveWatchOnly() const return (!setWatchOnly.empty()); } -bool CBasicKeyStore::AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk) -{ - LOCK(cs_SpendingKeyStore); - auto address = sk.address(); - mapSproutSpendingKeys[address] = sk; - mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(sk.receiving_key()))); - return true; -} - //! Sapling bool CBasicKeyStore::AddSaplingSpendingKey( const libzcash::SaplingExtendedSpendingKey &sk, @@ -155,14 +147,6 @@ bool CBasicKeyStore::AddSaplingSpendingKey( return true; } -bool CBasicKeyStore::AddSproutViewingKey(const libzcash::SproutViewingKey &vk) -{ - LOCK(cs_SpendingKeyStore); - auto address = vk.address(); - mapSproutViewingKeys[address] = vk; - mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(vk.sk_enc))); - return true; -} bool CBasicKeyStore::AddSaplingFullViewingKey( const libzcash::SaplingFullViewingKey &fvk, @@ -190,18 +174,7 @@ bool CBasicKeyStore::AddSaplingIncomingViewingKey( return true; } -bool CBasicKeyStore::RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk) -{ - LOCK(cs_SpendingKeyStore); - mapSproutViewingKeys.erase(vk.address()); - return true; -} -bool CBasicKeyStore::HaveSproutViewingKey(const libzcash::SproutPaymentAddress &address) const -{ - LOCK(cs_SpendingKeyStore); - return mapSproutViewingKeys.count(address) > 0; -} bool CBasicKeyStore::HaveSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey &ivk) const { @@ -215,19 +188,6 @@ bool CBasicKeyStore::HaveSaplingIncomingViewingKey(const libzcash::SaplingPaymen return mapSaplingIncomingViewingKeys.count(addr) > 0; } -bool CBasicKeyStore::GetSproutViewingKey( - const libzcash::SproutPaymentAddress &address, - libzcash::SproutViewingKey &vkOut) const -{ - LOCK(cs_SpendingKeyStore); - SproutViewingKeyMap::const_iterator mi = mapSproutViewingKeys.find(address); - if (mi != mapSproutViewingKeys.end()) { - vkOut = mi->second; - return true; - } - return false; -} - bool CBasicKeyStore::GetSaplingFullViewingKey(const libzcash::SaplingIncomingViewingKey &ivk, libzcash::SaplingFullViewingKey &fvkOut) const { diff --git a/src/keystore.h b/src/keystore.h index ac2ccf233..6f34d9bc4 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -120,12 +120,7 @@ protected: KeyMap mapKeys; ScriptMap mapScripts; WatchOnlySet setWatchOnly; - /* - SproutSpendingKeyMap mapSproutSpendingKeys; - SproutViewingKeyMap mapSproutViewingKeys; - NoteDecryptorMap mapNoteDecryptors; - */ - + SaplingSpendingKeyMap mapSaplingSpendingKeys; SaplingFullViewingKeyMap mapSaplingFullViewingKeys; SaplingIncomingViewingKeyMap mapSaplingIncomingViewingKeys; @@ -246,7 +241,6 @@ public: typedef std::vector > CKeyingMaterial; typedef std::map > > CryptedKeyMap; -//typedef std::map > CryptedSproutSpendingKeyMap; //! Sapling typedef std::map > CryptedSaplingSpendingKeyMap; diff --git a/src/paymentdisclosure.h b/src/paymentdisclosure.h index 28a1d4cdc..5c3a20c33 100644 --- a/src/paymentdisclosure.h +++ b/src/paymentdisclosure.h @@ -1,4 +1,5 @@ // Copyright (c) 2017 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index fb3e21137..a41a8169d 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -204,7 +204,7 @@ UniValue getinfo(const UniValue& params, bool fHelp, const CPubKey& mypk) " \"version\": xxxxx, (numeric) the server version\n" " \"protocolversion\": xxxxx, (numeric) the protocol version\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" - " \"balance\": xxxxxxx, (numeric) the total Komodo balance of the wallet\n" + " \"balance\": xxxxxxx, (numeric) the total Hush balance of the wallet\n" " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" " \"timeoffset\": xxxxx, (numeric) the time offset\n" " \"connections\": xxxxx, (numeric) the number of connections\n" @@ -590,30 +590,6 @@ UniValue validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk } -class DescribePaymentAddressVisitor : public boost::static_visitor -{ -public: - UniValue operator()(const libzcash::InvalidEncoding &zaddr) const { return UniValue(UniValue::VOBJ); } - - UniValue operator()(const libzcash::SaplingPaymentAddress &zaddr) const { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("type", "sapling")); - obj.push_back(Pair("diversifier", HexStr(zaddr.d))); - obj.push_back(Pair("diversifiedtransmissionkey", zaddr.pk_d.GetHex())); -#ifdef ENABLE_WALLET - if (pwalletMain) { - libzcash::SaplingIncomingViewingKey ivk; - libzcash::SaplingFullViewingKey fvk; - bool isMine = pwalletMain->GetSaplingIncomingViewingKey(zaddr, ivk) && - pwalletMain->GetSaplingFullViewingKey(ivk, fvk) && - pwalletMain->HaveSaplingSpendingKey(fvk); - obj.push_back(Pair("ismine", isMine)); - } -#endif - return obj; - } -}; - UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (fHelp || params.size() != 1) @@ -650,11 +626,25 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& my UniValue ret(UniValue::VOBJ); ret.push_back(Pair("isvalid", isValid)); - if (isValid) + auto zaddr = boost::get(&address); + if (isValid && (zaddr != nullptr)) { ret.push_back(Pair("address", strAddress)); - UniValue detail = boost::apply_visitor(DescribePaymentAddressVisitor(), address); - ret.pushKVs(detail); + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("type", "sapling")); + obj.push_back(Pair("diversifier", HexStr(zaddr->d))); + obj.push_back(Pair("diversifiedtransmissionkey", zaddr->pk_d.GetHex())); +#ifdef ENABLE_WALLET + if (pwalletMain) { + libzcash::SaplingIncomingViewingKey ivk; + libzcash::SaplingFullViewingKey fvk; + bool isMine = pwalletMain->GetSaplingIncomingViewingKey(*zaddr, ivk) && + pwalletMain->GetSaplingFullViewingKey(ivk, fvk) && + pwalletMain->HaveSaplingSpendingKey(fvk); + obj.push_back(Pair("ismine", isMine)); + } +#endif + ret.pushKVs(obj); } return ret; } @@ -733,9 +723,9 @@ UniValue createmultisig(const UniValue& params, bool fHelp, const CPubKey& mypk) "\nArguments:\n" "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" - "2. \"keys\" (string, required) A json array of keys which are Komodo addresses or hex-encoded public keys\n" + "2. \"keys\" (string, required) A json array of keys which are Hush addresses or hex-encoded public keys\n" " [\n" - " \"key\" (string) Komodo address or hex-encoded public key\n" + " \"key\" (string) Hush address or hex-encoded public key\n" " ,...\n" " ]\n" @@ -769,10 +759,10 @@ UniValue verifymessage(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (fHelp || params.size() != 3) throw runtime_error( - "verifymessage \"komodoaddress\" \"signature\" \"message\"\n" + "verifymessage \"hushaddress\" \"signature\" \"message\"\n" "\nVerify a signed message\n" "\nArguments:\n" - "1. \"komodoaddress\" (string, required) The Komodo address to use for the signature.\n" + "1. \"hushaddress\" (string, required) The Hush address to use for the signature.\n" "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n" "3. \"message\" (string, required) The message that was signed.\n" "\nResult:\n" diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 107188779..2abe2d782 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -571,9 +571,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) // Verify number of addresses stored in wallet is n1+n2 int numAddrs = myaddrs.size(); BOOST_CHECK(numAddrs == (2 * n1) + n2); - pwalletMain->GetSproutPaymentAddresses(addrs); pwalletMain->GetSaplingPaymentAddresses(saplingAddrs); - BOOST_CHECK(addrs.size() + saplingAddrs.size() == numAddrs); + BOOST_CHECK(saplingAddrs.size() == numAddrs); // Ask wallet to list addresses BOOST_CHECK_NO_THROW(retValue = CallRPC("z_listaddresses")); @@ -595,9 +594,6 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport) std::string newaddress = retValue.get_str(); auto address = DecodePaymentAddress(newaddress); BOOST_CHECK(IsValidPaymentAddress(address)); - BOOST_ASSERT(boost::get(&address) != nullptr); - auto newAddr = boost::get(address); - BOOST_CHECK(pwalletMain->HaveSproutSpendingKey(newAddr)); // Check if too many args BOOST_CHECK_THROW(CallRPC("z_getnewaddress toomanyargs"), runtime_error); diff --git a/src/utiltest.cpp b/src/utiltest.cpp deleted file mode 100644 index ead7fe6a0..000000000 --- a/src/utiltest.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2016 The Zcash developers -// Copyright (c) 2019-2020 The Hush developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "utiltest.h" - -#include "consensus/upgrades.h" - -#include - -CWalletTx GetValidReceive(ZCJoinSplit& params, - const libzcash::SproutSpendingKey& sk, CAmount value, - bool randomInputs, - int32_t version /* = 2 */) { - CMutableTransaction mtx; - mtx.nVersion = version; - mtx.vin.resize(2); - if (randomInputs) { - mtx.vin[0].prevout.hash = GetRandHash(); - mtx.vin[1].prevout.hash = GetRandHash(); - } else { - mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); - mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); - } - mtx.vin[0].prevout.n = 0; - mtx.vin[1].prevout.n = 0; - - // Generate an ephemeral keypair. - uint256 joinSplitPubKey; - unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; - crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); - mtx.joinSplitPubKey = joinSplitPubKey; - - std::array inputs = { - libzcash::JSInput(), // dummy input - libzcash::JSInput() // dummy input - }; - - std::array outputs = { - libzcash::JSOutput(sk.address(), value), - libzcash::JSOutput(sk.address(), value) - }; - - // Prepare JoinSplits - uint256 rt; - JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, - inputs, outputs, 2*value, 0, false}; - mtx.vjoinsplit.push_back(jsdesc); - - if (version >= 4) { - // Shielded Output - OutputDescription od; - mtx.vShieldedOutput.push_back(od); - } - - // Empty output script. - uint32_t consensusBranchId = SPROUT_BRANCH_ID; - CScript scriptCode; - CTransaction signTx(mtx); - uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); - - // Add the signature - assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, - dataToBeSigned.begin(), 32, - joinSplitPrivKey - ) == 0); - - CTransaction tx {mtx}; - CWalletTx wtx {NULL, tx}; - return wtx; -} - -libzcash::SproutNote GetNote(ZCJoinSplit& params, - const libzcash::SproutSpendingKey& sk, - const CTransaction& tx, size_t js, size_t n) { - ZCNoteDecryption decryptor {sk.receiving_key()}; - auto hSig = tx.vjoinsplit[js].h_sig(params, tx.joinSplitPubKey); - auto note_pt = libzcash::SproutNotePlaintext::decrypt( - decryptor, - tx.vjoinsplit[js].ciphertexts[n], - tx.vjoinsplit[js].ephemeralKey, - hSig, - (unsigned char) n); - return note_pt.note(sk.address()); -} - -CWalletTx GetValidSpend(ZCJoinSplit& params, - const libzcash::SproutSpendingKey& sk, - const libzcash::SproutNote& note, CAmount value) { - CMutableTransaction mtx; - mtx.vout.resize(2); - mtx.vout[0].nValue = value; - mtx.vout[1].nValue = 0; - - // Generate an ephemeral keypair. - uint256 joinSplitPubKey; - unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; - crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); - mtx.joinSplitPubKey = joinSplitPubKey; - - // Fake tree for the unused witness - SproutMerkleTree tree; - - libzcash::JSOutput dummyout; - libzcash::JSInput dummyin; - - { - if (note.value() > value) { - libzcash::SproutSpendingKey dummykey = libzcash::SproutSpendingKey::random(); - libzcash::SproutPaymentAddress dummyaddr = dummykey.address(); - dummyout = libzcash::JSOutput(dummyaddr, note.value() - value); - } else if (note.value() < value) { - libzcash::SproutSpendingKey dummykey = libzcash::SproutSpendingKey::random(); - libzcash::SproutPaymentAddress dummyaddr = dummykey.address(); - libzcash::SproutNote dummynote(dummyaddr.a_pk, (value - note.value()), uint256(), uint256()); - tree.append(dummynote.cm()); - dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey); - } - } - - tree.append(note.cm()); - - std::array inputs = { - libzcash::JSInput(tree.witness(), note, sk), - dummyin - }; - - std::array outputs = { - dummyout, // dummy output - libzcash::JSOutput() // dummy output - }; - - // Prepare JoinSplits - uint256 rt = tree.root(); - JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, - inputs, outputs, 0, value, false}; - mtx.vjoinsplit.push_back(jsdesc); - - // Empty output script. - uint32_t consensusBranchId = SPROUT_BRANCH_ID; - CScript scriptCode; - CTransaction signTx(mtx); - uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); - - // Add the signature - assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, - dataToBeSigned.begin(), 32, - joinSplitPrivKey - ) == 0); - CTransaction tx {mtx}; - CWalletTx wtx {NULL, tx}; - return wtx; -} diff --git a/src/utiltest.h b/src/utiltest.h deleted file mode 100644 index 327dc7be4..000000000 --- a/src/utiltest.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "wallet/wallet.h" -#include "zcash/JoinSplit.hpp" -#include "zcash/Note.hpp" -#include "zcash/NoteEncryption.hpp" - -CWalletTx GetValidReceive(ZCJoinSplit& params, - const libzcash::SproutSpendingKey& sk, CAmount value, - bool randomInputs, - int32_t version = 2); -libzcash::SproutNote GetNote(ZCJoinSplit& params, - const libzcash::SproutSpendingKey& sk, - const CTransaction& tx, size_t js, size_t n); -CWalletTx GetValidSpend(ZCJoinSplit& params, - const libzcash::SproutSpendingKey& sk, - const libzcash::SproutNote& note, CAmount value); diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.h b/src/wallet/asyncrpcoperation_shieldcoinbase.h index b3fef0fc1..db4fb83af 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.h +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.h @@ -1,4 +1,5 @@ // Copyright (c) 2017 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -123,7 +124,6 @@ public: ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount) : m_op(op), sendAmount(sendAmount) {} - bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 38aff1a04..9d11a55fe 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2009-2013 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * @@ -168,22 +169,6 @@ static bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector& vchCryptedSecret, - const libzcash::SproutPaymentAddress& address, - libzcash::SproutSpendingKey& sk) -{ - CKeyingMaterial vchSecret; - if (!DecryptSecret(vMasterKey, vchCryptedSecret, address.GetHash(), vchSecret)) - return false; - - if (vchSecret.size() != libzcash::SerializedSproutSpendingKeySize) - return false; - - CSecureDataStream ss(vchSecret, SER_NETWORK, PROTOCOL_VERSION); - ss >> sk; - return sk.address() == address; -} static bool DecryptSaplingSpendingKey(const CKeyingMaterial& vMasterKey, const std::vector& vchCryptedSecret, @@ -207,7 +192,7 @@ bool CCryptoKeyStore::SetCrypted() LOCK2(cs_KeyStore, cs_SpendingKeyStore); if (fUseCrypto) return true; - if (!(mapKeys.empty() && mapSproutSpendingKeys.empty() && mapSaplingSpendingKeys.empty())) + if (!(mapKeys.empty() && mapSaplingSpendingKeys.empty())) return false; fUseCrypto = true; return true; @@ -260,21 +245,6 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) if (fDecryptionThoroughlyChecked) break; } - CryptedSproutSpendingKeyMap::const_iterator miSprout = mapCryptedSproutSpendingKeys.begin(); - for (; miSprout != mapCryptedSproutSpendingKeys.end(); ++miSprout) - { - const libzcash::SproutPaymentAddress &address = (*miSprout).first; - const std::vector &vchCryptedSecret = (*miSprout).second; - libzcash::SproutSpendingKey sk; - if (!DecryptSproutSpendingKey(vMasterKeyIn, vchCryptedSecret, address, sk)) - { - keyFail = true; - break; - } - keyPass = true; - if (fDecryptionThoroughlyChecked) - break; - } CryptedSaplingSpendingKeyMap::const_iterator miSapling = mapCryptedSaplingSpendingKeys.begin(); for (; miSapling != mapCryptedSaplingSpendingKeys.end(); ++miSapling) { @@ -292,7 +262,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) } if (keyPass && keyFail) { - LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n"); + LogPrintf("Oh shit! The wallet is probably corrupted: Some keys decrypt but not all.\n"); assert(false); } if (keyFail || !keyPass) @@ -440,30 +410,6 @@ bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) co return false; } -bool CCryptoKeyStore::AddSproutSpendingKey(const libzcash::SproutSpendingKey &sk) -{ - { - LOCK(cs_SpendingKeyStore); - if (!IsCrypted()) - return CBasicKeyStore::AddSproutSpendingKey(sk); - - if (IsLocked()) - return false; - - std::vector vchCryptedSecret; - CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << sk; - CKeyingMaterial vchSecret(ss.begin(), ss.end()); - auto address = sk.address(); - if (!EncryptSecret(vMasterKey, vchSecret, address.GetHash(), vchCryptedSecret)) - return false; - - if (!AddCryptedSproutSpendingKey(address, sk.receiving_key(), vchCryptedSecret)) - return false; - } - return true; -} - bool CCryptoKeyStore::AddSaplingSpendingKey( const libzcash::SaplingExtendedSpendingKey &sk, const libzcash::SaplingPaymentAddress &defaultAddr) @@ -494,22 +440,6 @@ bool CCryptoKeyStore::AddSaplingSpendingKey( return true; } -bool CCryptoKeyStore::AddCryptedSproutSpendingKey( - const libzcash::SproutPaymentAddress &address, - const libzcash::ReceivingKey &rk, - const std::vector &vchCryptedSecret) -{ - { - LOCK(cs_SpendingKeyStore); - if (!SetCrypted()) - return false; - - mapCryptedSproutSpendingKeys[address] = vchCryptedSecret; - mapNoteDecryptors.insert(std::make_pair(address, ZCNoteDecryption(rk))); - } - return true; -} - bool CCryptoKeyStore::AddCryptedSaplingSpendingKey( const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector &vchCryptedSecret, @@ -531,23 +461,6 @@ bool CCryptoKeyStore::AddCryptedSaplingSpendingKey( return true; } -bool CCryptoKeyStore::GetSproutSpendingKey(const libzcash::SproutPaymentAddress &address, libzcash::SproutSpendingKey &skOut) const -{ - { - LOCK(cs_SpendingKeyStore); - if (!IsCrypted()) - return CBasicKeyStore::GetSproutSpendingKey(address, skOut); - - CryptedSproutSpendingKeyMap::const_iterator mi = mapCryptedSproutSpendingKeys.find(address); - if (mi != mapCryptedSproutSpendingKeys.end()) - { - const std::vector &vchCryptedSecret = (*mi).second; - return DecryptSproutSpendingKey(vMasterKey, vchCryptedSecret, address, skOut); - } - } - return false; -} - bool CCryptoKeyStore::GetSaplingSpendingKey(const libzcash::SaplingFullViewingKey &fvk, libzcash::SaplingExtendedSpendingKey &skOut) const { { @@ -603,22 +516,6 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) } } mapKeys.clear(); - BOOST_FOREACH(SproutSpendingKeyMap::value_type& mSproutSpendingKey, mapSproutSpendingKeys) - { - const libzcash::SproutSpendingKey &sk = mSproutSpendingKey.second; - CSecureDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << sk; - CKeyingMaterial vchSecret(ss.begin(), ss.end()); - libzcash::SproutPaymentAddress address = sk.address(); - std::vector vchCryptedSecret; - if (!EncryptSecret(vMasterKeyIn, vchSecret, address.GetHash(), vchCryptedSecret)) { - return false; - } - if (!AddCryptedSproutSpendingKey(address, sk.receiving_key(), vchCryptedSecret)) { - return false; - } - } - mapSproutSpendingKeys.clear(); //! Sapling key support BOOST_FOREACH(SaplingSpendingKeyMap::value_type& mSaplingSpendingKey, mapSaplingSpendingKeys) { diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index dcc7fdfdd..0ad789137 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -139,341 +139,8 @@ TEST(WalletTests, SetupDatadirLocationRunAsFirstTest) { boost::filesystem::create_directories(pathTemp); mapArgs["-datadir"] = pathTemp.string(); } +/* -TEST(WalletTests, SproutNoteDataSerialisation) { - auto sk = libzcash::SproutSpendingKey::random(); - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - SproutMerkleTree tree; - nd.witnesses.push_front(tree.witness()); - noteData[jsoutpt] = nd; - - CDataStream ss(SER_DISK, CLIENT_VERSION); - ss << noteData; - - mapSproutNoteData_t noteData2; - ss >> noteData2; - - EXPECT_EQ(noteData, noteData2); - EXPECT_EQ(noteData[jsoutpt].witnesses, noteData2[jsoutpt].witnesses); -} - - -TEST(WalletTests, FindUnspentSproutNotes) { - SelectParams(CBaseChainParams::TESTNET); - CWallet wallet; - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - noteData[jsoutpt] = nd; - - wtx.SetSproutNoteData(noteData); - wallet.AddToWallet(wtx, true, NULL); - EXPECT_FALSE(wallet.IsSproutSpent(nullifier)); - - // We currently have an unspent and unconfirmed note in the wallet (depth of -1) - std::vector sproutEntries; - std::vector saplingEntries; - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0); - EXPECT_EQ(0, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", -1); - EXPECT_EQ(1, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - - // Fake-mine the transaction - EXPECT_EQ(-1, chainActive.Height()); - CBlock block; - block.vtx.push_back(wtx); - block.hashMerkleRoot = block.BuildMerkleTree(); - auto blockHash = block.GetHash(); - CBlockIndex fakeIndex {block}; - mapBlockIndex.insert(std::make_pair(blockHash, &fakeIndex)); - chainActive.SetTip(&fakeIndex); - EXPECT_TRUE(chainActive.Contains(&fakeIndex)); - EXPECT_EQ(0, chainActive.Height()); - - wtx.SetMerkleBranch(block); - wallet.AddToWallet(wtx, true, NULL); - EXPECT_FALSE(wallet.IsSproutSpent(nullifier)); - - - // We now have an unspent and confirmed note in the wallet (depth of 1) - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0); - EXPECT_EQ(1, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 1); - EXPECT_EQ(1, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 2); - EXPECT_EQ(0, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - - - // Let's spend the note. - auto wtx2 = GetValidSpend(sk, note, 5); - wallet.AddToWallet(wtx2, true, NULL); - EXPECT_FALSE(wallet.IsSproutSpent(nullifier)); - - // Fake-mine a spend transaction - EXPECT_EQ(0, chainActive.Height()); - CBlock block2; - block2.vtx.push_back(wtx2); - block2.hashMerkleRoot = block2.BuildMerkleTree(); - block2.hashPrevBlock = blockHash; - auto blockHash2 = block2.GetHash(); - CBlockIndex fakeIndex2 {block2}; - mapBlockIndex.insert(std::make_pair(blockHash2, &fakeIndex2)); - fakeIndex2.SetHeight(1); - chainActive.SetTip(&fakeIndex2); - EXPECT_TRUE(chainActive.Contains(&fakeIndex2)); - EXPECT_EQ(1, chainActive.Height()); - - wtx2.SetMerkleBranch(block2); - wallet.AddToWallet(wtx2, true, NULL); - EXPECT_TRUE(wallet.IsSproutSpent(nullifier)); - - // The note has been spent. By default, GetFilteredNotes() ignores spent notes. - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0); - EXPECT_EQ(0, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - // Let's include spent notes to retrieve it. - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 0, false); - EXPECT_EQ(1, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - // The spent note has two confirmations. - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 2, false); - EXPECT_EQ(1, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - // It does not have 3 confirmations. - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 3, false); - EXPECT_EQ(0, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - - - // Let's receive a new note - CWalletTx wtx3; - { - auto wtx = GetValidReceive(sk, 20, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - noteData[jsoutpt] = nd; - - wtx.SetSproutNoteData(noteData); - wallet.AddToWallet(wtx, true, NULL); - EXPECT_FALSE(wallet.IsSproutSpent(nullifier)); - - wtx3 = wtx; - } - - // Fake-mine the new transaction - EXPECT_EQ(1, chainActive.Height()); - CBlock block3; - block3.vtx.push_back(wtx3); - block3.hashMerkleRoot = block3.BuildMerkleTree(); - block3.hashPrevBlock = blockHash2; - auto blockHash3 = block3.GetHash(); - CBlockIndex fakeIndex3 {block3}; - mapBlockIndex.insert(std::make_pair(blockHash3, &fakeIndex3)); - fakeIndex3.SetHeight(2); - chainActive.SetTip(&fakeIndex3); - EXPECT_TRUE(chainActive.Contains(&fakeIndex3)); - EXPECT_EQ(2, chainActive.Height()); - - wtx3.SetMerkleBranch(block3); - wallet.AddToWallet(wtx3, true, NULL); - - // We now have an unspent note which has one confirmation, in addition to our spent note. - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 1); - EXPECT_EQ(1, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - // Let's return the spent note too. - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 1, false); - EXPECT_EQ(2, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - // Increasing number of confirmations will exclude our new unspent note. - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 2, false); - EXPECT_EQ(1, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - // If we also ignore spent notes at this depth, we won't find any notes. - wallet.GetFilteredNotes(sproutEntries, saplingEntries, "", 2, true); - EXPECT_EQ(0, sproutEntries.size()); - sproutEntries.clear(); - saplingEntries.clear(); - - // Tear down - chainActive.SetTip(NULL); - mapBlockIndex.erase(blockHash); - mapBlockIndex.erase(blockHash2); - mapBlockIndex.erase(blockHash3); -} - - -TEST(WalletTests, SetSproutNoteAddrsInCWalletTx) { - auto sk = libzcash::SproutSpendingKey::random(); - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - EXPECT_EQ(0, wtx.mapSproutNoteData.size()); - - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - noteData[jsoutpt] = nd; - - wtx.SetSproutNoteData(noteData); - EXPECT_EQ(noteData, wtx.mapSproutNoteData); -} - -TEST(WalletTests, SetSaplingNoteAddrsInCWalletTx) { - SelectParams(CBaseChainParams::REGTEST); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - auto consensusParams = Params().GetConsensus(); - - TestWallet wallet; - - std::vector> rawSeed(32); - HDSeed seed(rawSeed); - auto sk = libzcash::SaplingExtendedSpendingKey::Master(seed); - auto expsk = sk.expsk; - auto fvk = expsk.full_viewing_key(); - auto ivk = fvk.in_viewing_key(); - auto pk = sk.DefaultAddress(); - - libzcash::SaplingNote note(pk, 50000); - auto cm = note.cm().get(); - SaplingMerkleTree tree; - tree.append(cm); - auto anchor = tree.root(); - auto witness = tree.witness(); - - auto nf = note.nullifier(fvk, witness.position()); - ASSERT_TRUE(nf); - uint256 nullifier = nf.get(); - - auto builder = TransactionBuilder(consensusParams, 1); - ASSERT_TRUE(builder.AddSaplingSpend(expsk, note, anchor, witness)); - builder.AddSaplingOutput(fvk.ovk, pk, 50000, {}); - builder.SetFee(0); - auto maybe_tx = builder.Build(); - ASSERT_EQ(static_cast(maybe_tx), true); - auto tx = maybe_tx.get(); - - CWalletTx wtx {&wallet, tx}; - - EXPECT_EQ(0, wtx.mapSaplingNoteData.size()); - mapSaplingNoteData_t noteData; - - SaplingOutPoint op {wtx.GetHash(), 0}; - SaplingNoteData nd; - nd.nullifier = nullifier; - nd.ivk = ivk; - nd.witnesses.push_front(witness); - nd.witnessHeight = 123; - noteData.insert(std::make_pair(op, nd)); - - wtx.SetSaplingNoteData(noteData); - EXPECT_EQ(noteData, wtx.mapSaplingNoteData); - - // Test individual fields in case equality operator is defined/changed. - EXPECT_EQ(ivk, wtx.mapSaplingNoteData[op].ivk); - EXPECT_EQ(nullifier, wtx.mapSaplingNoteData[op].nullifier); - EXPECT_EQ(nd.witnessHeight, wtx.mapSaplingNoteData[op].witnessHeight); - EXPECT_TRUE(witness == wtx.mapSaplingNoteData[op].witnesses.front()); - - // Revert to default - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); -} - -TEST(WalletTests, SetSproutInvalidNoteAddrsInCWalletTx) { - CWalletTx wtx; - EXPECT_EQ(0, wtx.mapSproutNoteData.size()); - - mapSproutNoteData_t noteData; - auto sk = libzcash::SproutSpendingKey::random(); - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), uint256()}; - noteData[jsoutpt] = nd; - - EXPECT_THROW(wtx.SetSproutNoteData(noteData), std::logic_error); -} - -// The following test is the same as SetInvalidSaplingNoteDataInCWalletTx -// TEST(WalletTests, SetSaplingInvalidNoteAddrsInCWalletTx) - -// Cannot add note data for an index which does not exist in tx.vShieldedOutput -TEST(WalletTests, SetInvalidSaplingNoteDataInCWalletTx) { - CWalletTx wtx; - EXPECT_EQ(0, wtx.mapSaplingNoteData.size()); - - mapSaplingNoteData_t noteData; - SaplingOutPoint op {uint256(), 1}; - SaplingNoteData nd; - noteData.insert(std::make_pair(op, nd)); - - EXPECT_THROW(wtx.SetSaplingNoteData(noteData), std::logic_error); -} - -TEST(WalletTests, GetSproutNoteNullifier) { - CWallet wallet; - - auto sk = libzcash::SproutSpendingKey::random(); - auto address = sk.address(); - auto dec = ZCNoteDecryption(sk.receiving_key()); - - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - auto hSig = wtx.vjoinsplit[0].h_sig( - *params, wtx.joinSplitPubKey); - - auto ret = wallet.GetSproutNoteNullifier( - wtx.vjoinsplit[0], - address, - dec, - hSig, 1); - EXPECT_NE(nullifier, ret); - - wallet.AddSproutSpendingKey(sk); - - ret = wallet.GetSproutNoteNullifier( - wtx.vjoinsplit[0], - address, - dec, - hSig, 1); - EXPECT_EQ(nullifier, ret); -} TEST(WalletTests, FindMySaplingNotes) { SelectParams(CBaseChainParams::REGTEST); @@ -577,92 +244,6 @@ TEST(WalletTests, FindMySaplingNotesWithIvkOnly) { UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); } -TEST(WalletTests, FindMySproutNotes) { - CWallet wallet; - - auto sk = libzcash::SproutSpendingKey::random(); - auto sk2 = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk2); - - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - auto noteMap = wallet.FindMySproutNotes(wtx); - EXPECT_EQ(0, noteMap.size()); - - wallet.AddSproutSpendingKey(sk); - - noteMap = wallet.FindMySproutNotes(wtx); - EXPECT_EQ(2, noteMap.size()); - - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - EXPECT_EQ(1, noteMap.count(jsoutpt)); - EXPECT_EQ(nd, noteMap[jsoutpt]); -} - -TEST(WalletTests, FindMySproutNotesInEncryptedWallet) { - TestWallet wallet; - uint256 r {GetRandHash()}; - CKeyingMaterial vMasterKey (r.begin(), r.end()); - - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - - ASSERT_TRUE(wallet.EncryptKeys(vMasterKey)); - - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - auto noteMap = wallet.FindMySproutNotes(wtx); - EXPECT_EQ(2, noteMap.size()); - - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - EXPECT_EQ(1, noteMap.count(jsoutpt)); - EXPECT_NE(nd, noteMap[jsoutpt]); - - ASSERT_TRUE(wallet.Unlock(vMasterKey)); - - noteMap = wallet.FindMySproutNotes(wtx); - EXPECT_EQ(2, noteMap.size()); - EXPECT_EQ(1, noteMap.count(jsoutpt)); - EXPECT_EQ(nd, noteMap[jsoutpt]); -} - -TEST(WalletTests, GetConflictedSproutNotes) { - CWallet wallet; - - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - auto wtx2 = GetValidSpend(sk, note, 5); - auto wtx3 = GetValidSpend(sk, note, 10); - auto hash2 = wtx2.GetHash(); - auto hash3 = wtx3.GetHash(); - - // No conflicts for no spends - EXPECT_EQ(0, wallet.GetConflicts(hash2).size()); - wallet.AddToWallet(wtx, true, NULL); - EXPECT_EQ(0, wallet.GetConflicts(hash2).size()); - - // No conflicts for one spend - wallet.AddToWallet(wtx2, true, NULL); - EXPECT_EQ(0, wallet.GetConflicts(hash2).size()); - - // Conflicts for two spends - wallet.AddToWallet(wtx3, true, NULL); - auto c3 = wallet.GetConflicts(hash2); - EXPECT_EQ(2, c3.size()); - EXPECT_EQ(std::set({hash2, hash3}), c3); -} - // Generate note A and spend to create note B, from which we spend to create two conflicting transactions TEST(WalletTests, GetConflictedSaplingNotes) { SelectParams(CBaseChainParams::REGTEST); @@ -1735,88 +1316,6 @@ TEST(WalletTests, SetBestChainIgnoresTxsWithoutShieldedData) { wallet.SetBestChain(walletdb, loc); } -TEST(WalletTests, UpdateSproutNullifierNoteMap) { - TestWallet wallet; - uint256 r {GetRandHash()}; - CKeyingMaterial vMasterKey (r.begin(), r.end()); - - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - - ASSERT_TRUE(wallet.EncryptKeys(vMasterKey)); - - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - - // Pretend that we called FindMySproutNotes while the wallet was locked - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; - SproutNoteData nd {sk.address()}; - noteData[jsoutpt] = nd; - wtx.SetSproutNoteData(noteData); - - wallet.AddToWallet(wtx, true, NULL); - EXPECT_EQ(0, wallet.mapSproutNullifiersToNotes.count(nullifier)); - - EXPECT_FALSE(wallet.UpdateNullifierNoteMap()); - - ASSERT_TRUE(wallet.Unlock(vMasterKey)); - - EXPECT_TRUE(wallet.UpdateNullifierNoteMap()); - EXPECT_EQ(1, wallet.mapSproutNullifiersToNotes.count(nullifier)); - EXPECT_EQ(wtx.GetHash(), wallet.mapSproutNullifiersToNotes[nullifier].hash); - EXPECT_EQ(0, wallet.mapSproutNullifiersToNotes[nullifier].js); - EXPECT_EQ(1, wallet.mapSproutNullifiersToNotes[nullifier].n); -} - -TEST(WalletTests, UpdatedSproutNoteData) { - TestWallet wallet; - - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - - auto wtx = GetValidReceive(sk, 10, true); - auto note = GetNote(sk, wtx, 0, 0); - auto note2 = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - auto nullifier2 = note2.nullifier(sk); - auto wtx2 = wtx; - - // First pretend we added the tx to the wallet and - // we don't have the key for the second note - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {wtx.GetHash(), 0, 0}; - SproutNoteData nd {sk.address(), nullifier}; - noteData[jsoutpt] = nd; - wtx.SetSproutNoteData(noteData); - - // Pretend we mined the tx by adding a fake witness - SproutMerkleTree tree; - wtx.mapSproutNoteData[jsoutpt].witnesses.push_front(tree.witness()); - wtx.mapSproutNoteData[jsoutpt].witnessHeight = 100; - - // Now pretend we added the key for the second note, and - // the tx was "added" to the wallet again to update it. - // This happens via the 'z_importkey' RPC method. - JSOutPoint jsoutpt2 {wtx2.GetHash(), 0, 1}; - SproutNoteData nd2 {sk.address(), nullifier2}; - noteData[jsoutpt2] = nd2; - wtx2.SetSproutNoteData(noteData); - - // The txs should initially be different - EXPECT_NE(wtx.mapSproutNoteData, wtx2.mapSproutNoteData); - EXPECT_EQ(1, wtx.mapSproutNoteData[jsoutpt].witnesses.size()); - EXPECT_EQ(100, wtx.mapSproutNoteData[jsoutpt].witnessHeight); - - // After updating, they should be the same - EXPECT_TRUE(wallet.UpdatedNoteData(wtx2, wtx)); - EXPECT_EQ(wtx.mapSproutNoteData, wtx2.mapSproutNoteData); - EXPECT_EQ(1, wtx.mapSproutNoteData[jsoutpt].witnesses.size()); - EXPECT_EQ(100, wtx.mapSproutNoteData[jsoutpt].witnessHeight); - // TODO: The new note should get witnessed (but maybe not here) (#1350) -} - TEST(WalletTests, UpdatedSaplingNoteData) { SelectParams(CBaseChainParams::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); @@ -1941,37 +1440,6 @@ TEST(WalletTests, UpdatedSaplingNoteData) { UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); } -TEST(WalletTests, MarkAffectedSproutTransactionsDirty) { - TestWallet wallet; - - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - - auto wtx = GetValidReceive(sk, 10, true); - auto hash = wtx.GetHash(); - auto note = GetNote(sk, wtx, 0, 1); - auto nullifier = note.nullifier(sk); - auto wtx2 = GetValidSpend(sk, note, 5); - - mapSproutNoteData_t noteData; - JSOutPoint jsoutpt {hash, 0, 1}; - SproutNoteData nd {sk.address(), nullifier}; - noteData[jsoutpt] = nd; - - wtx.SetSproutNoteData(noteData); - wallet.AddToWallet(wtx, true, NULL); - wallet.MarkAffectedTransactionsDirty(wtx); - - // After getting a cached value, the first tx should be clean - wallet.mapWallet[hash].GetDebit(ISMINE_ALL); - EXPECT_TRUE(wallet.mapWallet[hash].fDebitCached); - - // After adding the note spend, the first tx should be dirty - wallet.AddToWallet(wtx2, true, NULL); - wallet.MarkAffectedTransactionsDirty(wtx2); - EXPECT_FALSE(wallet.mapWallet[hash].fDebitCached); -} - TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { SelectParams(CBaseChainParams::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); @@ -1999,7 +1467,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { auto scriptPubKey = GetScriptForDestination(tsk.GetPubKey().GetID()); // Generate shielding tx from transparent to Sapling - // 0.0005 t-ZEC in, 0.0004 z-ZEC out, 0.0001 t-ZEC fee + // 0.0005 t-HUSH in, 0.0004 z-HUSH out, 0.0001 t-HUSH fee auto builder = TransactionBuilder(consensusParams, 1, &keystore); builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); builder.AddSaplingOutput(fvk.ovk, pk, 40000, {}); @@ -2093,39 +1561,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) { UpdateNetworkUpgradeParameters(Consensus::UPGRADE_SAPLING, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); } - -TEST(WalletTests, SproutNoteLocking) { - TestWallet wallet; - - auto sk = libzcash::SproutSpendingKey::random(); - wallet.AddSproutSpendingKey(sk); - - auto wtx = GetValidReceive(sk, 10, true); - auto wtx2 = GetValidReceive(sk, 10, true); - - JSOutPoint jsoutpt {wtx.GetHash(), 0, 0}; - JSOutPoint jsoutpt2 {wtx2.GetHash(),0, 0}; - - // Test selective locking - wallet.LockNote(jsoutpt); - EXPECT_TRUE(wallet.IsLockedNote(jsoutpt)); - EXPECT_FALSE(wallet.IsLockedNote(jsoutpt2)); - - // Test selective unlocking - wallet.UnlockNote(jsoutpt); - EXPECT_FALSE(wallet.IsLockedNote(jsoutpt)); - - // Test multiple locking - wallet.LockNote(jsoutpt); - wallet.LockNote(jsoutpt2); - EXPECT_TRUE(wallet.IsLockedNote(jsoutpt)); - EXPECT_TRUE(wallet.IsLockedNote(jsoutpt2)); - - // Test unlock all - wallet.UnlockAllSproutNotes(); - EXPECT_FALSE(wallet.IsLockedNote(jsoutpt)); - EXPECT_FALSE(wallet.IsLockedNote(jsoutpt2)); -} +*/ TEST(WalletTests, SaplingNoteLocking) { TestWallet wallet; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 37f67042b..d3d396bbc 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5487,34 +5487,6 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp "Cannot send between Sprout and Sapling addresses using z_mergetoaddress"); } - // Find unspent notes and update estimated size - for (const CSproutNotePlaintextEntry& entry : sproutEntries) { - noteCounter++; - CAmount nValue = entry.plaintext.value(); - - if (!maxedOutNotesFlag) { - // If we haven't added any notes yet and the merge is to a - // z-address, we have already accounted for the first JoinSplit. - size_t increase = (sproutNoteInputs.empty() && !isToSproutZaddr) || (sproutNoteInputs.size() % 2 == 0) ? JOINSPLIT_SIZE : 0; - if (estimatedTxSize + increase >= max_tx_size || - (sproutNoteLimit > 0 && noteCounter > sproutNoteLimit)) - { - maxedOutNotesFlag = true; - } else { - estimatedTxSize += increase; - auto zaddr = entry.address; - SproutSpendingKey zkey; - pwalletMain->GetSproutSpendingKey(zaddr, zkey); - sproutNoteInputs.emplace_back(entry.jsop, entry.plaintext.note(zaddr), nValue, zkey); - mergedNoteValue += nValue; - } - } - - if (maxedOutNotesFlag) { - remainingNoteValue += nValue; - } - } - for (const SaplingNoteEntry& entry : saplingEntries) { noteCounter++; CAmount nValue = entry.note.value(); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d82e100ed..f3526c583 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1408,7 +1408,6 @@ private: public: PaymentAddressBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {} - bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1421,7 +1420,6 @@ private: public: IncomingViewingKeyBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {} - bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1433,7 +1431,6 @@ private: public: HaveSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} - bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1445,7 +1442,6 @@ private: public: GetSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} - boost::optional operator()(const libzcash::SproutPaymentAddress &zaddr) const; boost::optional operator()(const libzcash::SaplingPaymentAddress &zaddr) const; boost::optional operator()(const libzcash::InvalidEncoding& no) const; }; @@ -1517,7 +1513,6 @@ public: ) : m_wallet(wallet), params(params), nTime(_nTime), hdKeypath(_hdKeypath), seedFpStr(_seedFp), log(_log) {} - SpendingKeyAddResult operator()(const libzcash::SproutSpendingKey &sk) const; SpendingKeyAddResult operator()(const libzcash::SaplingExtendedSpendingKey &sk) const; SpendingKeyAddResult operator()(const libzcash::InvalidEncoding& no) const; }; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 1177bbedd..71331ed93 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -653,6 +653,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "czkey") { + /* libzcash::SproutPaymentAddress addr; ssKey >> addr; // Deserialization of a pair is just one item after another @@ -663,12 +664,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssValue >> vchCryptedSecret; wss.nCKeys++; - //if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret)) - //{ - // strErr = "Error reading wallet database: LoadCryptedZKey failed"; - // return false; - //} - //wss.fIsEncrypted = true; + if (!pwallet->LoadCryptedZKey(addr, rk, vchCryptedSecret)) + { + strErr = "Error reading wallet database: LoadCryptedZKey failed"; + return false; + } + wss.fIsEncrypted = true; + */ } else if (strType == "csapzkey") { @@ -704,11 +706,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else if (strType == "zkeymeta") { + /* libzcash::SproutPaymentAddress addr; ssKey >> addr; CKeyMetadata keyMeta; ssValue >> keyMeta; wss.nZKeyMeta++; + */ // pwallet->LoadZKeyMetadata(addr, keyMeta); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 9069e3a08..64a4817d9 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -1,7 +1,8 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers +// Copyright (c) 2009-2013 The Hush developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * @@ -199,23 +200,15 @@ public: bool WriteHDChain(const CHDChain& chain); /// Write spending key to wallet database, where key is payment address and value is spending key. - bool WriteZKey(const libzcash::SproutPaymentAddress& addr, const libzcash::SproutSpendingKey& key, const CKeyMetadata &keyMeta); bool WriteSaplingZKey(const libzcash::SaplingIncomingViewingKey &ivk, const libzcash::SaplingExtendedSpendingKey &key, const CKeyMetadata &keyMeta); bool WriteSaplingPaymentAddress(const libzcash::SaplingPaymentAddress &addr, const libzcash::SaplingIncomingViewingKey &ivk); - bool WriteCryptedZKey(const libzcash::SproutPaymentAddress & addr, - const libzcash::ReceivingKey & rk, - const std::vector& vchCryptedSecret, - const CKeyMetadata &keyMeta); bool WriteCryptedSaplingZKey(const libzcash::SaplingExtendedFullViewingKey &extfvk, const std::vector& vchCryptedSecret, const CKeyMetadata &keyMeta); - bool WriteSproutViewingKey(const libzcash::SproutViewingKey &vk); - bool EraseSproutViewingKey(const libzcash::SproutViewingKey &vk); - private: CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); diff --git a/src/zcash/Address.cpp b/src/zcash/Address.cpp index 148cd321c..5ce66a82f 100644 --- a/src/zcash/Address.cpp +++ b/src/zcash/Address.cpp @@ -1,3 +1,7 @@ +// Copyright (c) 2019-2020 The Hush developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php + #include "Address.hpp" #include "NoteEncryption.hpp" #include "hash.h" @@ -13,36 +17,6 @@ const uint32_t SAPLING_BRANCH_ID = 0x76b809bb; namespace libzcash { -uint256 SproutPaymentAddress::GetHash() const { - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << *this; - return Hash(ss.begin(), ss.end()); -} - -uint256 ReceivingKey::pk_enc() const { - return ZCNoteEncryption::generate_pubkey(*this); -} - -SproutPaymentAddress SproutViewingKey::address() const { - return SproutPaymentAddress(a_pk, sk_enc.pk_enc()); -} - -ReceivingKey SproutSpendingKey::receiving_key() const { - return ReceivingKey(ZCNoteEncryption::generate_privkey(*this)); -} - -SproutViewingKey SproutSpendingKey::viewing_key() const { - return SproutViewingKey(PRF_addr_a_pk(*this), receiving_key()); -} - -SproutSpendingKey SproutSpendingKey::random() { - return SproutSpendingKey(random_uint252()); -} - -SproutPaymentAddress SproutSpendingKey::address() const { - return viewing_key().address(); -} - //! Sapling uint256 SaplingPaymentAddress::GetHash() const { CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -119,10 +93,6 @@ class IsValidAddressForNetwork : public boost::static_visitor { public: IsValidAddressForNetwork(uint32_t consensusBranchId) : branchId(consensusBranchId) {} - bool operator()(const libzcash::SproutPaymentAddress &addr) const { - return true; - } - bool operator()(const libzcash::InvalidEncoding &addr) const { return false; } diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 9af3c184a..152ad7295 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -25,7 +25,6 @@ #include "sodium.h" #include "streams.h" #include "txdb.h" -#include "utiltest.h" #include "wallet/wallet.h" #include "zcbenchmarks.h" @@ -41,7 +40,7 @@ void pre_wallet_load() { LogPrintf("%s: In progress...\n", __func__); if (ShutdownRequested()) - throw new std::runtime_error("The node is shutting down"); + throw new std::runtime_error("The Hush node is shutting down"); if (pwalletMain) pwalletMain->Flush(false); @@ -93,37 +92,6 @@ double benchmark_sleep() return timer_stop(tv_start); } -std::vector benchmark_create_joinsplit_threaded(int nThreads) -{ - std::vector ret; - std::vector> tasks; - std::vector threads; - for (int i = 0; i < nThreads; i++) { - std::packaged_task task(&benchmark_create_joinsplit); - tasks.emplace_back(task.get_future()); - threads.emplace_back(std::move(task)); - } - std::future_status status; - for (auto it = tasks.begin(); it != tasks.end(); it++) { - it->wait(); - ret.push_back(it->get()); - } - for (auto it = threads.begin(); it != threads.end(); it++) { - it->join(); - } - return ret; -} - -double benchmark_verify_joinsplit(const JSDescription &joinsplit) -{ - struct timeval tv_start; - timer_start(tv_start); - uint256 joinSplitPubKey; - auto verifier = libzcash::ProofVerifier::Strict(); - joinsplit.Verify(*pzcashParams, verifier, joinSplitPubKey); - return timer_stop(tv_start); -} - #ifdef ENABLE_MINING double benchmark_solve_equihash() { From 2c661422928dd1de743b02f29c0dc88cb24608e5 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 01:22:51 -0400 Subject: [PATCH 46/98] desprout --- src/key_io.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/key_io.cpp b/src/key_io.cpp index dd4bf884c..2626a0b9b 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -321,20 +321,6 @@ std::string EncodeViewingKey(const libzcash::ViewingKey& vk) libzcash::ViewingKey DecodeViewingKey(const std::string& str) { std::vector data; - if (DecodeBase58Check(str, data)) { - const std::vector& vk_prefix = Params().Base58Prefix(CChainParams::ZCVIEWING_KEY); - if ((data.size() == libzcash::SerializedSproutViewingKeySize + vk_prefix.size()) && - std::equal(vk_prefix.begin(), vk_prefix.end(), data.begin())) { - CSerializeData serialized(data.begin() + vk_prefix.size(), data.end()); - CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); - libzcash::SproutViewingKey ret; - ss >> ret; - memory_cleanse(serialized.data(), serialized.size()); - memory_cleanse(data.data(), data.size()); - return ret; - } - } - data.clear(); auto bech = bech32::Decode(str); if(bech.first == Params().Bech32HRP(CChainParams::SAPLING_INCOMING_VIEWING_KEY) && bech.second.size() == ConvertedSaplingIncomingViewingKeySize) { From 42a862650b4cfbe7a3f0c156cef68be4f7fa3a99 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 01:34:55 -0400 Subject: [PATCH 47/98] desprout --- src/key_io.cpp | 14 -------------- src/key_io.h | 1 + src/test/coins_tests.cpp | 17 +---------------- 3 files changed, 2 insertions(+), 30 deletions(-) diff --git a/src/key_io.cpp b/src/key_io.cpp index 2626a0b9b..319c24eef 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -344,20 +344,6 @@ std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey) libzcash::SpendingKey DecodeSpendingKey(const std::string& str) { std::vector data; - if (DecodeBase58Check(str, data)) { - const std::vector& zkey_prefix = Params().Base58Prefix(CChainParams::ZCSPENDING_KEY); - if ((data.size() == libzcash::SerializedSproutSpendingKeySize + zkey_prefix.size()) && - std::equal(zkey_prefix.begin(), zkey_prefix.end(), data.begin())) { - CSerializeData serialized(data.begin() + zkey_prefix.size(), data.end()); - CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); - libzcash::SproutSpendingKey ret; - ss >> ret; - memory_cleanse(serialized.data(), serialized.size()); - memory_cleanse(data.data(), data.size()); - return ret; - } - } - data.clear(); auto bech = bech32::Decode(str); if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY) && bech.second.size() == ConvertedSaplingExtendedSpendingKeySize) { diff --git a/src/key_io.h b/src/key_io.h index 013469ab6..567c9a2f2 100644 --- a/src/key_io.h +++ b/src/key_io.h @@ -1,6 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers // Copyright (c) 2016-2018 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index bb6432a81..8067b42b9 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -39,22 +40,6 @@ public: hashBestSaplingAnchor_ = SaplingMerkleTree::empty_root(); } - bool GetSproutAnchorAt(const uint256& rt, SproutMerkleTree &tree) const { - if (rt == SproutMerkleTree::empty_root()) { - SproutMerkleTree new_tree; - tree = new_tree; - return true; - } - - std::map::const_iterator it = mapSproutAnchors_.find(rt); - if (it == mapSproutAnchors_.end()) { - return false; - } else { - tree = it->second; - return true; - } - } - bool GetSaplingAnchorAt(const uint256& rt, SaplingMerkleTree &tree) const { if (rt == SaplingMerkleTree::empty_root()) { SaplingMerkleTree new_tree; From f7b1c1f26f537c4ba79eef257360aa81ce4a3208 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 07:20:38 -0400 Subject: [PATCH 48/98] Delete Payment Disclosures This code will be "experimental" forever, only supports Sprout, and is a piece of shit. Deleting with fire. Sapling viewing keys are the replacement, which already exist. --- doc/payment-disclosure.md | 107 ------ qa/pull-tester/rpc-tests.sh | 1 - qa/rpc-tests/paymentdisclosure.py | 215 ------------ src/Makefile.am | 7 - src/gtest/test_paymentdisclosure.cpp | 211 ------------ src/paymentdisclosure.cpp | 65 ---- src/paymentdisclosure.h | 149 -------- src/paymentdisclosuredb.cpp | 93 ----- src/paymentdisclosuredb.h | 42 --- .../asyncrpcoperation_mergetoaddress.cpp | 20 +- src/wallet/asyncrpcoperation_mergetoaddress.h | 7 +- src/wallet/asyncrpcoperation_sendmany.cpp | 17 +- src/wallet/asyncrpcoperation_sendmany.h | 7 +- .../asyncrpcoperation_shieldcoinbase.cpp | 19 - src/wallet/asyncrpcoperation_shieldcoinbase.h | 7 - src/wallet/rpcdisclosure.cpp | 324 ------------------ src/zcash/NoteEncryption.cpp | 50 +-- src/zcash/NoteEncryption.hpp | 29 +- 18 files changed, 8 insertions(+), 1362 deletions(-) delete mode 100644 doc/payment-disclosure.md delete mode 100755 qa/rpc-tests/paymentdisclosure.py delete mode 100644 src/gtest/test_paymentdisclosure.cpp delete mode 100644 src/paymentdisclosure.cpp delete mode 100644 src/paymentdisclosure.h delete mode 100644 src/paymentdisclosuredb.cpp delete mode 100644 src/paymentdisclosuredb.h delete mode 100644 src/wallet/rpcdisclosure.cpp diff --git a/doc/payment-disclosure.md b/doc/payment-disclosure.md deleted file mode 100644 index 02b4167da..000000000 --- a/doc/payment-disclosure.md +++ /dev/null @@ -1,107 +0,0 @@ -# Payment Disclosure (Experimental Feature) - -**Summary** - -Use RPC calls `z_getpaymentdisclosure` and `z_validatepaymentdisclosure` to reveal details of a shielded payment. - -**Who should read this document** - -Frequent users of shielded transactions, payment processors, exchanges, block explorer - -### Experimental Feature - -This is an experimental feature. Enable it by launching `zcashd` with flags: - - zcashd -experimentalfeatures -paymentdisclosure -debug=paymentdisclosure -txindex=1 - -These flags can also be set as options in `zcash.conf`. - -All nodes that generate or validate payment disclosures must run with `txindex=1` enabled. - -### Background - -Payment Disclosure is an implementation of the work-in-progress Payment Disclosure ZIP [1]. - -The ZIP describes a method of proving that a payment was sent to a shielded address. In the typical case, this means enabling a sender to present a proof that they transferred funds to a recipient's shielded address. - -[1] https://github.com/zcash/zips/pull/119 - -### Example Use Case - -Alice the customer sends 10 HUSH to Bob the merchant at the shielded address shown on their website. However, Bob is not sure if he received the funds. - -Alice's node is running with payment disclosure enabled, so Alice generates a payment disclosure and provides it to Bob, who verifies the payment was made. - -If Bob is a bad merchant, Alice can present the payment disclosure to a third party to validate that payment was indeed made. - -### Solution - -A payment disclosure can be generated for any output of a JoinSplit using the RPC call: - - z_getpaymentdisclosure txid js_index output_index (message) - -An optional message can be supplied. This could be used for a refund address or some other reference, as currently it is not common practice to (ahead of time) include a refund address in the memo field when making a payment. - -To validate a payment disclosure, the following RPC call can be used: - - z_validatepaymentdisclosure hexdata - -### Example - -Generate a payment disclosure for the first joinsplit, second output (index starts from zero): - - hush-cli z_getpaymentdisclosure 79189528d611e811a1c7bb0358dd31343033d14b4c1e998d7c4799c40f8b652b 0 1 "Hello" - -This returns a payment disclosure in the form of a hex string: - - 706462ff000a3722aafa8190cdf9710bfad6da2af6d3a74262c1fc96ad47df814b0cd5641c2b658b0fc499477c8d991e4c4bd133303431dd5803bbc7a111e811d6289518790000000000000000017e861adb829d8cb1cbcf6330b8c2e25fb0d08041a67a857815a136f0227f8a5342bce5b3c0d894e2983000eb594702d3c1580817d0374e15078528e56bb6f80c0548656c6c6f59a7085395c9e706d82afe3157c54ad4ae5bf144fcc774a8d9c921c58471402019c156ec5641e2173c4fb6467df5f28530dc4636fa71f4d0e48fc5c560fac500 - -To validate the payment disclosure: - - hush-cli z_validatepaymentdisclosure HEXDATA - -This returns data related to the payment and the payment disclosure: - - { - "txid": "79189528d611e811a1c7bb0358dd31343033d14b4c1e998d7c4799c40f8b652b", - "jsIndex": 0, - "outputIndex": 1, - "version": 0, - "onetimePrivKey": "1c64d50c4b81df47ad96fcc16242a7d3f62adad6fa0b71f9cd9081faaa22370a", - "message": "Hello", - "joinSplitPubKey": "d1c465d16166b602992479acfac18e87dc18065f6cefde6a002e70bc371b9faf", - "signatureVerified": true, - "paymentAddress": "ztaZJXy8iX8nrk2ytXKDBoTWqPkhQcj6E2ifARnD3wfkFwsxXs5SoX7NGmrjkzSiSKn8VtLHTJae48vX5NakvmDhtGNY5eb", - "memo": "f600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "value": 12.49900000, - "commitmentMatch": true, - "valid": true - } - -The `signatureVerified` field confirms that the payment disclosure was generated and signed with the joinSplitPrivKey, which should only be known by the node generating and sending the transaction 7918...652b in question. - -### Where is the data stored? - -For all nodes, payment disclosure does not touch `wallet.dat` in any way. - -For nodes that only validate payment disclosures, no data is stored locally. - -For nodes that generate payment disclosures, a LevelDB database is created in the node's datadir. For most users, this would be in the folder: - - $HOME/.zcash/paymentdisclosure - -If you decide you don't want to use payment disclosure, it is safe to shut down your node and delete the database folder. - -### Security Properties - -Please consult the work-in-progress ZIP for details about the protocol, security properties and caveats. - -### Reminder - -Feedback is most welcome! - -This is an experimental feature so there are no guarantees that the protocol, database format, RPC interface etc. will remain the same in the future. - -### Notes - -Currently there is no user friendly way to help senders identify which joinsplit output index maps to a given payment they made. It is possible to construct this from `debug.log`. Ideas and feedback are most welcome on how to improve the user experience. diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index a23f2908d..94429cb7f 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -17,7 +17,6 @@ testScripts=( 'dpow.py' 'dpowconfs.py' 'ac_private.py' - 'paymentdisclosure.py' 'prioritisetransaction.py' 'wallet_treestate.py' 'wallet_anchorfork.py' diff --git a/qa/rpc-tests/paymentdisclosure.py b/qa/rpc-tests/paymentdisclosure.py deleted file mode 100755 index 48d4712a9..000000000 --- a/qa/rpc-tests/paymentdisclosure.py +++ /dev/null @@ -1,215 +0,0 @@ -#!/usr/bin/env python2 -# Copyright (c) 2017 The Zcash developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal, initialize_chain_clean, \ - start_node, connect_nodes_bi, wait_and_assert_operationid_status - -from decimal import Decimal - -class PaymentDisclosureTest (BitcoinTestFramework): - - def setup_chain(self): - print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 4) - - def setup_network(self, split=False): - args = ['-debug=zrpcunsafe,paymentdisclosure', '-experimentalfeatures', '-paymentdisclosure', '-txindex=1'] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.nodes.append(start_node(1, self.options.tmpdir, args)) - # node 2 does not enable payment disclosure - args2 = ['-debug=zrpcunsafe', '-experimentalfeatures', '-txindex=1'] - self.nodes.append(start_node(2, self.options.tmpdir, args2)) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() - - def run_test (self): - print "Mining blocks..." - - self.nodes[0].generate(4) - walletinfo = self.nodes[0].getwalletinfo() - assert_equal(walletinfo['immature_balance'], 40) - assert_equal(walletinfo['balance'], 0) - self.sync_all() - self.nodes[2].generate(3) - self.sync_all() - self.nodes[1].generate(101) - self.sync_all() - assert_equal(self.nodes[0].getbalance(), 40) - assert_equal(self.nodes[1].getbalance(), 10) - assert_equal(self.nodes[2].getbalance(), 30) - - mytaddr = self.nodes[0].getnewaddress() - myzaddr = self.nodes[0].z_getnewaddress() - - # Check that Node 2 has payment disclosure disabled. - try: - self.nodes[2].z_getpaymentdisclosure("invalidtxid", 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("payment disclosure is disabled" in errorString) - - # Check that Node 0 returns an error for an unknown txid - try: - self.nodes[0].z_getpaymentdisclosure("invalidtxid", 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("No information available about transaction" in errorString) - - # Shield coinbase utxos from node 0 of value 40, standard fee of 0.00010000 - recipients = [{"address":myzaddr, "amount":Decimal('40.0')-Decimal('0.0001')}] - myopid = self.nodes[0].z_sendmany(mytaddr, recipients) - txid = wait_and_assert_operationid_status(self.nodes[0], myopid) - - # Check the tx has joinsplits - assert( len(self.nodes[0].getrawtransaction("" + txid, 1)["vjoinsplit"]) > 0 ) - - # Sync mempools - self.sync_all() - - # Confirm that you can't create a payment disclosure for an unconfirmed tx - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction has not been confirmed yet" in errorString) - - try: - self.nodes[1].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction has not been confirmed yet" in errorString) - - # Mine tx - self.nodes[0].generate(1) - self.sync_all() - - # Confirm that Node 1 cannot create a payment disclosure for a transaction which does not impact its wallet - try: - self.nodes[1].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction does not belong to the wallet" in errorString) - - # Check that an invalid joinsplit index is rejected - try: - self.nodes[0].z_getpaymentdisclosure(txid, 1, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Invalid js_index" in errorString) - - try: - self.nodes[0].z_getpaymentdisclosure(txid, -1, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Invalid js_index" in errorString) - - # Check that an invalid output index is rejected - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, 2) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Invalid output_index" in errorString) - - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, -1) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Invalid output_index" in errorString) - - # Ask Node 0 to create and validate a payment disclosure for output 0 - message = "Here is proof of my payment!" - pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 0, message) - result = self.nodes[0].z_validatepaymentdisclosure(pd) - assert(result["valid"]) - output_value_sum = Decimal(result["value"]) - - # Ask Node 1 to confirm the payment disclosure is valid - result = self.nodes[1].z_validatepaymentdisclosure(pd) - assert(result["valid"]) - assert_equal(result["message"], message) - assert_equal(result["value"], output_value_sum) - - # Confirm that payment disclosure begins with prefix zpd: - assert(pd.startswith("zpd:")) - - # Confirm that payment disclosure without prefix zpd: fails validation - try: - self.nodes[1].z_validatepaymentdisclosure(pd[4:]) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("payment disclosure prefix not found" in errorString) - - # Check that total value of output index 0 and index 1 should equal shielding amount of 40 less standard fee. - pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 1) - result = self.nodes[0].z_validatepaymentdisclosure(pd) - output_value_sum += Decimal(result["value"]) - assert_equal(output_value_sum, Decimal('39.99990000')) - - # Create a z->z transaction, sending shielded funds from node 0 to node 1 - node1zaddr = self.nodes[1].z_getnewaddress() - recipients = [{"address":node1zaddr, "amount":Decimal('1')}] - myopid = self.nodes[0].z_sendmany(myzaddr, recipients) - txid = wait_and_assert_operationid_status(self.nodes[0], myopid) - self.sync_all() - self.nodes[0].generate(1) - self.sync_all() - - # Confirm that Node 0 can create a valid payment disclosure - pd = self.nodes[0].z_getpaymentdisclosure(txid, 0, 0, "a message of your choice") - result = self.nodes[0].z_validatepaymentdisclosure(pd) - assert(result["valid"]) - - # Confirm that Node 1, even as recipient of shielded funds, cannot create a payment disclosure - # as the transaction was created by Node 0 and Node 1's payment disclosure database does not - # contain the necessary data to do so, where the data would only have been available on Node 0 - # when executing z_shieldcoinbase. - try: - self.nodes[1].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Could not find payment disclosure info for the given joinsplit output" in errorString) - - # Payment disclosures cannot be created for transparent transactions. - txid = self.nodes[2].sendtoaddress(mytaddr, 1.0) - self.sync_all() - - # No matter the type of transaction, if it has not been confirmed, it is ignored. - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction has not been confirmed yet" in errorString) - - self.nodes[0].generate(1) - self.sync_all() - - # Confirm that a payment disclosure can only be generated for a shielded transaction. - try: - self.nodes[0].z_getpaymentdisclosure(txid, 0, 0) - assert(False) - except JSONRPCException as e: - errorString = e.error['message'] - assert("Transaction is not a shielded transaction" in errorString) - -if __name__ == '__main__': - PaymentDisclosureTest().main() diff --git a/src/Makefile.am b/src/Makefile.am index 2d2d7a691..ab04c24bc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -181,8 +181,6 @@ BITCOIN_CORE_H = \ netbase.h \ notaries_staked.h \ noui.h \ - paymentdisclosure.h \ - paymentdisclosuredb.h \ policy/fees.h \ pow.h \ prevector.h \ @@ -303,8 +301,6 @@ libbitcoin_server_a_SOURCES = \ notaries_staked.cpp \ noui.cpp \ notarisationdb.cpp \ - paymentdisclosure.cpp \ - paymentdisclosuredb.cpp \ policy/fees.cpp \ pow.cpp \ rest.cpp \ @@ -355,10 +351,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/asyncrpcoperation_shieldcoinbase.cpp \ wallet/crypter.cpp \ wallet/db.cpp \ - paymentdisclosure.cpp \ - paymentdisclosuredb.cpp \ transaction_builder.cpp \ - wallet/rpcdisclosure.cpp \ wallet/rpcdump.cpp \ cc/CCtokens.cpp \ cc/CCassetsCore.cpp \ diff --git a/src/gtest/test_paymentdisclosure.cpp b/src/gtest/test_paymentdisclosure.cpp deleted file mode 100644 index c166cdbe1..000000000 --- a/src/gtest/test_paymentdisclosure.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include - -#include "main.h" -#include "utilmoneystr.h" -#include "chainparams.h" -#include "utilstrencodings.h" -#include "zcash/Address.hpp" -#include "wallet/wallet.h" -#include "amount.h" - -#include -#include -#include -#include -#include -#include -#include -#include "util.h" - -#include "paymentdisclosure.h" -#include "paymentdisclosuredb.h" - -#include "sodium.h" - -#include -#include -#include - -using namespace std; - -/* - To run tests: - ./zcash-gtest --gtest_filter="paymentdisclosure.*" - - Note: As an experimental feature, writing your own tests may require option flags to be set. - mapArgs["-experimentalfeatures"] = true; - mapArgs["-paymentdisclosure"] = true; -*/ - -#define NUM_TRIES 10000 - -#define DUMP_DATABASE_TO_STDOUT false - -static boost::uuids::random_generator uuidgen; - -static uint256 random_uint256() -{ - uint256 ret; - randombytes_buf(ret.begin(), 32); - return ret; -} - -// Subclass of PaymentDisclosureDB to add debugging methods -class PaymentDisclosureDBTest : public PaymentDisclosureDB { -public: - PaymentDisclosureDBTest(const boost::filesystem::path& dbPath) : PaymentDisclosureDB(dbPath) {} - - void DebugDumpAllStdout() { - ASSERT_NE(db, nullptr); - std::lock_guard guard(lock_); - - // Iterate over each item in the database and print them - leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions()); - - for (it->SeekToFirst(); it->Valid(); it->Next()) { - cout << it->key().ToString() << " : "; - // << it->value().ToString() << endl; - try { - std::string strValue = it->value().ToString(); - PaymentDisclosureInfo info; - CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION); - ssValue >> info; - cout << info.ToString() << std::endl; - } catch (const std::exception& e) { - cout << e.what() << std::endl; - } - } - - if (false == it->status().ok()) { - cerr << "An error was found iterating over the database" << endl; - cerr << it->status().ToString() << endl; - } - - delete it; - } -}; - - - -// This test creates random payment disclosure blobs and checks that they can be -// 1. inserted and retrieved from a database -// 2. serialized and deserialized without corruption -// Note that the zpd: prefix is not part of the payment disclosure blob itself. It is only -// used as convention to improve the user experience when sharing payment disclosure blobs. -TEST(paymentdisclosure, mainnet) { - SelectParams(CBaseChainParams::MAIN); - - boost::filesystem::path pathTemp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); - boost::filesystem::create_directories(pathTemp); - mapArgs["-datadir"] = pathTemp.string(); - - std::cout << "Test payment disclosure database created in folder: " << pathTemp.string() << std::endl; - - PaymentDisclosureDBTest mydb(pathTemp); - - for (int i=0; i vch(&buffer[0], &buffer[0] + 32); - uint256 joinSplitPrivKey = uint256(vch); - - // Create payment disclosure key and info data to store in test database - size_t js = random_uint256().GetCheapHash() % std::numeric_limits::max(); - uint8_t n = random_uint256().GetCheapHash() % std::numeric_limits::max(); - PaymentDisclosureKey key { random_uint256(), js, n}; - PaymentDisclosureInfo info; - info.esk = random_uint256(); - info.joinSplitPrivKey = joinSplitPrivKey; - info.zaddr = libzcash::SproutSpendingKey::random().address(); - ASSERT_TRUE(mydb.Put(key, info)); - - // Retrieve info from test database into new local variable and test it matches - PaymentDisclosureInfo info2; - ASSERT_TRUE(mydb.Get(key, info2)); - ASSERT_EQ(info, info2); - - // Modify this local variable and confirm it no longer matches - info2.esk = random_uint256(); - info2.joinSplitPrivKey = random_uint256(); - info2.zaddr = libzcash::SproutSpendingKey::random().address(); - ASSERT_NE(info, info2); - - // Using the payment info object, let's create a dummy payload - PaymentDisclosurePayload payload; - payload.version = PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL; - payload.esk = info.esk; - payload.txid = key.hash; - payload.js = key.js; - payload.n = key.n; - payload.message = "random-" + boost::uuids::to_string(uuidgen()); // random message - payload.zaddr = info.zaddr; - - // Serialize and hash the payload to generate a signature - uint256 dataToBeSigned = SerializeHash(payload, SER_GETHASH, 0); - - // Compute the payload signature - unsigned char payloadSig[64]; - if (!(crypto_sign_detached(&payloadSig[0], NULL, - dataToBeSigned.begin(), 32, - &buffer[0] // buffer containing both private and public key required - ) == 0)) - { - throw std::runtime_error("crypto_sign_detached failed"); - } - - // Sanity check - if (!(crypto_sign_verify_detached(&payloadSig[0], - dataToBeSigned.begin(), 32, - joinSplitPubKey.begin() - ) == 0)) - { - throw std::runtime_error("crypto_sign_verify_detached failed"); - } - - // Convert signature buffer to boost array - std::array arrayPayloadSig; - memcpy(arrayPayloadSig.data(), &payloadSig[0], 64); - - // Payment disclosure blob to pass around - PaymentDisclosure pd = {payload, arrayPayloadSig}; - - // Test payment disclosure constructors - PaymentDisclosure pd2(payload, arrayPayloadSig); - ASSERT_EQ(pd, pd2); - PaymentDisclosure pd3(joinSplitPubKey, key, info, payload.message); - ASSERT_EQ(pd, pd3); - - // Verify serialization and deserialization works - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pd; - std::string ssHexString = HexStr(ss.begin(), ss.end()); - - PaymentDisclosure pdTmp; - CDataStream ssTmp(ParseHex(ssHexString), SER_NETWORK, PROTOCOL_VERSION); - ssTmp >> pdTmp; - ASSERT_EQ(pd, pdTmp); - - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << pdTmp; - std::string ss2HexString = HexStr(ss2.begin(), ss2.end()); - ASSERT_EQ(ssHexString, ss2HexString); - - // Verify marker - ASSERT_EQ(pd.payload.marker, PAYMENT_DISCLOSURE_PAYLOAD_MAGIC_BYTES); - ASSERT_EQ(pdTmp.payload.marker, PAYMENT_DISCLOSURE_PAYLOAD_MAGIC_BYTES); - ASSERT_EQ(0, ssHexString.find("706462ff")); // Little endian encoding of PAYMENT_DISCLOSURE_PAYLOAD_MAGIC_BYTES value - - // Sanity check - PaymentDisclosure pdDummy; - ASSERT_NE(pd, pdDummy); - } - -#if DUMP_DATABASE_TO_STDOUT == true - mydb.DebugDumpAllStdout(); -#endif -} diff --git a/src/paymentdisclosure.cpp b/src/paymentdisclosure.cpp deleted file mode 100644 index eb55a0536..000000000 --- a/src/paymentdisclosure.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2017 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "paymentdisclosure.h" - -#include "key_io.h" -#include "util.h" - -std::string PaymentDisclosureInfo::ToString() const { - return strprintf("PaymentDisclosureInfo(version=%d, esk=%s, joinSplitPrivKey=, address=%s)", - version, esk.ToString(), EncodePaymentAddress(zaddr)); -} - -std::string PaymentDisclosure::ToString() const { - std::string s = HexStr(payloadSig.begin(), payloadSig.end()); - return strprintf("PaymentDisclosure(payload=%s, payloadSig=%s)", payload.ToString(), s); -} - -std::string PaymentDisclosurePayload::ToString() const { - return strprintf("PaymentDisclosurePayload(version=%d, esk=%s, txid=%s, js=%d, n=%d, address=%s, message=%s)", - version, esk.ToString(), txid.ToString(), js, n, EncodePaymentAddress(zaddr), message); -} - -PaymentDisclosure::PaymentDisclosure(const uint256 &joinSplitPubKey, const PaymentDisclosureKey &key, const PaymentDisclosureInfo &info, const std::string &message) -{ - // Populate payload member variable - payload.version = info.version; // experimental = 0, production = 1 etc. - payload.esk = info.esk; - payload.txid = key.hash; - payload.js = key.js; - payload.n = key.n; - payload.zaddr = info.zaddr; - payload.message = message; - - // Serialize and hash the payload to generate a signature - uint256 dataToBeSigned = SerializeHash(payload, SER_GETHASH, 0); - - LogPrint("paymentdisclosure", "Payment Disclosure: signing raw payload = %s\n", dataToBeSigned.ToString()); - - // Prepare buffer to store ed25519 key pair in libsodium-compatible format - unsigned char bufferKeyPair[64]; - memcpy(&bufferKeyPair[0], info.joinSplitPrivKey.begin(), 32); - memcpy(&bufferKeyPair[32], joinSplitPubKey.begin(), 32); - - // Compute payload signature member variable - if (!(crypto_sign_detached(payloadSig.data(), NULL, - dataToBeSigned.begin(), 32, - &bufferKeyPair[0] - ) == 0)) - { - throw std::runtime_error("crypto_sign_detached failed"); - } - - // Sanity check - if (!(crypto_sign_verify_detached(payloadSig.data(), - dataToBeSigned.begin(), 32, - joinSplitPubKey.begin()) == 0)) - { - throw std::runtime_error("crypto_sign_verify_detached failed"); - } - - std::string sigString = HexStr(payloadSig.data(), payloadSig.data() + payloadSig.size()); - LogPrint("paymentdisclosure", "Payment Disclosure: signature = %s\n", sigString); -} diff --git a/src/paymentdisclosure.h b/src/paymentdisclosure.h deleted file mode 100644 index 5c3a20c33..000000000 --- a/src/paymentdisclosure.h +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2017 The Zcash developers -// Copyright (c) 2019-2020 The Hush developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef ZCASH_PAYMENTDISCLOSURE_H -#define ZCASH_PAYMENTDISCLOSURE_H - -#include "uint256.h" -#include "clientversion.h" -#include "serialize.h" -#include "streams.h" -#include "version.h" - -// For JSOutPoint -#include "wallet/wallet.h" - -#include -#include -#include - - -// Ensure that the two different protocol messages, payment disclosure blobs and transactions, -// which are signed with the same key, joinSplitPrivKey, have disjoint encodings such that an -// encoding from one context will be rejected in the other. We know that the set of valid -// transaction versions is currently ({1..INT32_MAX}) so we will use a negative value for -// payment disclosure of -10328976 which in hex is 0xFF626470. Serialization is in little endian -// format, so a payment disclosure hex string begins 706462FF, which in ISO-8859-1 is "pdbÿ". -#define PAYMENT_DISCLOSURE_PAYLOAD_MAGIC_BYTES -10328976 - -#define PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL 0 - -#define PAYMENT_DISCLOSURE_BLOB_STRING_PREFIX "zpd:" - -typedef JSOutPoint PaymentDisclosureKey; - -struct PaymentDisclosureInfo { - uint8_t version; // 0 = experimental, 1 = first production version, etc. - uint256 esk; // zcash/NoteEncryption.cpp - uint256 joinSplitPrivKey; // primitives/transaction.h - // ed25519 - not tied to implementation e.g. libsodium, see ed25519 rfc - - libzcash::SproutPaymentAddress zaddr; - - PaymentDisclosureInfo() : version(PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL) { - } - - PaymentDisclosureInfo(uint8_t v, uint256 esk, uint256 key, libzcash::SproutPaymentAddress zaddr) : version(v), esk(esk), joinSplitPrivKey(key), zaddr(zaddr) { } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(version); - READWRITE(esk); - READWRITE(joinSplitPrivKey); - READWRITE(zaddr); - } - - std::string ToString() const; - - friend bool operator==(const PaymentDisclosureInfo& a, const PaymentDisclosureInfo& b) { - return (a.version == b.version && a.esk == b.esk && a.joinSplitPrivKey == b.joinSplitPrivKey && a.zaddr == b.zaddr); - } - - friend bool operator!=(const PaymentDisclosureInfo& a, const PaymentDisclosureInfo& b) { - return !(a == b); - } - -}; - - -struct PaymentDisclosurePayload { - int32_t marker = PAYMENT_DISCLOSURE_PAYLOAD_MAGIC_BYTES; // to be disjoint from transaction encoding - uint8_t version; // 0 = experimental, 1 = first production version, etc. - uint256 esk; // zcash/NoteEncryption.cpp - uint256 txid; // primitives/transaction.h - uint64_t js; // Index into CTransaction.vjoinsplit - uint8_t n; // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS - libzcash::SproutPaymentAddress zaddr; // zcash/Address.hpp - std::string message; // parameter to RPC call - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(marker); - READWRITE(version); - READWRITE(esk); - READWRITE(txid); - READWRITE(js); - READWRITE(n); - READWRITE(zaddr); - READWRITE(message); - } - - std::string ToString() const; - - friend bool operator==(const PaymentDisclosurePayload& a, const PaymentDisclosurePayload& b) { - return ( - a.version == b.version && - a.esk == b.esk && - a.txid == b.txid && - a.js == b.js && - a.n == b.n && - a.zaddr == b.zaddr && - a.message == b.message - ); - } - - friend bool operator!=(const PaymentDisclosurePayload& a, const PaymentDisclosurePayload& b) { - return !(a == b); - } -}; - -struct PaymentDisclosure { - PaymentDisclosurePayload payload; - std::array payloadSig; - // We use boost array because serialize doesn't like char buffer, otherwise we could do: unsigned char payloadSig[64]; - - PaymentDisclosure() {}; - PaymentDisclosure(const PaymentDisclosurePayload payload, const std::array sig) : payload(payload), payloadSig(sig) {}; - PaymentDisclosure(const uint256& joinSplitPubKey, const PaymentDisclosureKey& key, const PaymentDisclosureInfo& info, const std::string& message); - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(payload); - READWRITE(payloadSig); - } - - std::string ToString() const; - - friend bool operator==(const PaymentDisclosure& a, const PaymentDisclosure& b) { - return (a.payload == b.payload && a.payloadSig == b.payloadSig); - } - - friend bool operator!=(const PaymentDisclosure& a, const PaymentDisclosure& b) { - return !(a == b); - } -}; - - - -typedef std::pair PaymentDisclosureKeyInfo; - - -#endif // ZCASH_PAYMENTDISCLOSURE_H diff --git a/src/paymentdisclosuredb.cpp b/src/paymentdisclosuredb.cpp deleted file mode 100644 index 8840dcda0..000000000 --- a/src/paymentdisclosuredb.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2017 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "paymentdisclosuredb.h" - -#include "util.h" -#include "dbwrapper.h" - -#include - -using namespace std; - -static boost::filesystem::path emptyPath; - -/** - * Static method to return the shared/default payment disclosure database. - */ -shared_ptr PaymentDisclosureDB::sharedInstance() { - // Thread-safe in C++11 and gcc 4.3 - static shared_ptr ptr = std::make_shared(); - return ptr; -} - -// C++11 delegated constructor -PaymentDisclosureDB::PaymentDisclosureDB() : PaymentDisclosureDB(emptyPath) { -} - -PaymentDisclosureDB::PaymentDisclosureDB(const boost::filesystem::path& dbPath) { - boost::filesystem::path path(dbPath); - if (path.empty()) { - path = GetDataDir() / "paymentdisclosure"; - LogPrintf("PaymentDisclosure: using default path for database: %s\n", path.string()); - } else { - LogPrintf("PaymentDisclosure: using custom path for database: %s\n", path.string()); - } - - TryCreateDirectory(path); - options.create_if_missing = true; - leveldb::Status status = leveldb::DB::Open(options, path.string(), &db); - dbwrapper_private::HandleError(status); // throws exception - LogPrintf("PaymentDisclosure: Opened LevelDB successfully\n"); -} - -PaymentDisclosureDB::~PaymentDisclosureDB() { - if (db != nullptr) { - delete db; - } -} - -bool PaymentDisclosureDB::Put(const PaymentDisclosureKey& key, const PaymentDisclosureInfo& info) -{ - if (db == nullptr) { - return false; - } - - std::lock_guard guard(lock_); - - CDataStream ssValue(SER_DISK, CLIENT_VERSION); - ssValue.reserve(GetSerializeSize(ssValue, info)); - ssValue << info; - leveldb::Slice slice(&ssValue[0], ssValue.size()); - - leveldb::Status status = db->Put(writeOptions, key.ToString(), slice); - dbwrapper_private::HandleError(status); - return true; -} - -bool PaymentDisclosureDB::Get(const PaymentDisclosureKey& key, PaymentDisclosureInfo& info) -{ - if (db == nullptr) { - return false; - } - - std::lock_guard guard(lock_); - - std::string strValue; - leveldb::Status status = db->Get(readOptions, key.ToString(), &strValue); - if (!status.ok()) { - if (status.IsNotFound()) - return false; - LogPrintf("PaymentDisclosure: LevelDB read failure: %s\n", status.ToString()); - dbwrapper_private::HandleError(status); - } - - try { - CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION); - ssValue >> info; - } catch (const std::exception&) { - return false; - } - return true; -} diff --git a/src/paymentdisclosuredb.h b/src/paymentdisclosuredb.h deleted file mode 100644 index 9352cac8f..000000000 --- a/src/paymentdisclosuredb.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2017 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef ZCASH_PAYMENTDISCLOSUREDB_H -#define ZCASH_PAYMENTDISCLOSUREDB_H - -#include "paymentdisclosure.h" - -#include -#include -#include -#include -#include - -#include - -#include - - -class PaymentDisclosureDB -{ -protected: - leveldb::DB* db = nullptr; - leveldb::Options options; - leveldb::ReadOptions readOptions; - leveldb::WriteOptions writeOptions; - mutable std::mutex lock_; - -public: - static std::shared_ptr sharedInstance(); - - PaymentDisclosureDB(); - PaymentDisclosureDB(const boost::filesystem::path& dbPath); - ~PaymentDisclosureDB(); - - bool Put(const PaymentDisclosureKey& key, const PaymentDisclosureInfo& info); - bool Get(const PaymentDisclosureKey& key, PaymentDisclosureInfo& info); -}; - - -#endif // ZCASH_PAYMENTDISCLOSUREDB_H diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index ed4efc014..4e47a5a2d 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -133,9 +133,6 @@ saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), context // Lock UTXOs lock_utxos(); lock_notes(); - - // Enable payment disclosure if requested - paymentDisclosureMode = fExperimentalMode && GetBoolArg("-paymentdisclosure", true); } AsyncRPCOperation_mergetoaddress::~AsyncRPCOperation_mergetoaddress() @@ -210,25 +207,10 @@ void AsyncRPCOperation_mergetoaddress::main() unlock_utxos(); // clean up unlock_notes(); // clean up - - // !!! Payment disclosure START - if (success && paymentDisclosureMode && paymentDisclosureData_.size() > 0) { - uint256 txidhash = tx_.GetHash(); - std::shared_ptr db = PaymentDisclosureDB::sharedInstance(); - for (PaymentDisclosureKeyInfo p : paymentDisclosureData_) { - p.first.hash = txidhash; - if (!db->Put(p.first, p.second)) { - LogPrint("paymentdisclosure", "%s: Payment Disclosure: Error writing entry to database for key %s\n", getId(), p.first.ToString()); - } else { - LogPrint("paymentdisclosure", "%s: Payment Disclosure: Successfully added entry to database for key %s\n", getId(), p.first.ToString()); - } - } - } - // !!! Payment disclosure END } // Notes: -// 1. #1359 Currently there is no limit set on the number of joinsplits, so size of tx could be invalid. +// 1. #1359 Currently there is no limit set on the number of inputs+outputs, so size of tx could be invalid. // 2. #1277 Spendable notes are not locked, so an operation running in parallel could also try to use them. bool AsyncRPCOperation_mergetoaddress::main_impl() { diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index be49baff0..4876921db 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -1,4 +1,6 @@ // Copyright (c) 2017 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers + // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,7 +24,6 @@ #include "amount.h" #include "asyncrpcoperation.h" -#include "paymentdisclosure.h" #include "primitives/transaction.h" #include "transaction_builder.h" #include "wallet.h" @@ -93,8 +94,6 @@ public: bool testmode = false; // Set to true to disable sending txs and generating proofs - bool paymentDisclosureMode = true; // Set to true to save esk for encrypted notes in payment disclosure database. - private: friend class TEST_FRIEND_AsyncRPCOperation_mergetoaddress; // class for unit testing @@ -148,8 +147,6 @@ private: void unlock_notes(); - // payment disclosure! - std::vector paymentDisclosureData_; }; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index a1ecb296d..31f987bef 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -211,25 +211,10 @@ void AsyncRPCOperation_sendmany::main() { s += strprintf(", error=%s)\n", getErrorMessage()); } LogPrintf("%s",s); - - // !!! Payment disclosure START - if (success && paymentDisclosureMode && paymentDisclosureData_.size()>0) { - uint256 txidhash = tx_.GetHash(); - std::shared_ptr db = PaymentDisclosureDB::sharedInstance(); - for (PaymentDisclosureKeyInfo p : paymentDisclosureData_) { - p.first.hash = txidhash; - if (!db->Put(p.first, p.second)) { - LogPrint("paymentdisclosure", "%s: Payment Disclosure: Error writing entry to database for key %s\n", getId(), p.first.ToString()); - } else { - LogPrint("paymentdisclosure", "%s: Payment Disclosure: Successfully added entry to database for key %s\n", getId(), p.first.ToString()); - } - } - } - // !!! Payment disclosure END } // Notes: -// 1. #1159 Currently there is no limit set on the number of joinsplits, so size of tx could be invalid. +// 1. #1159 Currently there is no limit set on the number of shielded spends, so size of tx could be invalid. // 2. #1360 Note selection is not optimal // 3. #1277 Spendable notes are not locked, so an operation running in parallel could also try to use them bool AsyncRPCOperation_sendmany::main_impl() { diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index 8e39f341a..0b803ddd9 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -1,4 +1,5 @@ // Copyright (c) 2016 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -27,7 +28,6 @@ #include "zcash/JoinSplit.hpp" #include "zcash/Address.hpp" #include "wallet.h" -#include "paymentdisclosure.h" #include #include @@ -90,8 +90,6 @@ public: bool testmode = false; // Set to true to disable sending txs and generating proofs - bool paymentDisclosureMode = true; // Set to true to save esk for encrypted notes in payment disclosure database. - private: friend class TEST_FRIEND_AsyncRPCOperation_sendmany; // class for unit testing @@ -143,9 +141,6 @@ private: uint256 anchor); void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error - - // payment disclosure! - std::vector paymentDisclosureData_; }; diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index 5db0ca51b..de56ba3bc 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -48,9 +48,6 @@ #include "asyncrpcoperation_shieldcoinbase.h" -#include "paymentdisclosure.h" -#include "paymentdisclosuredb.h" - using namespace libzcash; extern uint64_t ASSETCHAINS_TIMELOCKGTE; @@ -108,8 +105,6 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase( // Lock UTXOs lock_utxos(); - // Enable payment disclosure if requested - paymentDisclosureMode = fExperimentalMode && GetBoolArg("-paymentdisclosure", true); } AsyncRPCOperation_shieldcoinbase::~AsyncRPCOperation_shieldcoinbase() { @@ -181,20 +176,6 @@ void AsyncRPCOperation_shieldcoinbase::main() { unlock_utxos(); // clean up - // !!! Payment disclosure START - if (success && paymentDisclosureMode && paymentDisclosureData_.size()>0) { - uint256 txidhash = tx_.GetHash(); - std::shared_ptr db = PaymentDisclosureDB::sharedInstance(); - for (PaymentDisclosureKeyInfo p : paymentDisclosureData_) { - p.first.hash = txidhash; - if (!db->Put(p.first, p.second)) { - LogPrint("paymentdisclosure", "%s: Payment Disclosure: Error writing entry to database for key %s\n", getId(), p.first.ToString()); - } else { - LogPrint("paymentdisclosure", "%s: Payment Disclosure: Successfully added entry to database for key %s\n", getId(), p.first.ToString()); - } - } - } - // !!! Payment disclosure END } bool AsyncRPCOperation_shieldcoinbase::main_impl() { diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.h b/src/wallet/asyncrpcoperation_shieldcoinbase.h index db4fb83af..3eb1a6cfc 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.h +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.h @@ -34,8 +34,6 @@ #include -#include "paymentdisclosure.h" - // Default transaction fee if caller does not specify one. #define SHIELD_COINBASE_DEFAULT_MINERS_FEE 10000 @@ -81,8 +79,6 @@ public: bool testmode = false; // Set to true to disable sending txs and generating proofs bool cheatSpend = false; // set when this is shielding a cheating coinbase - bool paymentDisclosureMode = true; // Set to true to save esk for encrypted notes in payment disclosure database. - private: friend class ShieldToAddress; friend class TEST_FRIEND_AsyncRPCOperation_shieldcoinbase; // class for unit testing @@ -110,9 +106,6 @@ private: void lock_utxos(); void unlock_utxos(); - - // payment disclosure! - std::vector paymentDisclosureData_; }; class ShieldToAddress : public boost::static_visitor diff --git a/src/wallet/rpcdisclosure.cpp b/src/wallet/rpcdisclosure.cpp deleted file mode 100644 index 918e70cbc..000000000 --- a/src/wallet/rpcdisclosure.cpp +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright (c) 2017 The Zcash developers -// Copyright (c) 2019-2020 The Hush developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - -#include "rpc/server.h" -#include "init.h" -#include "key_io.h" -#include "main.h" -#include "script/script.h" -#include "script/standard.h" -#include "sync.h" -#include "util.h" -#include "utiltime.h" -#include "wallet.h" - -#include -#include - -#include -#include - -#include - -#include "paymentdisclosure.h" -#include "paymentdisclosuredb.h" - -#include "zcash/Note.hpp" -#include "zcash/NoteEncryption.hpp" - -using namespace std; -using namespace libzcash; - -// Function declaration for function implemented in wallet/rpcwallet.cpp -bool EnsureWalletIsAvailable(bool avoidException); - -/** - * RPC call to generate a payment disclosure - */ -UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (!EnsureWalletIsAvailable(fHelp)) - return NullUniValue; - - string enableArg = "paymentdisclosure"; - auto fEnablePaymentDisclosure = fExperimentalMode && GetBoolArg("-" + enableArg, true); - string strPaymentDisclosureDisabledMsg = ""; - if (!fEnablePaymentDisclosure) { - strPaymentDisclosureDisabledMsg = experimentalDisabledHelpMsg("z_getpaymentdisclosure", enableArg); - } - - if (fHelp || params.size() < 3 || params.size() > 4 ) - throw runtime_error( - "z_getpaymentdisclosure \"txid\" \"js_index\" \"output_index\" (\"message\") \n" - "\nGenerate a payment disclosure for a given joinsplit output.\n" - "\nEXPERIMENTAL FEATURE\n" - + strPaymentDisclosureDisabledMsg + - "\nArguments:\n" - "1. \"txid\" (string, required) \n" - "2. \"js_index\" (string, required) \n" - "3. \"output_index\" (string, required) \n" - "4. \"message\" (string, optional) \n" - "\nResult:\n" - "\"paymentdisclosure\" (string) Hex data string, with \"zpd:\" prefix.\n" - "\nExamples:\n" - + HelpExampleCli("z_getpaymentdisclosure", "96f12882450429324d5f3b48630e3168220e49ab7b0f066e5c2935a6b88bb0f2 0 0 \"refund\"") - + HelpExampleRpc("z_getpaymentdisclosure", "\"96f12882450429324d5f3b48630e3168220e49ab7b0f066e5c2935a6b88bb0f2\", 0, 0, \"refund\"") - ); - - if (!fEnablePaymentDisclosure) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error: payment disclosure is disabled."); - } - - LOCK2(cs_main, pwalletMain->cs_wallet); - - EnsureWalletIsUnlocked(); - - // Check wallet knows about txid - string txid = params[0].get_str(); - uint256 hash; - hash.SetHex(txid); - - CTransaction tx; - uint256 hashBlock; - - // Check txid has been seen - if (!GetTransaction(hash, tx, hashBlock, true)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); - } - - // Check tx has been confirmed - if (hashBlock.IsNull()) { - throw JSONRPCError(RPC_MISC_ERROR, "Transaction has not been confirmed yet"); - } - - // Check is mine - if (!pwalletMain->mapWallet.count(hash)) { - throw JSONRPCError(RPC_MISC_ERROR, "Transaction does not belong to the wallet"); - } - const CWalletTx& wtx = pwalletMain->mapWallet[hash]; - - // Check if shielded tx - if (wtx.vjoinsplit.empty()) { - throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not a shielded transaction"); - } - - // Check js_index - int js_index = params[1].get_int(); - if (js_index < 0 || js_index >= wtx.vjoinsplit.size()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid js_index"); - } - - // Check output_index - int output_index = params[2].get_int(); - if (output_index < 0 || output_index >= ZC_NUM_JS_OUTPUTS) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid output_index"); - } - - // Get message if it exists - string msg; - if (params.size() == 4) { - msg = params[3].get_str(); - } - - // Create PaymentDisclosureKey - PaymentDisclosureKey key = {hash, (size_t)js_index, (uint8_t)output_index }; - - // TODO: In future, perhaps init the DB in init.cpp - shared_ptr db = PaymentDisclosureDB::sharedInstance(); - PaymentDisclosureInfo info; - if (!db->Get(key, info)) { - throw JSONRPCError(RPC_DATABASE_ERROR, "Could not find payment disclosure info for the given joinsplit output"); - } - - PaymentDisclosure pd( wtx.joinSplitPubKey, key, info, msg ); - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pd; - string strHex = HexStr(ss.begin(), ss.end()); - return PAYMENT_DISCLOSURE_BLOB_STRING_PREFIX + strHex; -} - - - -/** - * RPC call to validate a payment disclosure data blob. - */ -UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk) -{ - if (!EnsureWalletIsAvailable(fHelp)) - return NullUniValue; - - string enableArg = "paymentdisclosure"; - auto fEnablePaymentDisclosure = fExperimentalMode && GetBoolArg("-" + enableArg, true); - string strPaymentDisclosureDisabledMsg = ""; - if (!fEnablePaymentDisclosure) { - strPaymentDisclosureDisabledMsg = experimentalDisabledHelpMsg("z_validatepaymentdisclosure", enableArg); - } - - if (fHelp || params.size() != 1) - throw runtime_error( - "z_validatepaymentdisclosure \"paymentdisclosure\"\n" - "\nValidates a payment disclosure.\n" - "\nEXPERIMENTAL FEATURE\n" - + strPaymentDisclosureDisabledMsg + - "\nArguments:\n" - "1. \"paymentdisclosure\" (string, required) Hex data string, with \"zpd:\" prefix.\n" - "\nExamples:\n" - + HelpExampleCli("z_validatepaymentdisclosure", "\"zpd:706462ff004c561a0447ba2ec51184e6c204...\"") - + HelpExampleRpc("z_validatepaymentdisclosure", "\"zpd:706462ff004c561a0447ba2ec51184e6c204...\"") - ); - - if (!fEnablePaymentDisclosure) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error: payment disclosure is disabled."); - } - - throw JSONRPCError(RPC_WALLET_ERROR, "Error: payment disclosures not implemented for Sapling yet"); - - LOCK2(cs_main, pwalletMain->cs_wallet); - - EnsureWalletIsUnlocked(); - - // Verify the payment disclosure input begins with "zpd:" prefix. - string strInput = params[0].get_str(); - size_t pos = strInput.find(PAYMENT_DISCLOSURE_BLOB_STRING_PREFIX); - if (pos != 0) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, payment disclosure prefix not found."); - } - string hexInput = strInput.substr(strlen(PAYMENT_DISCLOSURE_BLOB_STRING_PREFIX)); - if (!IsHex(hexInput)) - { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected payment disclosure data in hexadecimal format."); - } - - // Unserialize the payment disclosure data into an object - PaymentDisclosure pd; - CDataStream ss(ParseHex(hexInput), SER_NETWORK, PROTOCOL_VERSION); - try { - ss >> pd; - // too much data is ignored, but if not enough data, exception of type ios_base::failure is thrown, - // CBaseDataStream::read(): end of data: iostream error - } catch (const std::exception &e) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, payment disclosure data is malformed."); - } - - if (pd.payload.marker != PAYMENT_DISCLOSURE_PAYLOAD_MAGIC_BYTES) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, payment disclosure marker not found."); - } - - if (pd.payload.version != PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Payment disclosure version is unsupported."); - } - - uint256 hash = pd.payload.txid; - CTransaction tx; - uint256 hashBlock; - // Check if we have seen the transaction - if (!GetTransaction(hash, tx, hashBlock, true)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); - } - - // Check if the transaction has been confirmed - if (hashBlock.IsNull()) { - throw JSONRPCError(RPC_MISC_ERROR, "Transaction has not been confirmed yet"); - } - - // Check if shielded tx - if (tx.vjoinsplit.empty()) { - throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not a shielded transaction"); - } - - UniValue errs(UniValue::VARR); - UniValue o(UniValue::VOBJ); - o.push_back(Pair("txid", pd.payload.txid.ToString())); - - // Check js_index - if (pd.payload.js >= tx.vjoinsplit.size()) { - errs.push_back("Payment disclosure refers to an invalid joinsplit index"); - } - o.push_back(Pair("jsIndex", pd.payload.js)); - - if (pd.payload.n < 0 || pd.payload.n >= ZC_NUM_JS_OUTPUTS) { - errs.push_back("Payment disclosure refers to an invalid output index"); - } - o.push_back(Pair("outputIndex", pd.payload.n)); - o.push_back(Pair("version", pd.payload.version)); - o.push_back(Pair("onetimePrivKey", pd.payload.esk.ToString())); - o.push_back(Pair("message", pd.payload.message)); - o.push_back(Pair("joinSplitPubKey", tx.joinSplitPubKey.ToString())); - - // Verify the payment disclosure was signed using the same key as the transaction i.e. the joinSplitPrivKey. - uint256 dataToBeSigned = SerializeHash(pd.payload, SER_GETHASH, 0); - bool sigVerified = (crypto_sign_verify_detached(pd.payloadSig.data(), - dataToBeSigned.begin(), 32, - tx.joinSplitPubKey.begin()) == 0); - o.push_back(Pair("signatureVerified", sigVerified)); - if (!sigVerified) { - errs.push_back("Payment disclosure signature does not match transaction signature"); - } - - /* - // Check the payment address is valid - PaymentAddress zaddr = pd.payload.zaddr; - { - o.push_back(Pair("paymentAddress", EncodePaymentAddress(zaddr))); - - try { - // Decrypt the note to get value and memo field - JSDescription jsdesc = tx.vjoinsplit[pd.payload.js]; - uint256 h_sig = jsdesc.h_sig(*pzcashParams, tx.joinSplitPubKey); - - ZCPaymentDisclosureNoteDecryption decrypter; - - ZCNoteEncryption::Ciphertext ciphertext = jsdesc.ciphertexts[pd.payload.n]; - - uint256 pk_enc = zaddr.pk_enc; - auto plaintext = decrypter.decryptWithEsk(ciphertext, pk_enc, pd.payload.esk, h_sig, pd.payload.n); - - CDataStream ssPlain(SER_NETWORK, PROTOCOL_VERSION); - ssPlain << plaintext; - SproutNotePlaintext npt; - ssPlain >> npt; - - string memoHexString = HexStr(npt.memo().data(), npt.memo().data() + npt.memo().size()); - o.push_back(Pair("memo", memoHexString)); - o.push_back(Pair("value", ValueFromAmount(npt.value()))); - - // Check the blockchain commitment matches decrypted note commitment - uint256 cm_blockchain = jsdesc.commitments[pd.payload.n]; - SproutNote note = npt.note(zaddr); - uint256 cm_decrypted = note.cm(); - bool cm_match = (cm_decrypted == cm_blockchain); - o.push_back(Pair("commitmentMatch", cm_match)); - if (!cm_match) { - errs.push_back("Commitment derived from payment disclosure does not match blockchain commitment"); - } - } catch (const std::exception &e) { - errs.push_back(string("Error while decrypting payment disclosure note: ") + string(e.what()) ); - } - } - */ - - bool isValid = errs.empty(); - o.push_back(Pair("valid", isValid)); - if (!isValid) { - o.push_back(Pair("errors", errs)); - } - - return o; -} diff --git a/src/zcash/NoteEncryption.cpp b/src/zcash/NoteEncryption.cpp index 63e073265..9f2d64563 100644 --- a/src/zcash/NoteEncryption.cpp +++ b/src/zcash/NoteEncryption.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #include "NoteEncryption.hpp" #include #include "sodium.h" @@ -374,52 +376,6 @@ typename NoteDecryption::Plaintext NoteDecryption::decrypt return plaintext; } -// -// Payment disclosure - decrypt with esk -// -template -typename PaymentDisclosureNoteDecryption::Plaintext PaymentDisclosureNoteDecryption::decryptWithEsk - (const PaymentDisclosureNoteDecryption::Ciphertext &ciphertext, - const uint256 &pk_enc, - const uint256 &esk, - const uint256 &hSig, - unsigned char nonce - ) const -{ - uint256 dhsecret; - - if (crypto_scalarmult(dhsecret.begin(), esk.begin(), pk_enc.begin()) != 0) { - throw std::logic_error("Could not create DH secret"); - } - - // Regenerate keypair - uint256 epk = NoteEncryption::generate_pubkey(esk); - - unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE]; - KDF(K, dhsecret, epk, pk_enc, hSig, nonce); - - // The nonce is zero because we never reuse keys - unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {}; - - PaymentDisclosureNoteDecryption::Plaintext plaintext; - - // Message length is always NOTEENCRYPTION_AUTH_BYTES less than - // the ciphertext length. - if (crypto_aead_chacha20poly1305_ietf_decrypt(plaintext.begin(), NULL, - NULL, - ciphertext.begin(), PaymentDisclosureNoteDecryption::CLEN, - NULL, - 0, - cipher_nonce, K) != 0) { - throw note_decryption_failed(); - } - - return plaintext; -} - - - - template uint256 NoteEncryption::generate_privkey(const uint252 &a_sk) { @@ -461,6 +417,4 @@ uint252 random_uint252() template class NoteEncryption; template class NoteDecryption; -template class PaymentDisclosureNoteDecryption; - } diff --git a/src/zcash/NoteEncryption.hpp b/src/zcash/NoteEncryption.hpp index f6e692028..9c726d5cf 100644 --- a/src/zcash/NoteEncryption.hpp +++ b/src/zcash/NoteEncryption.hpp @@ -1,7 +1,4 @@ -/* -See the Zcash protocol specification for more information. -https://github.com/zcash/zips/blob/master/protocol/protocol.pdf -*/ +// Copyright (c) 2019-2020 The Hush developers #ifndef ZC_NOTE_ENCRYPTION_H_ #define ZC_NOTE_ENCRYPTION_H_ @@ -169,33 +166,9 @@ public: }; - -// Subclass PaymentDisclosureNoteDecryption provides a method to decrypt a note with esk. -template -class PaymentDisclosureNoteDecryption : public NoteDecryption { -protected: -public: - enum { CLEN=MLEN+NOTEENCRYPTION_AUTH_BYTES }; - typedef std::array Ciphertext; - typedef std::array Plaintext; - - PaymentDisclosureNoteDecryption() : NoteDecryption() {} - PaymentDisclosureNoteDecryption(uint256 sk_enc) : NoteDecryption(sk_enc) {} - - Plaintext decryptWithEsk( - const Ciphertext &ciphertext, - const uint256 &pk_enc, - const uint256 &esk, - const uint256 &hSig, - unsigned char nonce - ) const; -}; - } typedef libzcash::NoteEncryption ZCNoteEncryption; typedef libzcash::NoteDecryption ZCNoteDecryption; -typedef libzcash::PaymentDisclosureNoteDecryption ZCPaymentDisclosureNoteDecryption; - #endif /* ZC_NOTE_ENCRYPTION_H_ */ From 7e48b4f8ec46125a64c58d2901849e83c84ec258 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 09:31:31 -0400 Subject: [PATCH 49/98] desprout --- src/amount.h | 1 + src/key.h | 1 + src/key_io.cpp | 1 + src/primitives/block.h | 2 +- src/test/key_tests.cpp | 37 ++----------------------------------- src/util.h | 1 + 6 files changed, 7 insertions(+), 36 deletions(-) diff --git a/src/amount.h b/src/amount.h index be1c39a6e..c5f49593c 100644 --- a/src/amount.h +++ b/src/amount.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/key.h b/src/key.h index 857e8a8ae..16492b151 100644 --- a/src/key.h +++ b/src/key.h @@ -1,6 +1,7 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers // Copyright (c) 2017 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/key_io.cpp b/src/key_io.cpp index 319c24eef..2e0dfeb9a 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -99,6 +99,7 @@ public: } std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; } + std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const { return {}; } }; class ViewingKeyEncoder : public boost::static_visitor diff --git a/src/primitives/block.h b/src/primitives/block.h index ea93d6f50..a2d0ba708 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers -// Copyright (c) 2019 The Hush developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 220d6a9b7..390b2bc7b 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2012-2013 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -22,6 +23,7 @@ using namespace std; using namespace libzcash; +//TODO: convert to Hush addresses static const std::string strSecret1 = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj"; static const std::string strSecret2 = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3"; static const std::string strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw"; @@ -186,41 +188,6 @@ BOOST_AUTO_TEST_CASE(key_test1) BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d")); } -BOOST_AUTO_TEST_CASE(zc_address_test) -{ - for (size_t i = 0; i < 1000; i++) { - auto sk = SproutSpendingKey::random(); - { - string sk_string = EncodeSpendingKey(sk); - - BOOST_CHECK(sk_string[0] == 'S'); - BOOST_CHECK(sk_string[1] == 'K'); - - auto spendingkey2 = DecodeSpendingKey(sk_string); - BOOST_CHECK(IsValidSpendingKey(spendingkey2)); - BOOST_ASSERT(boost::get(&spendingkey2) != nullptr); - auto sk2 = boost::get(spendingkey2); - BOOST_CHECK(sk.inner() == sk2.inner()); - } - { - auto addr = sk.address(); - - std::string addr_string = EncodePaymentAddress(addr); - - BOOST_CHECK(addr_string[0] == 'z'); - BOOST_CHECK(addr_string[1] == 'c'); - - auto paymentaddr2 = DecodePaymentAddress(addr_string); - BOOST_ASSERT(IsValidPaymentAddress(paymentaddr2)); - - BOOST_ASSERT(boost::get(&paymentaddr2) != nullptr); - auto addr2 = boost::get(paymentaddr2); - BOOST_CHECK(addr.a_pk == addr2.a_pk); - BOOST_CHECK(addr.pk_enc == addr2.pk_enc); - } - } -} - BOOST_AUTO_TEST_CASE(zs_address_test) { SelectParams(CBaseChainParams::REGTEST); diff --git a/src/util.h b/src/util.h index 2e8232871..d1bbdd26d 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. From b089972147348bbb3e633aaec3b232225ef455d1 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 10:07:36 -0400 Subject: [PATCH 50/98] delete --- src/rpcblockchain.old | 1625 ----------------------------------------- 1 file changed, 1625 deletions(-) delete mode 100644 src/rpcblockchain.old diff --git a/src/rpcblockchain.old b/src/rpcblockchain.old deleted file mode 100644 index a91f73a63..000000000 --- a/src/rpcblockchain.old +++ /dev/null @@ -1,1625 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "amount.h" -#include "chain.h" -#include "chainparams.h" -#include "checkpoints.h" -#include "crosschain.h" -#include "base58.h" -#include "consensus/validation.h" -#include "cc/eval.h" -#include "main.h" -#include "primitives/transaction.h" -#include "rpcserver.h" -#include "sync.h" -#include "util.h" -#include "script/script.h" -#include "script/script_error.h" -#include "script/sign.h" -#include "script/standard.h" - -#include - -#include - -#include - -using namespace std; - -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -int32_t komodo_longestchain(); -int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); -<<<<<<< HEAD:src/rpcblockchain.old -extern int32_t KOMODO_LONGESTCHAIN; -======= ->>>>>>> master:src/rpcblockchain.cpp - -double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty) -{ - // Floating point number that is a multiple of the minimum difficulty, - // minimum difficulty = 1.0. - if (blockindex == NULL) - { - if (chainActive.LastTip() == NULL) - return 1.0; - else - blockindex = chainActive.LastTip(); - } - - uint32_t bits; - if (networkDifficulty) { - bits = GetNextWorkRequired(blockindex, nullptr, Params().GetConsensus()); - } else { - bits = blockindex->nBits; - } - - uint32_t powLimit = - UintToArith256(Params().GetConsensus().powLimit).GetCompact(); - int nShift = (bits >> 24) & 0xff; - int nShiftAmount = (powLimit >> 24) & 0xff; - - double dDiff = - (double)(powLimit & 0x00ffffff) / - (double)(bits & 0x00ffffff); - - while (nShift < nShiftAmount) - { - dDiff *= 256.0; - nShift++; - } - while (nShift > nShiftAmount) - { - dDiff /= 256.0; - nShift--; - } - - return dDiff; -} - -double GetDifficulty(const CBlockIndex* blockindex) -{ - return GetDifficultyINTERNAL(blockindex, false); -} - -double GetNetworkDifficulty(const CBlockIndex* blockindex) -{ - return GetDifficultyINTERNAL(blockindex, true); -} - -static UniValue ValuePoolDesc( - const std::string &name, - const boost::optional chainValue, - const boost::optional valueDelta) -{ - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); - rv.push_back(Pair("monitored", (bool)chainValue)); - if (chainValue) { - rv.push_back(Pair("chainValue", ValueFromAmount(*chainValue))); - rv.push_back(Pair("chainValueZat", *chainValue)); - } - if (valueDelta) { - rv.push_back(Pair("valueDelta", ValueFromAmount(*valueDelta))); - rv.push_back(Pair("valueDeltaZat", *valueDelta)); - } - return rv; -} - -UniValue blockheaderToJSON(const CBlockIndex* blockindex) -{ - UniValue result(UniValue::VOBJ); - if ( blockindex == 0 ) - { - result.push_back(Pair("error", "null blockhash")); - return(result); - } - result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", blockindex->nVersion)); - result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); - result.push_back(Pair("time", (int64_t)blockindex->nTime)); - result.push_back(Pair("nonce", blockindex->nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(blockindex->nSolution))); - result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) -{ - UniValue result(UniValue::VOBJ); - result.push_back(Pair("hash", block.GetHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) { - confirmations = chainActive.Height() - blockindex->nHeight + 1; - } else { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan"); - } - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - - UniValue deltas(UniValue::VARR); - - for (unsigned int i = 0; i < block.vtx.size(); i++) { - const CTransaction &tx = block.vtx[i]; - const uint256 txhash = tx.GetHash(); - - UniValue entry(UniValue::VOBJ); - entry.push_back(Pair("txid", txhash.GetHex())); - entry.push_back(Pair("index", (int)i)); - - UniValue inputs(UniValue::VARR); - - if (!tx.IsCoinBase()) { - - for (size_t j = 0; j < tx.vin.size(); j++) { - const CTxIn input = tx.vin[j]; - - UniValue delta(UniValue::VOBJ); - - CSpentIndexValue spentInfo; - CSpentIndexKey spentKey(input.prevout.hash, input.prevout.n); - - if (GetSpentIndex(spentKey, spentInfo)) { - if (spentInfo.addressType == 1) { - delta.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); - } - else if (spentInfo.addressType == 2) { - delta.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); - } - else { - continue; - } - delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis)); - delta.push_back(Pair("index", (int)j)); - delta.push_back(Pair("prevtxid", input.prevout.hash.GetHex())); - delta.push_back(Pair("prevout", (int)input.prevout.n)); - - inputs.push_back(delta); - } else { - throw JSONRPCError(RPC_INTERNAL_ERROR, "Spent information not available"); - } - - } - } - - entry.push_back(Pair("inputs", inputs)); - - UniValue outputs(UniValue::VARR); - - for (unsigned int k = 0; k < tx.vout.size(); k++) { - const CTxOut &out = tx.vout[k]; - - UniValue delta(UniValue::VOBJ); - - if (out.scriptPubKey.IsPayToScriptHash()) { - vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); - delta.push_back(Pair("address", CBitcoinAddress(CScriptID(uint160(hashBytes))).ToString())); - - } - else if (out.scriptPubKey.IsPayToPublicKeyHash()) { - vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); - delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - } - else if (out.scriptPubKey.IsPayToPublicKey() || out.scriptPubKey.IsPayToCryptoCondition()) { - CTxDestination address; - if (ExtractDestination(out.scriptPubKey, address)) - { - //vector hashBytes(out.scriptPubKey.begin()+1, out.scriptPubKey.begin()+34); - //xxx delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); - delta.push_back(Pair("address", CBitcoinAddress(address).ToString())); - } - } - else { - continue; - } - - delta.push_back(Pair("satoshis", out.nValue)); - delta.push_back(Pair("index", (int)k)); - - outputs.push_back(delta); - } - - entry.push_back(Pair("outputs", outputs)); - deltas.push_back(entry); - - } - result.push_back(Pair("deltas", deltas)); - result.push_back(Pair("time", block.GetBlockTime())); - result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); - result.push_back(Pair("nonce", block.nNonce.GetHex())); - result.push_back(Pair("bits", strprintf("%08x", block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) -{ - UniValue result(UniValue::VOBJ); - result.push_back(Pair("hash", block.GetHash().GetHex())); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); - result.push_back(Pair("rawconfirmations", confirmations)); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("segid", (int64_t)blockindex->segid)); - UniValue txs(UniValue::VARR); - BOOST_FOREACH(const CTransaction&tx, block.vtx) - { - if(txDetails) - { - UniValue objTx(UniValue::VOBJ); - TxToJSON(tx, uint256(), objTx); - txs.push_back(objTx); - } - else - txs.push_back(tx.GetHash().GetHex()); - } - result.push_back(Pair("tx", txs)); - result.push_back(Pair("time", block.GetBlockTime())); - result.push_back(Pair("nonce", block.nNonce.GetHex())); - result.push_back(Pair("solution", HexStr(block.nSolution))); - result.push_back(Pair("bits", strprintf("%08x", block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); - result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex())); - - UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", blockindex->nChainSproutValue, blockindex->nSproutValue)); - result.push_back(Pair("valuePools", valuePools)); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - CBlockIndex *pnext = chainActive.Next(blockindex); - if (pnext) - result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); - return result; -} - -UniValue getblockcount(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockcount\n" - "\nReturns the number of blocks in the best valid block chain.\n" - "\nResult:\n" - "n (numeric) The current block count\n" - "\nExamples:\n" - + HelpExampleCli("getblockcount", "") - + HelpExampleRpc("getblockcount", "") - ); - - LOCK(cs_main); - return chainActive.Height(); -} - -UniValue getbestblockhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getbestblockhash\n" - "\nReturns the hash of the best (tip) block in the longest block chain.\n" - "\nResult\n" - "\"hex\" (string) the block hash hex encoded\n" - "\nExamples\n" - + HelpExampleCli("getbestblockhash", "") - + HelpExampleRpc("getbestblockhash", "") - ); - - LOCK(cs_main); - return chainActive.LastTip()->GetBlockHash().GetHex(); -} - -UniValue getdifficulty(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getdifficulty\n" - "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nResult:\n" - "n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n" - "\nExamples:\n" - + HelpExampleCli("getdifficulty", "") - + HelpExampleRpc("getdifficulty", "") - ); - - LOCK(cs_main); - return GetNetworkDifficulty(); -} - -bool myIsutxo_spentinmempool(uint256 txid,int32_t vout) -{ - //char *uint256_str(char *str,uint256); char str[65]; - //LOCK(mempool.cs); - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - BOOST_FOREACH(const CTxIn &txin,tx.vin) - { - //fprintf(stderr,"%s/v%d ",uint256_str(str,txin.prevout.hash),txin.prevout.n); - if ( txin.prevout.n == vout && txin.prevout.hash == txid ) - return(true); - } - //fprintf(stderr,"are vins for %s\n",uint256_str(str,hash)); - } - return(false); -} - -bool mytxid_inmempool(uint256 txid) -{ - BOOST_FOREACH(const CTxMemPoolEntry &e,mempool.mapTx) - { - const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - if ( txid == hash ) - return(true); - } - return(false); -} - -UniValue mempoolToJSON(bool fVerbose = false) -{ - if (fVerbose) - { - LOCK(mempool.cs); - UniValue o(UniValue::VOBJ); - BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) - { - const uint256& hash = e.GetTx().GetHash(); - UniValue info(UniValue::VOBJ); - info.push_back(Pair("size", (int)e.GetTxSize())); - info.push_back(Pair("fee", ValueFromAmount(e.GetFee()))); - info.push_back(Pair("time", e.GetTime())); - info.push_back(Pair("height", (int)e.GetHeight())); - info.push_back(Pair("startingpriority", e.GetPriority(e.GetHeight()))); - info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height()))); - const CTransaction& tx = e.GetTx(); - set setDepends; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { - if (mempool.exists(txin.prevout.hash)) - setDepends.insert(txin.prevout.hash.ToString()); - } - - UniValue depends(UniValue::VARR); - BOOST_FOREACH(const string& dep, setDepends) - { - depends.push_back(dep); - } - - info.push_back(Pair("depends", depends)); - o.push_back(Pair(hash.ToString(), info)); - } - return o; - } - else - { - vector vtxid; - mempool.queryHashes(vtxid); - - UniValue a(UniValue::VARR); - BOOST_FOREACH(const uint256& hash, vtxid) - a.push_back(hash.ToString()); - - return a; - } -} - -UniValue getrawmempool(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() > 1) - throw runtime_error( - "getrawmempool ( verbose )\n" - "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" - "\nArguments:\n" - "1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" - "\nResult: (for verbose = false):\n" - "[ (json array of string)\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - "\nResult: (for verbose = true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - " \"size\" : n, (numeric) transaction size in bytes\n" - " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" - " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"startingpriority\" : n, (numeric) priority when transaction entered pool\n" - " \"currentpriority\" : n, (numeric) transaction priority now\n" - " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" - " \"transactionid\", (string) parent transaction id\n" - " ... ]\n" - " }, ...\n" - "}\n" - "\nExamples\n" - + HelpExampleCli("getrawmempool", "true") - + HelpExampleRpc("getrawmempool", "true") - ); - - LOCK(cs_main); - - bool fVerbose = false; - if (params.size() > 0) - fVerbose = params[0].get_bool(); - - return mempoolToJSON(fVerbose); -} - -UniValue getblockdeltas(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error(""); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, pblockindex,1)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - return blockToDeltasJSON(block, pblockindex); -} - -UniValue getblockhashes(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2) - throw runtime_error( - "getblockhashes timestamp\n" - "\nReturns array of hashes of blocks within the timestamp range provided.\n" - "\nArguments:\n" - "1. high (numeric, required) The newer block timestamp\n" - "2. low (numeric, required) The older block timestamp\n" - "3. options (string, required) A json object\n" - " {\n" - " \"noOrphans\":true (boolean) will only include blocks on the main chain\n" - " \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n" - " }\n" - "\nResult:\n" - "[\n" - " \"hash\" (string) The block hash\n" - "]\n" - "[\n" - " {\n" - " \"blockhash\": (string) The block hash\n" - " \"logicalts\": (numeric) The logical timestamp\n" - " }\n" - "]\n" - "\nExamples:\n" - + HelpExampleCli("getblockhashes", "1231614698 1231024505") - + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") - + HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'") - ); - - unsigned int high = params[0].get_int(); - unsigned int low = params[1].get_int(); - bool fActiveOnly = false; - bool fLogicalTS = false; - - if (params.size() > 2) { - if (params[2].isObject()) { - UniValue noOrphans = find_value(params[2].get_obj(), "noOrphans"); - UniValue returnLogical = find_value(params[2].get_obj(), "logicalTimes"); - - if (noOrphans.isBool()) - fActiveOnly = noOrphans.get_bool(); - - if (returnLogical.isBool()) - fLogicalTS = returnLogical.get_bool(); - } - } - - std::vector > blockHashes; - - if (fActiveOnly) - LOCK(cs_main); - - if (!GetTimestampIndex(high, low, fActiveOnly, blockHashes)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes"); - } - - UniValue result(UniValue::VARR); - - for (std::vector >::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) { - if (fLogicalTS) { - UniValue item(UniValue::VOBJ); - item.push_back(Pair("blockhash", it->first.GetHex())); - item.push_back(Pair("logicalts", (int)it->second)); - result.push_back(item); - } else { - result.push_back(it->first.GetHex()); - } - } - - return result; -} - -UniValue getblockhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getblockhash index\n" - "\nReturns hash of block in best-block-chain at index provided.\n" - "\nArguments:\n" - "1. index (numeric, required) The block index\n" - "\nResult:\n" - "\"hash\" (string) The block hash\n" - "\nExamples:\n" - + HelpExampleCli("getblockhash", "1000") - + HelpExampleRpc("getblockhash", "1000") - ); - - LOCK(cs_main); - - int nHeight = params[0].get_int(); - if (nHeight < 0 || nHeight > chainActive.Height()) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - - CBlockIndex* pblockindex = chainActive[nHeight]; - return pblockindex->GetBlockHash().GetHex(); -} - -/*uint256 _komodo_getblockhash(int32_t nHeight) -{ - uint256 hash; - LOCK(cs_main); - if ( nHeight >= 0 && nHeight <= chainActive.Height() ) - { - CBlockIndex* pblockindex = chainActive[nHeight]; - hash = pblockindex->GetBlockHash(); - int32_t i; - for (i=0; i<32; i++) - printf("%02x",((uint8_t *)&hash)[i]); - printf(" blockhash.%d\n",nHeight); - } else memset(&hash,0,sizeof(hash)); - return(hash); -}*/ - -UniValue getblockheader(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblockheader \"hash\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" - "If verbose is true, returns an Object with information about blockheader .\n" - "\nArguments:\n" - "1. \"hash\" (string, required) The block hash\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - ); - - LOCK(cs_main); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - - bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << pblockindex->GetBlockHeader(); - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; - } - - return blockheaderToJSON(pblockindex); -} - -UniValue getblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblock \"hash|height\" ( verbose )\n" - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash|height'.\n" - "If verbose is true, returns an Object with information about block .\n" - "\nArguments:\n" - "1. \"hash|height\" (string, required) The block hash or height\n" - "2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n" - "\nResult (for verbose = true):\n" - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided hash)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"size\" : n, (numeric) The block size\n" - " \"height\" : n, (numeric) The block height or index (same as provided height)\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"tx\" : [ (array of string) The transaction ids\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - " ],\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - "\nResult (for verbose=false):\n" - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - "\nExamples:\n" - + HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleCli("getblock", "12800") - + HelpExampleRpc("getblock", "12800") - ); - - LOCK(cs_main); - - std::string strHash = params[0].get_str(); - - // If height is supplied, find the hash - if (strHash.size() < (2 * sizeof(uint256))) { - // std::stoi allows characters, whereas we want to be strict - regex r("[[:digit:]]+"); - if (!regex_match(strHash, r)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); - } - - int nHeight = -1; - try { - nHeight = std::stoi(strHash); - } - catch (const std::exception &e) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); - } - - if (nHeight < 0 || nHeight > chainActive.Height()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - } - strHash = chainActive[nHeight]->GetBlockHash().GetHex(); - } - - uint256 hash(uint256S(strHash)); - - bool fVerbose = true; - if (params.size() > 1) - fVerbose = params[1].get_bool(); - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - - if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); - - if(!ReadBlockFromDisk(block, pblockindex,1)) - throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); - - if (!fVerbose) - { - CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); - ssBlock << block; - std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); - return strHex; - } - - return blockToJSON(block, pblockindex); -} - -UniValue gettxoutsetinfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "gettxoutsetinfo\n" - "\nReturns statistics about the unspent transaction output set.\n" - "Note this call may take some time.\n" - "\nResult:\n" - "{\n" - " \"height\":n, (numeric) The current block height (index)\n" - " \"bestblock\": \"hex\", (string) the best block hash hex\n" - " \"transactions\": n, (numeric) The number of transactions\n" - " \"txouts\": n, (numeric) The number of output transactions\n" - " \"bytes_serialized\": n, (numeric) The serialized size\n" - " \"hash_serialized\": \"hash\", (string) The serialized hash\n" - " \"total_amount\": x.xxx (numeric) The total amount\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("gettxoutsetinfo", "") - + HelpExampleRpc("gettxoutsetinfo", "") - ); - - UniValue ret(UniValue::VOBJ); - - CCoinsStats stats; - FlushStateToDisk(); - if (pcoinsTip->GetStats(stats)) { - ret.push_back(Pair("height", (int64_t)stats.nHeight)); - ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); - ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); - ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs)); - ret.push_back(Pair("bytes_serialized", (int64_t)stats.nSerializedSize)); - ret.push_back(Pair("hash_serialized", stats.hashSerialized.GetHex())); - ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); - } - return ret; -} - -#include "komodo_defs.h" -#include "komodo_structs.h" - -#define IGUANA_MAXSCRIPTSIZE 10001 -#define KOMODO_KVDURATION 1440 -#define KOMODO_KVBINARY 2 -extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -uint64_t komodo_paxprice(uint64_t *seedp,int32_t height,char *base,char *rel,uint64_t basevolume); -int32_t komodo_paxprices(int32_t *heights,uint64_t *prices,int32_t max,char *base,char *rel); -int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); -char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); -int32_t komodo_minerids(uint8_t *minerids,int32_t height,int32_t width); -int32_t komodo_kvsearch(uint256 *refpubkeyp,int32_t current_height,uint32_t *flagsp,int32_t *heightp,uint8_t value[IGUANA_MAXSCRIPTSIZE],uint8_t *key,int32_t keylen); - -UniValue kvsearch(const UniValue& params, bool fHelp) -{ - UniValue ret(UniValue::VOBJ); uint32_t flags; uint8_t value[IGUANA_MAXSCRIPTSIZE*8],key[IGUANA_MAXSCRIPTSIZE*8]; int32_t duration,j,height,valuesize,keylen; uint256 refpubkey; static uint256 zeroes; - if (fHelp || params.size() != 1 ) - throw runtime_error( - "kvsearch key\n" - "\nSearch for a key stored via the kvupdate command. This feature is only available for asset chains.\n" - "\nArguments:\n" - "1. key (string, required) search the chain for this key\n" - "\nResult:\n" - "{\n" - " \"coin\": \"xxxxx\", (string) chain the key is stored on\n" - " \"currentheight\": xxxxx, (numeric) current height of the chain\n" - " \"key\": \"xxxxx\", (string) key\n" - " \"keylen\": xxxxx, (string) length of the key \n" - " \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n" - " \"height\": xxxxx, (numeric) height the key was stored at\n" - " \"expiration\": xxxxx, (numeric) height the key will expire\n" - " \"flags\": x (numeric) 1 if the key was created with a password; 0 otherwise.\n" - " \"value\": \"xxxxx\", (string) stored value\n" - " \"valuesize\": xxxxx (string) amount of characters stored\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("kvsearch", "examplekey") - + HelpExampleRpc("kvsearch", "\"examplekey\"") - ); - LOCK(cs_main); - if ( (keylen= (int32_t)strlen(params[0].get_str().c_str())) > 0 ) - { - ret.push_back(Pair("coin",(char *)(ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL))); - ret.push_back(Pair("currentheight", (int64_t)chainActive.LastTip()->nHeight)); - ret.push_back(Pair("key",params[0].get_str())); - ret.push_back(Pair("keylen",keylen)); - if ( keylen < sizeof(key) ) - { - memcpy(key,params[0].get_str().c_str(),keylen); - if ( (valuesize= komodo_kvsearch(&refpubkey,chainActive.LastTip()->nHeight,&flags,&height,value,key,keylen)) >= 0 ) - { - std::string val; char *valuestr; - val.resize(valuesize); - valuestr = (char *)val.data(); - memcpy(valuestr,value,valuesize); - if ( memcmp(&zeroes,&refpubkey,sizeof(refpubkey)) != 0 ) - ret.push_back(Pair("owner",refpubkey.GetHex())); - ret.push_back(Pair("height",height)); - duration = ((flags >> 2) + 1) * KOMODO_KVDURATION; - ret.push_back(Pair("expiration", (int64_t)(height+duration))); - ret.push_back(Pair("flags",(int64_t)flags)); - ret.push_back(Pair("value",val)); - ret.push_back(Pair("valuesize",valuesize)); - } else ret.push_back(Pair("error",(char *)"cant find key")); - } else ret.push_back(Pair("error",(char *)"key too big")); - } else ret.push_back(Pair("error",(char *)"null key")); - return ret; -} - -UniValue minerids(const UniValue& params, bool fHelp) -{ - uint32_t timestamp = 0; UniValue ret(UniValue::VOBJ); UniValue a(UniValue::VARR); uint8_t minerids[2000],pubkeys[65][33]; int32_t i,j,n,numnotaries,tally[129]; - if ( fHelp || params.size() != 1 ) - throw runtime_error("minerids needs height\n"); - LOCK(cs_main); - int32_t height = atoi(params[0].get_str().c_str()); - if ( height <= 0 ) - height = chainActive.LastTip()->nHeight; - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - timestamp = pblockindex->GetBlockTime(); - } - if ( (n= komodo_minerids(minerids,height,(int32_t)(sizeof(minerids)/sizeof(*minerids)))) > 0 ) - { - memset(tally,0,sizeof(tally)); - numnotaries = komodo_notaries(pubkeys,height,timestamp); - if ( numnotaries > 0 ) - { - for (i=0; i= numnotaries ) - tally[128]++; - else tally[minerids[i]]++; - } - for (i=0; i<64; i++) - { - UniValue item(UniValue::VOBJ); std::string hex,kmdaddress; char *hexstr,kmdaddr[64],*ptr; int32_t m; - hex.resize(66); - hexstr = (char *)hex.data(); - for (j=0; j<33; j++) - sprintf(&hexstr[j*2],"%02x",pubkeys[i][j]); - item.push_back(Pair("notaryid", i)); - - bitcoin_address(kmdaddr,60,pubkeys[i],33); - m = (int32_t)strlen(kmdaddr); - kmdaddress.resize(m); - ptr = (char *)kmdaddress.data(); - memcpy(ptr,kmdaddr,m); - item.push_back(Pair("KMDaddress", kmdaddress)); - - item.push_back(Pair("pubkey", hex)); - item.push_back(Pair("blocks", tally[i])); - a.push_back(item); - } - UniValue item(UniValue::VOBJ); - item.push_back(Pair("pubkey", (char *)"external miners")); - item.push_back(Pair("blocks", tally[128])); - a.push_back(item); - } - ret.push_back(Pair("mined", a)); - ret.push_back(Pair("numnotaries", numnotaries)); - } else ret.push_back(Pair("error", (char *)"couldnt extract minerids")); - return ret; -} - -UniValue notaries(const UniValue& params, bool fHelp) -{ - UniValue a(UniValue::VARR); uint32_t timestamp=0; UniValue ret(UniValue::VOBJ); int32_t i,j,n,m; char *hexstr; uint8_t pubkeys[64][33]; char btcaddr[64],kmdaddr[64],*ptr; - if ( fHelp || (params.size() != 1 && params.size() != 2) ) - throw runtime_error("notaries height timestamp\n"); - LOCK(cs_main); - int32_t height = atoi(params[0].get_str().c_str()); - if ( params.size() == 2 ) - timestamp = (uint32_t)atol(params[1].get_str().c_str()); - else timestamp = (uint32_t)time(NULL); - if ( height < 0 ) - { - height = chainActive.LastTip()->nHeight; - timestamp = chainActive.LastTip()->GetBlockTime(); - } - else if ( params.size() < 2 ) - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - timestamp = pblockindex->GetBlockTime(); - } - if ( (n= komodo_notaries(pubkeys,height,timestamp)) > 0 ) - { - for (i=0; i 0 ) - ret.push_back(Pair("withdraws", opretbuf)); - else ret.push_back(Pair("withdraws", (char *)"")); - for (baseid=0; baseid<32; baseid++) - { - UniValue item(UniValue::VOBJ); UniValue obj(UniValue::VOBJ); - if ( pax_fiatstatus(&available,&deposited,&issued,&withdrawn,&approved,&redeemed,CURRENCIES[baseid]) == 0 ) - { - if ( deposited != 0 || issued != 0 || withdrawn != 0 || approved != 0 || redeemed != 0 ) - { - item.push_back(Pair("available", ValueFromAmount(available))); - item.push_back(Pair("deposited", ValueFromAmount(deposited))); - item.push_back(Pair("issued", ValueFromAmount(issued))); - item.push_back(Pair("withdrawn", ValueFromAmount(withdrawn))); - item.push_back(Pair("approved", ValueFromAmount(approved))); - item.push_back(Pair("redeemed", ValueFromAmount(redeemed))); - obj.push_back(Pair(CURRENCIES[baseid],item)); - a.push_back(obj); - } - } - } - ret.push_back(Pair("fiatstatus", a)); - return ret; -} - -UniValue paxprice(const UniValue& params, bool fHelp) -{ - if ( fHelp || params.size() > 4 || params.size() < 2 ) - throw runtime_error("paxprice \"base\" \"rel\" height\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t basevolume=0,relvolume,seed; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t height; - if ( params.size() == 2 ) - height = chainActive.LastTip()->nHeight; - else height = atoi(params[2].get_str().c_str()); - //if ( params.size() == 3 || (basevolume= COIN * atof(params[3].get_str().c_str())) == 0 ) - basevolume = 100000; - relvolume = komodo_paxprice(&seed,height,(char *)base.c_str(),(char *)rel.c_str(),basevolume); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - ret.push_back(Pair("height", height)); - char seedstr[32]; - sprintf(seedstr,"%llu",(long long)seed); - ret.push_back(Pair("seed", seedstr)); - if ( height < 0 || height > chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[height]; - if ( pblockindex != 0 ) - ret.push_back(Pair("timestamp", (int64_t)pblockindex->nTime)); - if ( basevolume != 0 && relvolume != 0 ) - { - ret.push_back(Pair("price",((double)relvolume / (double)basevolume))); - ret.push_back(Pair("invprice",((double)basevolume / (double)relvolume))); - ret.push_back(Pair("basevolume",ValueFromAmount(basevolume))); - ret.push_back(Pair("relvolume",ValueFromAmount(relvolume))); - } else ret.push_back(Pair("error", "overflow or error in one or more of parameters")); - } - return ret; -} - -UniValue paxprices(const UniValue& params, bool fHelp) -{ - if ( fHelp || params.size() != 3 ) - throw runtime_error("paxprices \"base\" \"rel\" maxsamples\n"); - LOCK(cs_main); - UniValue ret(UniValue::VOBJ); uint64_t relvolume,prices[4096]; uint32_t i,n; int32_t heights[sizeof(prices)/sizeof(*prices)]; - std::string base = params[0].get_str(); - std::string rel = params[1].get_str(); - int32_t maxsamples = atoi(params[2].get_str().c_str()); - if ( maxsamples < 1 ) - maxsamples = 1; - else if ( maxsamples > sizeof(heights)/sizeof(*heights) ) - maxsamples = sizeof(heights)/sizeof(*heights); - ret.push_back(Pair("base", base)); - ret.push_back(Pair("rel", rel)); - n = komodo_paxprices(heights,prices,maxsamples,(char *)base.c_str(),(char *)rel.c_str()); - UniValue a(UniValue::VARR); - for (i=0; i chainActive.Height() ) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); - else - { - CBlockIndex *pblockindex = chainActive[heights[i]]; - - item.push_back(Pair("t", (int64_t)pblockindex->nTime)); - item.push_back(Pair("p", (double)prices[i] / COIN)); - a.push_back(item); - } - } - ret.push_back(Pair("array", a)); - return ret; -} - -uint64_t komodo_accrued_interest(int32_t *txheightp,uint32_t *locktimep,uint256 hash,int32_t n,int32_t checkheight,uint64_t checkvalue,int32_t tipheight); - -UniValue gettxout(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() < 2 || params.size() > 3) - throw runtime_error( - "gettxout \"txid\" n ( includemempool )\n" - "\nReturns details about an unspent transaction output.\n" - "\nArguments:\n" - "1. \"txid\" (string, required) The transaction id\n" - "2. n (numeric, required) vout value\n" - "3. includemempool (boolean, optional) Whether to include the mempool\n" - "\nResult:\n" - "{\n" - " \"bestblock\" : \"hash\", (string) the block hash\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"code\", (string) \n" - " \"hex\" : \"hex\", (string) \n" - " \"reqSigs\" : n, (numeric) Number of required signatures\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" - " \"addresses\" : [ (array of string) array of Komodo addresses\n" - " \"komodoaddress\" (string) Komodo address\n" - " ,...\n" - " ]\n" - " },\n" - " \"version\" : n, (numeric) The version\n" - " \"coinbase\" : true|false (boolean) Coinbase or not\n" - "}\n" - - "\nExamples:\n" - "\nGet unspent transactions\n" - + HelpExampleCli("listunspent", "") + - "\nView the details\n" - + HelpExampleCli("gettxout", "\"txid\" 1") + - "\nAs a json rpc call\n" - + HelpExampleRpc("gettxout", "\"txid\", 1") - ); - - LOCK(cs_main); - - UniValue ret(UniValue::VOBJ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - int n = params[1].get_int(); - bool fMempool = true; - if (params.size() > 2) - fMempool = params[2].get_bool(); - - CCoins coins; - if (fMempool) { - LOCK(mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); - if (!view.GetCoins(hash, coins)) - return NullUniValue; - mempool.pruneSpent(hash, coins); // TODO: this should be done by the CCoinsViewMemPool - } else { - if (!pcoinsTip->GetCoins(hash, coins)) - return NullUniValue; - } - if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull()) - return NullUniValue; - - BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - CBlockIndex *pindex = it->second; - ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex())); - if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) - ret.push_back(Pair("confirmations", 0)); - else - { - ret.push_back(Pair("confirmations", komodo_dpowconfs(coins.nHeight,pindex->nHeight - coins.nHeight + 1))); - ret.push_back(Pair("rawconfirmations", pindex->nHeight - coins.nHeight + 1)); - } - ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue))); - uint64_t interest; int32_t txheight; uint32_t locktime; - if ( (interest= komodo_accrued_interest(&txheight,&locktime,hash,n,coins.nHeight,coins.vout[n].nValue,(int32_t)pindex->nHeight)) != 0 ) - ret.push_back(Pair("interest", ValueFromAmount(interest))); - UniValue o(UniValue::VOBJ); - ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true); - ret.push_back(Pair("scriptPubKey", o)); - ret.push_back(Pair("version", coins.nVersion)); - ret.push_back(Pair("coinbase", coins.fCoinBase)); - - return ret; -} - -UniValue verifychain(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() > 2) - throw runtime_error( - "verifychain ( checklevel numblocks )\n" - "\nVerifies blockchain database.\n" - "\nArguments:\n" - "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n" - "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n" - "\nResult:\n" - "true|false (boolean) Verified or not\n" - "\nExamples:\n" - + HelpExampleCli("verifychain", "") - + HelpExampleRpc("verifychain", "") - ); - - LOCK(cs_main); - - int nCheckLevel = GetArg("-checklevel", 3); - int nCheckDepth = GetArg("-checkblocks", 288); - if (params.size() > 0) - nCheckLevel = params[0].get_int(); - if (params.size() > 1) - nCheckDepth = params[1].get_int(); - - return CVerifyDB().VerifyDB(pcoinsTip, nCheckLevel, nCheckDepth); -} - -/** Implementation of IsSuperMajority with better feedback */ -static UniValue SoftForkMajorityDesc(int minVersion, CBlockIndex* pindex, int nRequired, const Consensus::Params& consensusParams) -{ - int nFound = 0; - CBlockIndex* pstart = pindex; - for (int i = 0; i < consensusParams.nMajorityWindow && pstart != NULL; i++) - { - if (pstart->nVersion >= minVersion) - ++nFound; - pstart = pstart->pprev; - } - - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("status", nFound >= nRequired)); - rv.push_back(Pair("found", nFound)); - rv.push_back(Pair("required", nRequired)); - rv.push_back(Pair("window", consensusParams.nMajorityWindow)); - return rv; -} - -static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) -{ - UniValue rv(UniValue::VOBJ); - rv.push_back(Pair("id", name)); - rv.push_back(Pair("version", version)); - rv.push_back(Pair("enforce", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityEnforceBlockUpgrade, consensusParams))); - rv.push_back(Pair("reject", SoftForkMajorityDesc(version, pindex, consensusParams.nMajorityRejectBlockOutdated, consensusParams))); - return rv; -} - -static UniValue NetworkUpgradeDesc(const Consensus::Params& consensusParams, Consensus::UpgradeIndex idx, int height) -{ - UniValue rv(UniValue::VOBJ); - auto upgrade = NetworkUpgradeInfo[idx]; - rv.push_back(Pair("name", upgrade.strName)); - rv.push_back(Pair("activationheight", consensusParams.vUpgrades[idx].nActivationHeight)); - switch (NetworkUpgradeState(height, consensusParams, idx)) { - case UPGRADE_DISABLED: rv.push_back(Pair("status", "disabled")); break; - case UPGRADE_PENDING: rv.push_back(Pair("status", "pending")); break; - case UPGRADE_ACTIVE: rv.push_back(Pair("status", "active")); break; - } - rv.push_back(Pair("info", upgrade.strInfo)); - return rv; -} - -void NetworkUpgradeDescPushBack( - UniValue& networkUpgrades, - const Consensus::Params& consensusParams, - Consensus::UpgradeIndex idx, - int height) -{ - // Network upgrades with an activation height of NO_ACTIVATION_HEIGHT are - // hidden. This is used when network upgrade implementations are merged - // without specifying the activation height. - if (consensusParams.vUpgrades[idx].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) { - networkUpgrades.push_back(Pair( - HexInt(NetworkUpgradeInfo[idx].nBranchId), - NetworkUpgradeDesc(consensusParams, idx, height))); - } -} - - -UniValue getblockchaininfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockchaininfo\n" - "Returns an object containing various state info regarding block chain processing.\n" - "\nNote that when the chain tip is at the last block before a network upgrade activation,\n" - "consensus.chaintip != consensus.nextblock.\n" - "\nResult:\n" - "{\n" - " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"size_on_disk\": xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" - " \"commitments\": xxxxxx, (numeric) the current number of note commitments in the commitment tree\n" - " \"softforks\": [ (array) status of softforks in progress\n" - " {\n" - " \"id\": \"xxxx\", (string) name of softfork\n" - " \"version\": xx, (numeric) block version\n" - " \"enforce\": { (object) progress toward enforcing the softfork rules for new-version blocks\n" - " \"status\": xx, (boolean) true if threshold reached\n" - " \"found\": xx, (numeric) number of blocks with the new version found\n" - " \"required\": xx, (numeric) number of blocks required to trigger\n" - " \"window\": xx, (numeric) maximum size of examined window of recent blocks\n" - " },\n" - " \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n" - " }, ...\n" - " ],\n" - " \"upgrades\": { (object) status of network upgrades\n" - " \"xxxx\" : { (string) branch ID of the upgrade\n" - " \"name\": \"xxxx\", (string) name of upgrade\n" - " \"activationheight\": xxxxxx, (numeric) block height of activation\n" - " \"status\": \"xxxx\", (string) status of upgrade\n" - " \"info\": \"xxxx\", (string) additional information about upgrade\n" - " }, ...\n" - " },\n" - " \"consensus\": { (object) branch IDs of the current and upcoming consensus rules\n" - " \"chaintip\": \"xxxxxxxx\", (string) branch ID used to validate the current chain tip\n" - " \"nextblock\": \"xxxxxxxx\" (string) branch ID that the next block will be validated under\n" - " }\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getblockchaininfo", "") - + HelpExampleRpc("getblockchaininfo", "") - ); - - LOCK(cs_main); - double progress; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) { - progress = Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.LastTip()); - } else { - int32_t longestchain = KOMODO_LONGESTCHAIN;//komodo_longestchain(); - progress = (longestchain > 0 ) ? (double) chainActive.Height() / longestchain : 1.0; - } - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("chain", Params().NetworkIDString())); - obj.push_back(Pair("blocks", (int)chainActive.Height())); - obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); - obj.push_back(Pair("bestblockhash", chainActive.LastTip()->GetBlockHash().GetHex())); - obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty())); - obj.push_back(Pair("verificationprogress", progress)); - obj.push_back(Pair("chainwork", chainActive.LastTip()->nChainWork.GetHex())); - obj.push_back(Pair("pruned", fPruneMode)); - obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); - - ZCIncrementalMerkleTree tree; - pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree); - #ifdef __APPLE__ - obj.push_back(Pair("commitments", (uint64_t)tree.size())); - #else - obj.push_back(Pair("commitments", tree.size())); - #endif - - CBlockIndex* tip = chainActive.LastTip(); - UniValue valuePools(UniValue::VARR); - valuePools.push_back(ValuePoolDesc("sprout", tip->nChainSproutValue, boost::none)); - obj.push_back(Pair("valuePools", valuePools)); - - const Consensus::Params& consensusParams = Params().GetConsensus(); - UniValue softforks(UniValue::VARR); - softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); - softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); - softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - obj.push_back(Pair("softforks", softforks)); - - UniValue upgrades(UniValue::VOBJ); - for (int i = Consensus::UPGRADE_OVERWINTER; i < Consensus::MAX_NETWORK_UPGRADES; i++) { - NetworkUpgradeDescPushBack(upgrades, consensusParams, Consensus::UpgradeIndex(i), tip->nHeight); - } - obj.push_back(Pair("upgrades", upgrades)); - - UniValue consensus(UniValue::VOBJ); - consensus.push_back(Pair("chaintip", HexInt(CurrentEpochBranchId(tip->nHeight, consensusParams)))); - consensus.push_back(Pair("nextblock", HexInt(CurrentEpochBranchId(tip->nHeight + 1, consensusParams)))); - obj.push_back(Pair("consensus", consensus)); - - if (fPruneMode) - { - CBlockIndex *block = chainActive.LastTip(); - while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) - block = block->pprev; - - obj.push_back(Pair("pruneheight", block->nHeight)); - } - return obj; -} - -/** Comparison function for sorting the getchaintips heads. */ -struct CompareBlocksByHeight -{ - bool operator()(const CBlockIndex* a, const CBlockIndex* b) const - { - /* Make sure that unequal blocks with the same height do not compare - equal. Use the pointers themselves to make a distinction. */ - - if (a->nHeight != b->nHeight) - return (a->nHeight > b->nHeight); - - return a < b; - } -}; - -#include - -UniValue getchaintips(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getchaintips\n" - "Return information about all known tips in the block tree," - " including the main chain as well as orphaned branches.\n" - "\nResult:\n" - "[\n" - " {\n" - " \"height\": xxxx, (numeric) height of the chain tip\n" - " \"hash\": \"xxxx\", (string) block hash of the tip\n" - " \"branchlen\": 0 (numeric) zero for main chain\n" - " \"status\": \"active\" (string) \"active\" for the main chain\n" - " },\n" - " {\n" - " \"height\": xxxx,\n" - " \"hash\": \"xxxx\",\n" - " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" - " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" - " }\n" - "]\n" - "Possible values for status:\n" - "1. \"invalid\" This branch contains at least one invalid block\n" - "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" - "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" - "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" - "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" - "\nExamples:\n" - + HelpExampleCli("getchaintips", "") - + HelpExampleRpc("getchaintips", "") - ); - - LOCK(cs_main); - - /* Build up a list of chain tips. We start with the list of all - known blocks, and successively remove blocks that appear as pprev - of another block. */ - /*static pthread_mutex_t mutex; static int32_t didinit; - if ( didinit == 0 ) - { - pthread_mutex_init(&mutex,NULL); - didinit = 1; - } - pthread_mutex_lock(&mutex);*/ - std::set setTips; - int32_t n = 0; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - { - n++; - setTips.insert(item.second); - } - fprintf(stderr,"iterations getchaintips %d\n",n); - n = 0; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) - { - const CBlockIndex* pprev=0; - n++; - if ( item.second != 0 ) - pprev = item.second->pprev; - if (pprev) - setTips.erase(pprev); - } - fprintf(stderr,"iterations getchaintips %d\n",n); - //pthread_mutex_unlock(&mutex); - - // Always report the currently active tip. - setTips.insert(chainActive.LastTip()); - - /* Construct the output array. */ - UniValue res(UniValue::VARR); const CBlockIndex *forked; - BOOST_FOREACH(const CBlockIndex* block, setTips) - BOOST_FOREACH(const CBlockIndex* block, setTips) - { - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("height", block->nHeight)); - obj.push_back(Pair("hash", block->phashBlock->GetHex())); - forked = chainActive.FindFork(block); - if ( forked != 0 ) - { - const int branchLen = block->nHeight - forked->nHeight; - obj.push_back(Pair("branchlen", branchLen)); - - string status; - if (chainActive.Contains(block)) { - // This block is part of the currently active chain. - status = "active"; - } else if (block->nStatus & BLOCK_FAILED_MASK) { - // This block or one of its ancestors is invalid. - status = "invalid"; - } else if (block->nChainTx == 0) { - // This block cannot be connected because full block data for it or one of its parents is missing. - status = "headers-only"; - } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { - // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized. - status = "valid-fork"; - } else if (block->IsValid(BLOCK_VALID_TREE)) { - // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain. - status = "valid-headers"; - } else { - // No clue. - status = "unknown"; - } - obj.push_back(Pair("status", status)); - } - res.push_back(obj); - } - - return res; -} - -UniValue mempoolInfoToJSON() -{ - UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("size", (int64_t) mempool.size())); - ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); - ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); - - return ret; -} - -UniValue getmempoolinfo(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getmempoolinfo\n" - "\nReturns details on the active state of the TX memory pool.\n" - "\nResult:\n" - "{\n" - " \"size\": xxxxx (numeric) Current tx count\n" - " \"bytes\": xxxxx (numeric) Sum of all tx sizes\n" - " \"usage\": xxxxx (numeric) Total memory usage for the mempool\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getmempoolinfo", "") - + HelpExampleRpc("getmempoolinfo", "") - ); - - return mempoolInfoToJSON(); -} - -UniValue invalidateblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "invalidateblock \"hash\"\n" - "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to mark as invalid\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("invalidateblock", "\"blockhash\"") - + HelpExampleRpc("invalidateblock", "\"blockhash\"") - ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - CValidationState state; - - { - LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - InvalidateBlock(state, pblockindex); - } - - if (state.IsValid()) { - ActivateBestChain(state); - } - - if (!state.IsValid()) { - throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); - } - - return NullUniValue; -} - -UniValue reconsiderblock(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "reconsiderblock \"hash\"\n" - "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n" - "This can be used to undo the effects of invalidateblock.\n" - "\nArguments:\n" - "1. hash (string, required) the hash of the block to reconsider\n" - "\nResult:\n" - "\nExamples:\n" - + HelpExampleCli("reconsiderblock", "\"blockhash\"") - + HelpExampleRpc("reconsiderblock", "\"blockhash\"") - ); - - std::string strHash = params[0].get_str(); - uint256 hash(uint256S(strHash)); - CValidationState state; - - { - LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlockIndex* pblockindex = mapBlockIndex[hash]; - ReconsiderBlock(state, pblockindex); - } - - if (state.IsValid()) { - ActivateBestChain(state); - } - - if (!state.IsValid()) { - throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); - } - - return NullUniValue; -} From 86a98587a1d1fa7c89f77ef213416eed7b5eb1b2 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 10:14:52 -0400 Subject: [PATCH 51/98] desprout --- src/consensus/upgrades.cpp | 1 + src/serialize.h | 1 + src/wallet/asyncrpcoperation_mergetoaddress.h | 49 ---------- src/wallet/gtest/test_wallet.cpp | 5 - src/wallet/rpcwallet.cpp | 4 +- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 91 ++----------------- src/zcash/Address.hpp | 73 +-------------- src/zcash/JoinSplit.cpp | 18 ---- src/zcash/JoinSplit.hpp | 56 ------------ src/zcash/Note.hpp | 63 +------------ src/zcash/prf.h | 10 +- src/zcash/zip32.h | 3 +- 13 files changed, 24 insertions(+), 352 deletions(-) diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index b75e0c002..984ca377e 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers // Copyright (c) 2018 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/serialize.h b/src/serialize.h index 3d9c3fae6..9d23b469c 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2014 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index 4876921db..32dbcf015 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -44,29 +44,11 @@ using namespace libzcash; // Input UTXO is a tuple of txid, vout, amount, script typedef std::tuple MergeToAddressInputUTXO; -// Input JSOP is a tuple of JSOutpoint, note, amount, spending key -typedef std::tuple MergeToAddressInputSproutNote; - typedef std::tuple MergeToAddressInputSaplingNote; // A recipient is a tuple of address, memo (optional if zaddr) typedef std::tuple MergeToAddressRecipient; -// Package of info which is passed to perform_joinsplit methods. -struct MergeToAddressJSInfo { - std::vector vjsin; - std::vector vjsout; - std::vector notes; - std::vector zkeys; - CAmount vpub_old = 0; - CAmount vpub_new = 0; -}; - -// A struct to help us track the witness and anchor for a given JSOutPoint -struct MergeToAddressWitnessAnchorData { - boost::optional witness; - uint256 anchor; -}; class AsyncRPCOperation_mergetoaddress : public AsyncRPCOperation { @@ -116,7 +98,6 @@ private: std::unordered_map jsopWitnessAnchorMap; std::vector utxoInputs_; - std::vector sproutNoteInputs_; std::vector saplingNoteInputs_; TransactionBuilder builder_; @@ -125,18 +106,6 @@ private: std::array get_memo_from_hex_string(std::string s); bool main_impl(); - // JoinSplit without any input notes to spend - UniValue perform_joinsplit(MergeToAddressJSInfo&); - - // JoinSplit with input notes to spend (JSOutPoints)) - UniValue perform_joinsplit(MergeToAddressJSInfo&, std::vector&); - - // JoinSplit where you have the witnesses and anchor - UniValue perform_joinsplit( - MergeToAddressJSInfo& info, - std::vector> witnesses, - uint256 anchor); - void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error void lock_utxos(); @@ -180,24 +149,6 @@ public: return delegate->main_impl(); } - UniValue perform_joinsplit(MergeToAddressJSInfo& info) - { - return delegate->perform_joinsplit(info); - } - - UniValue perform_joinsplit(MergeToAddressJSInfo& info, std::vector& v) - { - return delegate->perform_joinsplit(info, v); - } - - UniValue perform_joinsplit( - MergeToAddressJSInfo& info, - std::vector> witnesses, - uint256 anchor) - { - return delegate->perform_joinsplit(info, witnesses, anchor); - } - void sign_send_raw_transaction(UniValue obj) { delegate->sign_send_raw_transaction(obj); diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index 0ad789137..6373b6e9f 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -75,11 +75,6 @@ CWalletTx GetValidReceive(const libzcash::SproutSpendingKey& sk, CAmount value, return GetValidReceive(*params, sk, value, randomInputs, version); } -libzcash::SproutNote GetNote(const libzcash::SproutSpendingKey& sk, - const CTransaction& tx, size_t js, size_t n) { - return GetNote(*params, sk, tx, js, n); -} - CWalletTx GetValidSpend(const libzcash::SproutSpendingKey& sk, const libzcash::SproutNote& note, CAmount value) { return GetValidSpend(*params, sk, note, value); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d3d396bbc..2a451dc12 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3123,7 +3123,7 @@ UniValue getalldata(const UniValue& params, bool fHelp,const CPubKey&) if (wtx.GetDepthInMainChain() < 0) continue; - if (wtx.mapSaplingNoteData.size() == 0 && wtx.mapSproutNoteData.size() == 0 && !wtx.IsTrusted()) + if (wtx.mapSaplingNoteData.size() == 0 && !wtx.IsTrusted()) continue; //Assign Immature @@ -3309,7 +3309,7 @@ UniValue getalldata(const UniValue& params, bool fHelp,const CPubKey&) if (!CheckFinalTx(wtx)) continue; - if (wtx.mapSaplingNoteData.size() == 0 && wtx.mapSproutNoteData.size() == 0 && !wtx.IsTrusted()) + if (wtx.mapSaplingNoteData.size() == 0 && !wtx.IsTrusted()) continue; //Excude transactions with less confirmations than required diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4be804abb..a346a547f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -934,7 +934,7 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO for (std::pair& wtxItem : mapWallet) { nWitnessTxIncrement += 1; - if (wtxItem.second.mapSproutNoteData.empty() && wtxItem.second.mapSaplingNoteData.empty()) + if (wtxItem.second.mapSaplingNoteData.empty()) continue; if (wtxItem.second.GetDepthInMainChain() > 0) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index f3526c583..0cd7d8bb6 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -236,82 +236,19 @@ public: std::string ToString() const; }; -class SproutNoteData +class SaplingNoteData { public: - libzcash::SproutPaymentAddress address; - - /** - * Cached note nullifier. May not be set if the wallet was not unlocked when - * this was SproutNoteData was created. If not set, we always assume that the - * note has not been spent. - * - * It's okay to cache the nullifier in the wallet, because we are storing - * the spending key there too, which could be used to derive this. - * If the wallet is encrypted, this means that someone with access to the - * locked wallet cannot spend notes, but can connect received notes to the - * transactions they are spent in. This is the same security semantics as - * for transparent addresses. - */ - boost::optional nullifier; - - /** - * Cached incremental witnesses for spendable Notes. - * Beginning of the list is the most recent witness. - */ - std::list witnesses; - /** * Block height corresponding to the most current witness. * - * When we first create a SproutNoteData in CWallet::FindMySproutNotes, this is set to + * When we first create a SaplingNoteData in CWallet::FindMySaplingNotes, this is set to * -1 as a placeholder. The next time CWallet::ChainTip is called, we can * determine what height the witness cache for this note is valid for (even * if no witnesses were cached), and so can set the correct value in * CWallet::BuildWitnessCache and CWallet::DecrementNoteWitnesses. */ - int witnessHeight; - //In Memory Only - bool witnessRootValidated; - - SproutNoteData() : address(), nullifier(), witnessHeight {-1}, witnessRootValidated {false} { } - SproutNoteData(libzcash::SproutPaymentAddress a) : - address {a}, nullifier(), witnessHeight {-1}, witnessRootValidated {false} { } - SproutNoteData(libzcash::SproutPaymentAddress a, uint256 n) : - address {a}, nullifier {n}, witnessHeight {-1}, witnessRootValidated {false} { } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(address); - READWRITE(nullifier); - READWRITE(witnesses); - READWRITE(witnessHeight); - } - - friend bool operator<(const SproutNoteData& a, const SproutNoteData& b) { - return (a.address < b.address || - (a.address == b.address && a.nullifier < b.nullifier)); - } - - friend bool operator==(const SproutNoteData& a, const SproutNoteData& b) { - return (a.address == b.address && a.nullifier == b.nullifier); - } - - friend bool operator!=(const SproutNoteData& a, const SproutNoteData& b) { - return !(a == b); - } -}; - -class SaplingNoteData -{ -public: - /** - * We initialize the height to -1 for the same reason as we do in SproutNoteData. - * See the comment in that class for a full description. - */ SaplingNoteData() : witnessHeight {-1}, nullifier() { } SaplingNoteData(libzcash::SaplingIncomingViewingKey ivk) : ivk {ivk}, witnessHeight {-1}, nullifier() { } SaplingNoteData(libzcash::SaplingIncomingViewingKey ivk, uint256 n) : ivk {ivk}, witnessHeight {-1}, nullifier(n) { } @@ -347,18 +284,11 @@ public: } }; + +// NOTE: this sprout structure is serialized into wallet.dat, removing it would change wallet.dat format on disk :( typedef std::map mapSproutNoteData_t; typedef std::map mapSaplingNoteData_t; -/** Decrypted note, its location in a transaction, and number of confirmations. */ -struct CSproutNotePlaintextEntry -{ - JSOutPoint jsop; - libzcash::SproutPaymentAddress address; - libzcash::SproutNotePlaintext plaintext; - int confirmations; -}; - /** Sapling note, its location in a transaction, and number of confirmations. */ struct SaplingNoteEntry { @@ -824,7 +754,6 @@ public: protected: - int SproutWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight); int SaplingWitnessMinimumHeight(const uint256& nullifier, int nWitnessHeight, int nMinimumHeight); /** @@ -848,11 +777,11 @@ protected: try { for (std::pair& wtxItem : mapWallet) { auto wtx = wtxItem.second; - // We skip transactions for which mapSproutNoteData and mapSaplingNoteData - // are empty. This covers transactions that have no Sprout or Sapling data + // We skip transactions for which mapSaplingNoteData + // is empty. This covers transactions that have no Sapling data // (i.e. are purely transparent), as well as shielding and unshielding // transactions in which we only have transparent addresses involved. - if (!(wtx.mapSproutNoteData.empty() && wtx.mapSaplingNoteData.empty())) { + if (!(wtx.mapSaplingNoteData.empty())) { if (!walletdb.WriteTx(wtxItem.first, wtx)) { LogPrintf("SetBestChain(): Failed to write CWalletTx, aborting atomic write\n"); walletdb.TxnAbort(); @@ -1319,8 +1248,7 @@ public: bool LoadCryptedHDSeed(const uint256& seedFp, const std::vector& seed); /* Find notes filtered by payment address, min depth, ability to spend */ - void GetFilteredNotes(std::vector& sproutEntries, - std::vector& saplingEntries, + void GetFilteredNotes(std::vector& saplingEntries, std::string address, int minDepth=1, bool ignoreSpent=true, @@ -1328,8 +1256,7 @@ public: /* Find notes filtered by payment addresses, min depth, max depth, if they are spent, if a spending key is required, and if they are locked */ - void GetFilteredNotes(std::vector& sproutEntries, - std::vector& saplingEntries, + void GetFilteredNotes(std::vector& saplingEntries, std::set& filterAddresses, int minDepth=1, int maxDepth=INT_MAX, diff --git a/src/zcash/Address.hpp b/src/zcash/Address.hpp index 42ee0031b..df9034bce 100644 --- a/src/zcash/Address.hpp +++ b/src/zcash/Address.hpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #ifndef ZC_ADDRESS_H_ #define ZC_ADDRESS_H_ @@ -26,34 +28,6 @@ const size_t SerializedSaplingSpendingKeySize = 32; typedef std::array diversifier_t; -class SproutPaymentAddress { -public: - uint256 a_pk; - uint256 pk_enc; - - SproutPaymentAddress() : a_pk(), pk_enc() { } - SproutPaymentAddress(uint256 a_pk, uint256 pk_enc) : a_pk(a_pk), pk_enc(pk_enc) { } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(a_pk); - READWRITE(pk_enc); - } - - //! Get the 256-bit SHA256d hash of this payment address. - uint256 GetHash() const; - - friend inline bool operator==(const SproutPaymentAddress& a, const SproutPaymentAddress& b) { - return a.a_pk == b.a_pk && a.pk_enc == b.pk_enc; - } - friend inline bool operator<(const SproutPaymentAddress& a, const SproutPaymentAddress& b) { - return (a.a_pk < b.a_pk || - (a.a_pk == b.a_pk && a.pk_enc < b.pk_enc)); - } -}; - class ReceivingKey : public uint256 { public: ReceivingKey() { } @@ -62,45 +36,6 @@ public: uint256 pk_enc() const; }; -class SproutViewingKey { -public: - uint256 a_pk; - ReceivingKey sk_enc; - - SproutViewingKey() : a_pk(), sk_enc() { } - SproutViewingKey(uint256 a_pk, ReceivingKey sk_enc) : a_pk(a_pk), sk_enc(sk_enc) { } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(a_pk); - READWRITE(sk_enc); - } - - SproutPaymentAddress address() const; - - friend inline bool operator==(const SproutViewingKey& a, const SproutViewingKey& b) { - return a.a_pk == b.a_pk && a.sk_enc == b.sk_enc; - } - friend inline bool operator<(const SproutViewingKey& a, const SproutViewingKey& b) { - return (a.a_pk < b.a_pk || - (a.a_pk == b.a_pk && a.sk_enc < b.sk_enc)); - } -}; - -class SproutSpendingKey : public uint252 { -public: - SproutSpendingKey() : uint252() { } - SproutSpendingKey(uint252 a_sk) : uint252(a_sk) { } - - static SproutSpendingKey random(); - - ReceivingKey receiving_key() const; - SproutViewingKey viewing_key() const; - SproutPaymentAddress address() const; -}; - //! Sapling functions. class SaplingPaymentAddress { public: @@ -218,8 +153,8 @@ public: SaplingPaymentAddress default_address() const; }; -typedef boost::variant PaymentAddress; -typedef boost::variant ViewingKey; +typedef boost::variant PaymentAddress; +typedef boost::variant ViewingKey; } diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index 0a052209a..e71bf25b1 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -246,24 +246,6 @@ uint256 JoinSplit::h_sig( return output; } -SproutNote JSOutput::note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const { - uint256 rho = PRF_rho(phi, i, h_sig); - - return SproutNote(addr.a_pk, value, rho, r); -} - -JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) { - SproutSpendingKey a_sk = SproutSpendingKey::random(); - addr = a_sk.address(); -} - -JSInput::JSInput() : witness(SproutMerkleTree().witness()), - key(SproutSpendingKey::random()) { - note = SproutNote(key.address().a_pk, 0, random_uint256(), random_uint256()); - SproutMerkleTree dummy_tree; - dummy_tree.append(note.cm()); - witness = dummy_tree.witness(); -} template class JoinSplit; diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp index 09e31570f..27df05db0 100644 --- a/src/zcash/JoinSplit.hpp +++ b/src/zcash/JoinSplit.hpp @@ -24,69 +24,13 @@ typedef std::array GrothProof; typedef boost::variant SproutProof; class JSInput { -public: - SproutWitness witness; - SproutNote note; - SproutSpendingKey key; - - JSInput(); - JSInput(SproutWitness witness, - SproutNote note, - SproutSpendingKey key) : witness(witness), note(note), key(key) { } - - uint256 nullifier() const { - return note.nullifier(key); - } }; class JSOutput { -public: - SproutPaymentAddress addr; - uint64_t value; - std::array memo = {{0xF6}}; // 0xF6 is invalid UTF8 as per spec, rest of array is 0x00 - - JSOutput(); - JSOutput(SproutPaymentAddress addr, uint64_t value) : addr(addr), value(value) { } - - SproutNote note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const; }; template class JoinSplit { -public: - virtual ~JoinSplit() {} - - static JoinSplit* Prepared(); - - static uint256 h_sig(const uint256& randomSeed, - const std::array& nullifiers, - const uint256& joinSplitPubKey - ); - - // Compute nullifiers, macs, note commitments & encryptions, and SNARK proof - virtual SproutProof prove( - const std::array& inputs, - const std::array& outputs, - std::array& out_notes, - std::array& out_ciphertexts, - uint256& out_ephemeralKey, - const uint256& joinSplitPubKey, - uint256& out_randomSeed, - std::array& out_hmacs, - std::array& out_nullifiers, - std::array& out_commitments, - uint64_t vpub_old, - uint64_t vpub_new, - const uint256& rt, - bool computeProof = true, - // For paymentdisclosure, we need to retrieve the esk. - // Reference as non-const parameter with default value leads to compile error. - // So use pointer for simplicity. - uint256 *out_esk = nullptr - ) = 0; - -protected: - JoinSplit() {} }; } diff --git a/src/zcash/Note.hpp b/src/zcash/Note.hpp index 7d3377306..5b16d95c5 100644 --- a/src/zcash/Note.hpp +++ b/src/zcash/Note.hpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #ifndef ZC_NOTE_H_ #define ZC_NOTE_H_ @@ -22,25 +24,6 @@ public: inline uint64_t value() const { return value_; }; }; -class SproutNote : public BaseNote { -public: - uint256 a_pk; - uint256 rho; - uint256 r; - - SproutNote(uint256 a_pk, uint64_t value, uint256 rho, uint256 r) - : BaseNote(value), a_pk(a_pk), rho(rho), r(r) {} - - SproutNote(); - - virtual ~SproutNote() {}; - - uint256 cm() const; - - uint256 nullifier(const SproutSpendingKey& a_sk) const; -}; - - class SaplingNote : public BaseNote { public: diversifier_t d; @@ -74,48 +57,6 @@ public: inline const std::array & memo() const { return memo_; } }; -class SproutNotePlaintext : public BaseNotePlaintext { -public: - uint256 rho; - uint256 r; - - SproutNotePlaintext() {} - - SproutNotePlaintext(const SproutNote& note, std::array memo); - - SproutNote note(const SproutPaymentAddress& addr) const; - - virtual ~SproutNotePlaintext() {} - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - unsigned char leadingByte = 0x00; - READWRITE(leadingByte); - - if (leadingByte != 0x00) { - throw std::ios_base::failure("lead byte of SproutNotePlaintext is not recognized"); - } - - READWRITE(value_); - READWRITE(rho); - READWRITE(r); - READWRITE(memo_); - } - - static SproutNotePlaintext decrypt(const ZCNoteDecryption& decryptor, - const ZCNoteDecryption::Ciphertext& ciphertext, - const uint256& ephemeralKey, - const uint256& h_sig, - unsigned char nonce - ); - - ZCNoteEncryption::Ciphertext encrypt(ZCNoteEncryption& encryptor, - const uint256& pk_enc - ) const; -}; - typedef std::pair SaplingNotePlaintextEncryptionResult; class SaplingNotePlaintext : public BaseNotePlaintext { diff --git a/src/zcash/prf.h b/src/zcash/prf.h index f666cfa23..adfd7d710 100644 --- a/src/zcash/prf.h +++ b/src/zcash/prf.h @@ -1,5 +1,6 @@ +// Copyright (c) 2019-2020 The Hush developers /* -Zcash uses SHA256Compress as a PRF for various components +Hush uses SHA256Compress as a PRF for various components within the zkSNARK circuit. */ @@ -11,13 +12,6 @@ within the zkSNARK circuit. #include -//! Sprout functions -uint256 PRF_addr_a_pk(const uint252& a_sk); -uint256 PRF_addr_sk_enc(const uint252& a_sk); -uint256 PRF_nf(const uint252& a_sk, const uint256& rho); -uint256 PRF_pk(const uint252& a_sk, size_t i0, const uint256& h_sig); -uint256 PRF_rho(const uint252& phi, size_t i0, const uint256& h_sig); - //! Sapling functions uint256 PRF_ask(const uint256& sk); uint256 PRF_nsk(const uint256& sk); diff --git a/src/zcash/zip32.h b/src/zcash/zip32.h index 44bc58598..1521dddd1 100644 --- a/src/zcash/zip32.h +++ b/src/zcash/zip32.h @@ -1,4 +1,5 @@ // Copyright (c) 2018 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -134,7 +135,7 @@ struct SaplingExtendedSpendingKey { } }; -typedef boost::variant SpendingKey; +typedef boost::variant SpendingKey; } From a44fa2ede4f474ed5a70dfa7a391ead3bf60075d Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 10:24:22 -0400 Subject: [PATCH 52/98] This datastructure is tied to the wallet.dat format on disk --- src/wallet/wallet.h | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0cd7d8bb6..f6e6274d1 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -236,6 +236,56 @@ public: std::string ToString() const; }; +// NOTE: wallet.dat format depends on this data structure :( +class SproutNoteData + { + public: + libzcash::SproutPaymentAddress address; + + /** + * Cached note nullifier. May not be set if the wallet was not unlocked when + * this was SproutNoteData was created. If not set, we always assume that the + * note has not been spent. + * + * It's okay to cache the nullifier in the wallet, because we are storing + * the spending key there too, which could be used to derive this. + * If the wallet is encrypted, this means that someone with access to the + * locked wallet cannot spend notes, but can connect received notes to the + * transactions they are spent in. This is the same security semantics as + * for transparent addresses. + */ + boost::optional nullifier; + + /** + * Cached incremental witnesses for spendable Notes. + * Beginning of the list is the most recent witness. + */ + std::list witnesses; + + /** + * Block height corresponding to the most current witness. + * + * When we first create a SaplingNoteData in CWallet::FindMySaplingNotes, this is set to + * -1 as a placeholder. The next time CWallet::ChainTip is called, we can + * determine what height the witness cache for this note is valid for (even + * if no witnesses were cached), and so can set the correct value in + * CWallet::BuildWitnessCache and CWallet::DecrementNoteWitnesses. + */ + int witnessHeight; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(address); + READWRITE(nullifier); + READWRITE(witnesses); + READWRITE(witnessHeight); + } + +}; + + class SaplingNoteData { public: From 90406d601c9ece64697379568982224af1970d87 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 11:13:30 -0400 Subject: [PATCH 53/98] desprout --- src/primitives/transaction.cpp | 78 +------------------------ src/wallet/asyncrpcoperation_sendmany.h | 43 +------------- src/zcash/Address.hpp | 31 ++++++++++ 3 files changed, 33 insertions(+), 119 deletions(-) diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 2cde04f2c..53aeeda99 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,83 +27,6 @@ #include "librustzcash.h" -JSDescription::JSDescription( - ZCJoinSplit& params, - const uint256& joinSplitPubKey, - const uint256& anchor, - const std::array& inputs, - const std::array& outputs, - CAmount vpub_old, - CAmount vpub_new, - bool computeProof, - uint256 *esk // payment disclosure -) : vpub_old(vpub_old), vpub_new(vpub_new), anchor(anchor) -{ - std::array notes; - - proof = params.prove( - inputs, - outputs, - notes, - ciphertexts, - ephemeralKey, - joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new, - anchor, - computeProof, - esk // payment disclosure - ); -} - -JSDescription JSDescription::Randomized( - ZCJoinSplit& params, - const uint256& joinSplitPubKey, - const uint256& anchor, - std::array& inputs, - std::array& outputs, - std::array& inputMap, - std::array& outputMap, - CAmount vpub_old, - CAmount vpub_new, - bool computeProof, - uint256 *esk, // payment disclosure - std::function gen -) -{ - // Randomize the order of the inputs and outputs - inputMap = {0, 1}; - outputMap = {0, 1}; - - assert(gen); - - MappedShuffle(inputs.begin(), inputMap.begin(), ZC_NUM_JS_INPUTS, gen); - MappedShuffle(outputs.begin(), outputMap.begin(), ZC_NUM_JS_OUTPUTS, gen); - - return JSDescription( - params, joinSplitPubKey, anchor, inputs, outputs, - vpub_old, vpub_new, computeProof, - esk // payment disclosure - ); -} - -bool JSDescription::Verify( - ZCJoinSplit& params, - libzcash::ProofVerifier& verifier, - const uint256& joinSplitPubKey -) const { - return false; -} - -uint256 JSDescription::h_sig(ZCJoinSplit& params, const uint256& joinSplitPubKey) const -{ - return params.h_sig(randomSeed, nullifiers, joinSplitPubKey); -} - std::string COutPoint::ToString() const { return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10), n); diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index 0b803ddd9..86e6ef775 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -46,19 +46,6 @@ typedef std::tuple SendManyRecipient; // Input UTXO is a tuple (quadruple) of txid, vout, amount, coinbase) typedef std::tuple SendManyInputUTXO; -// Input JSOP is a tuple of JSOutpoint, note and amount -typedef std::tuple SendManyInputJSOP; - -// Package of info which is passed to perform_joinsplit methods. -struct AsyncJoinSplitInfo -{ - std::vector vjsin; - std::vector vjsout; - std::vector notes; - CAmount vpub_old = 0; - CAmount vpub_new = 0; -}; - // A struct to help us track the witness and anchor for a given JSOutPoint struct WitnessAnchorData { boost::optional witness; @@ -115,7 +102,7 @@ private: std::vector t_outputs_; std::vector z_outputs_; std::vector t_inputs_; - std::vector z_sprout_inputs_; + //std::vector z_sprout_inputs_; std::vector z_sapling_inputs_; TransactionBuilder builder_; @@ -128,18 +115,6 @@ private: std::array get_memo_from_hex_string(std::string s); bool main_impl(); - // JoinSplit without any input notes to spend - UniValue perform_joinsplit(AsyncJoinSplitInfo &); - - // JoinSplit with input notes to spend (JSOutPoints)) - UniValue perform_joinsplit(AsyncJoinSplitInfo &, std::vector & ); - - // JoinSplit where you have the witnesses and anchor - UniValue perform_joinsplit( - AsyncJoinSplitInfo & info, - std::vector> witnesses, - uint256 anchor); - void sign_send_raw_transaction(UniValue obj); // throws exception if there was an error }; @@ -185,22 +160,6 @@ public: return delegate->main_impl(); } - UniValue perform_joinsplit(AsyncJoinSplitInfo &info) { - return delegate->perform_joinsplit(info); - } - - UniValue perform_joinsplit(AsyncJoinSplitInfo &info, std::vector &v ) { - return delegate->perform_joinsplit(info, v); - } - - UniValue perform_joinsplit( - AsyncJoinSplitInfo & info, - std::vector> witnesses, - uint256 anchor) - { - return delegate->perform_joinsplit(info, witnesses, anchor); - } - void sign_send_raw_transaction(UniValue obj) { delegate->sign_send_raw_transaction(obj); } diff --git a/src/zcash/Address.hpp b/src/zcash/Address.hpp index df9034bce..ac90120a5 100644 --- a/src/zcash/Address.hpp +++ b/src/zcash/Address.hpp @@ -36,6 +36,37 @@ public: uint256 pk_enc() const; }; + +// NOTE: wallet.dat format depends on this +class SproutPaymentAddress { +public: + uint256 a_pk; + uint256 pk_enc; + + SproutPaymentAddress() : a_pk(), pk_enc() { } + SproutPaymentAddress(uint256 a_pk, uint256 pk_enc) : a_pk(a_pk), pk_enc(pk_enc) { } + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(a_pk); + READWRITE(pk_enc); + } + + //! Get the 256-bit SHA256d hash of this payment address. + uint256 GetHash() const; + + friend inline bool operator==(const SproutPaymentAddress& a, const SproutPaymentAddress& b) { + return a.a_pk == b.a_pk && a.pk_enc == b.pk_enc; + } + friend inline bool operator<(const SproutPaymentAddress& a, const SproutPaymentAddress& b) { + return (a.a_pk < b.a_pk || + (a.a_pk == b.a_pk && a.pk_enc < b.pk_enc)); + } +}; + + //! Sapling functions. class SaplingPaymentAddress { public: From 3cb215e39ad5fc163cfb4b726d6eb3e6ad13bde7 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 12:17:41 -0400 Subject: [PATCH 54/98] more desprout, ugh --- src/init.cpp | 5 +- src/rpc/client.cpp | 2 - src/rpc/server.cpp | 6 +- .../asyncrpcoperation_mergetoaddress.cpp | 1 - src/wallet/asyncrpcoperation_sendmany.cpp | 4 +- src/wallet/rpcwallet.cpp | 8 +- src/zcash/JoinSplit.cpp | 163 +----------------- src/zcash/Note.cpp | 4 + src/zcash/prf.h | 10 +- 9 files changed, 21 insertions(+), 182 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index fd0303786..32cefbe91 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1042,10 +1042,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-developerencryptwallet")) { fprintf(stderr,"%s wallet encryption error\n", __FUNCTION__); return InitError(_("Wallet encryption requires -experimentalfeatures.")); - } - else if (mapArgs.count("-paymentdisclosure")) { - fprintf(stderr,"%s payment disclosure error\n", __FUNCTION__); - return InitError(_("Payment disclosure requires -experimentalfeatures.")); + //TODO: make this non experimental } else if (mapArgs.count("-zmergetoaddress")) { fprintf(stderr,"%s zmerge error\n", __FUNCTION__); return InitError(_("RPC method z_mergetoaddress requires -experimentalfeatures.")); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 79011da34..4f11a476f 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -164,8 +164,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "kvupdate", 4 }, { "z_importkey", 2 }, { "z_importviewingkey", 2 }, - { "z_getpaymentdisclosure", 1}, - { "z_getpaymentdisclosure", 2}, { "z_listsentbyaddress", 1}, { "z_listsentbyaddress", 2}, { "z_listsentbyaddress", 3}, diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 181de29bb..cfe21a6d5 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -669,11 +669,7 @@ static const CRPCCommand vRPCCommands[] = { "wallet", "z_importviewingkey", &z_importviewingkey, true }, { "wallet", "z_exportwallet", &z_exportwallet, true }, { "wallet", "z_importwallet", &z_importwallet, true }, - { "wallet", "opreturn_burn", &opreturn_burn, true }, - - // TODO: rearrange into another category - { "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true }, - { "disclosure", "z_validatepaymentdisclosure", &z_validatepaymentdisclosure, true } + { "wallet", "opreturn_burn", &opreturn_burn, true } #endif // ENABLE_WALLET }; diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 4e47a5a2d..0ecb1ec12 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -46,7 +46,6 @@ #include #include -#include "paymentdisclosuredb.h" int32_t komodo_blockheight(uint256 hash); using namespace libzcash; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 31f987bef..06b8960cf 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -49,7 +49,6 @@ #include #include -#include "paymentdisclosuredb.h" #include using namespace libzcash; @@ -142,9 +141,8 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( LogPrint("zrpc", "%s: z_sendmany initialized\n", getId()); } - // Enable payment disclosure if requested - paymentDisclosureMode = fExperimentalMode && GetBoolArg("-paymentdisclosure", true); + paymentDisclosureMode = false; } AsyncRPCOperation_sendmany::~AsyncRPCOperation_sendmany() { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2a451dc12..340f62a9c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -8309,9 +8309,6 @@ extern UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPu extern UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); -extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp -extern UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); - static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- @@ -8380,10 +8377,7 @@ static const CRPCCommand commands[] = { "wallet", "z_getinfo", &z_getinfo, true }, { "wallet", "z_listsentbyaddress", &z_listsentbyaddress, true }, { "wallet", "z_listreceivedbyaddress", &z_listreceivedbyaddress, true }, - { "wallet", "z_getnotescount", &z_getnotescount, false }, - // TODO: rearrange into another category - { "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true }, - { "disclosure", "z_validatepaymentdisclosure", &z_validatepaymentdisclosure, true } + { "wallet", "z_getnotescount", &z_getnotescount, false } }; diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index e71bf25b1..db51ff1fd 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers #include "JoinSplit.hpp" #include "prf.h" #include "sodium.h" @@ -28,6 +29,7 @@ public: JoinSplitCircuit() {} ~JoinSplitCircuit() {} + /* SproutProof prove( const std::array& inputs, const std::array& outputs, @@ -45,169 +47,13 @@ public: bool computeProof, uint256 *out_esk // Payment disclosure ) { - if (vpub_old > MAX_MONEY) { - throw std::invalid_argument("nonsensical vpub_old value"); - } - - if (vpub_new > MAX_MONEY) { - throw std::invalid_argument("nonsensical vpub_new value"); - } - - uint64_t lhs_value = vpub_old; - uint64_t rhs_value = vpub_new; - - for (size_t i = 0; i < NumInputs; i++) { - // Sanity checks of input - { - // If note has nonzero value - if (inputs[i].note.value() != 0) { - // The witness root must equal the input root. - if (inputs[i].witness.root() != rt) { - throw std::invalid_argument("joinsplit not anchored to the correct root"); - } - - // The tree must witness the correct element - if (inputs[i].note.cm() != inputs[i].witness.element()) { - throw std::invalid_argument("witness of wrong element for joinsplit input"); - } - } - - // Ensure we have the key to this note. - if (inputs[i].note.a_pk != inputs[i].key.address().a_pk) { - throw std::invalid_argument("input note not authorized to spend with given key"); - } - - // Balance must be sensical - if (inputs[i].note.value() > MAX_MONEY) { - throw std::invalid_argument("nonsensical input note value"); - } - - lhs_value += inputs[i].note.value(); - - if (lhs_value > MAX_MONEY) { - throw std::invalid_argument("nonsensical left hand size of joinsplit balance"); - } - } - - // Compute nullifier of input - out_nullifiers[i] = inputs[i].nullifier(); - } - - // Sample randomSeed - out_randomSeed = random_uint256(); - - // Compute h_sig - uint256 h_sig = this->h_sig(out_randomSeed, out_nullifiers, joinSplitPubKey); - - // Sample phi - uint252 phi = random_uint252(); - - // Compute notes for outputs - for (size_t i = 0; i < NumOutputs; i++) { - // Sanity checks of output - { - if (outputs[i].value > MAX_MONEY) { - throw std::invalid_argument("nonsensical output value"); - } - - rhs_value += outputs[i].value; - - if (rhs_value > MAX_MONEY) { - throw std::invalid_argument("nonsensical right hand side of joinsplit balance"); - } - } - - // Sample r - uint256 r = random_uint256(); - - out_notes[i] = outputs[i].note(phi, r, i, h_sig); - } - - if (lhs_value != rhs_value) { - throw std::invalid_argument("invalid joinsplit balance"); - } - - // Compute the output commitments - for (size_t i = 0; i < NumOutputs; i++) { - out_commitments[i] = out_notes[i].cm(); - } - - // Encrypt the ciphertexts containing the note - // plaintexts to the recipients of the value. - { - ZCNoteEncryption encryptor(h_sig); - - for (size_t i = 0; i < NumOutputs; i++) { - SproutNotePlaintext pt(out_notes[i], outputs[i].memo); - - out_ciphertexts[i] = pt.encrypt(encryptor, outputs[i].addr.pk_enc); - } - - out_ephemeralKey = encryptor.get_epk(); - - // !!! Payment disclosure START - if (out_esk != nullptr) { - *out_esk = encryptor.get_esk(); - } - // !!! Payment disclosure END - } - - // Authenticate h_sig with each of the input - // spending keys, producing macs which protect - // against malleability. - for (size_t i = 0; i < NumInputs; i++) { - out_macs[i] = PRF_pk(inputs[i].key, i, h_sig); - } - - if (!computeProof) { - return GrothProof(); - } - GrothProof proof; - - CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); - ss1 << inputs[0].witness.path(); - std::vector auth1(ss1.begin(), ss1.end()); - - CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); - ss2 << inputs[1].witness.path(); - std::vector auth2(ss2.begin(), ss2.end()); - - librustzcash_sprout_prove( - proof.begin(), - - phi.begin(), - rt.begin(), - h_sig.begin(), - - inputs[0].key.begin(), - inputs[0].note.value(), - inputs[0].note.rho.begin(), - inputs[0].note.r.begin(), - auth1.data(), - - inputs[1].key.begin(), - inputs[1].note.value(), - inputs[1].note.rho.begin(), - inputs[1].note.r.begin(), - auth2.data(), - - out_notes[0].a_pk.begin(), - out_notes[0].value(), - out_notes[0].r.begin(), - - out_notes[1].a_pk.begin(), - out_notes[1].value(), - out_notes[1].r.begin(), - - vpub_old, - vpub_new - ); - return proof; } + */ }; +/* template JoinSplit* JoinSplit::Prepared() { @@ -250,4 +96,5 @@ uint256 JoinSplit::h_sig( template class JoinSplit; +*/ } diff --git a/src/zcash/Note.cpp b/src/zcash/Note.cpp index 23210c784..f9e9a2058 100644 --- a/src/zcash/Note.cpp +++ b/src/zcash/Note.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #include "Note.hpp" #include "prf.h" #include "crypto/sha256.h" @@ -11,6 +13,7 @@ using namespace libzcash; +/* SproutNote::SproutNote() { a_pk = random_uint256(); rho = random_uint256(); @@ -39,6 +42,7 @@ uint256 SproutNote::cm() const { uint256 SproutNote::nullifier(const SproutSpendingKey& a_sk) const { return PRF_nf(a_sk, rho); } +*/ // Construct and populate Sapling note for a given payment address and value. SaplingNote::SaplingNote(const SaplingPaymentAddress& address, const uint64_t value) : BaseNote(value) { diff --git a/src/zcash/prf.h b/src/zcash/prf.h index adfd7d710..f666cfa23 100644 --- a/src/zcash/prf.h +++ b/src/zcash/prf.h @@ -1,6 +1,5 @@ -// Copyright (c) 2019-2020 The Hush developers /* -Hush uses SHA256Compress as a PRF for various components +Zcash uses SHA256Compress as a PRF for various components within the zkSNARK circuit. */ @@ -12,6 +11,13 @@ within the zkSNARK circuit. #include +//! Sprout functions +uint256 PRF_addr_a_pk(const uint252& a_sk); +uint256 PRF_addr_sk_enc(const uint252& a_sk); +uint256 PRF_nf(const uint252& a_sk, const uint256& rho); +uint256 PRF_pk(const uint252& a_sk, size_t i0, const uint256& h_sig); +uint256 PRF_rho(const uint252& phi, size_t i0, const uint256& h_sig); + //! Sapling functions uint256 PRF_ask(const uint256& sk); uint256 PRF_nsk(const uint256& sk); From 0cc4772c2559daf5616c03e8c217c3a2a0f26361 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Fri, 5 Jun 2020 12:43:01 -0400 Subject: [PATCH 55/98] desprout --- src/zcash/Note.cpp | 51 ---------------------------------------------- 1 file changed, 51 deletions(-) diff --git a/src/zcash/Note.cpp b/src/zcash/Note.cpp index f9e9a2058..9cd327d1b 100644 --- a/src/zcash/Note.cpp +++ b/src/zcash/Note.cpp @@ -92,57 +92,6 @@ boost::optional SaplingNote::nullifier(const SaplingFullViewingKey& vk, return result; } -SproutNotePlaintext::SproutNotePlaintext( - const SproutNote& note, - std::array memo) : BaseNotePlaintext(note, memo) -{ - rho = note.rho; - r = note.r; -} - -SproutNote SproutNotePlaintext::note(const SproutPaymentAddress& addr) const -{ - return SproutNote(addr.a_pk, value_, rho, r); -} - -SproutNotePlaintext SproutNotePlaintext::decrypt(const ZCNoteDecryption& decryptor, - const ZCNoteDecryption::Ciphertext& ciphertext, - const uint256& ephemeralKey, - const uint256& h_sig, - unsigned char nonce - ) -{ - auto plaintext = decryptor.decrypt(ciphertext, ephemeralKey, h_sig, nonce); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << plaintext; - - SproutNotePlaintext ret; - ss >> ret; - - assert(ss.size() == 0); - - return ret; -} - -ZCNoteEncryption::Ciphertext SproutNotePlaintext::encrypt(ZCNoteEncryption& encryptor, - const uint256& pk_enc - ) const -{ - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << (*this); - - ZCNoteEncryption::Plaintext pt; - - assert(pt.size() == ss.size()); - - memcpy(&pt[0], &ss[0], pt.size()); - - return encryptor.encrypt(pk_enc, pt); -} - - - // Construct and populate SaplingNotePlaintext for a given note and memo. SaplingNotePlaintext::SaplingNotePlaintext( const SaplingNote& note, From 22d4d1a06e88d0cc6bae7bc8dc4665931d5b11a8 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 6 Jun 2020 04:34:30 -0400 Subject: [PATCH 56/98] desprout --- .../asyncrpcoperation_mergetoaddress.cpp | 21 +-- src/wallet/asyncrpcoperation_mergetoaddress.h | 4 - ...asyncrpcoperation_saplingconsolidation.cpp | 3 +- src/wallet/asyncrpcoperation_sendmany.cpp | 18 +-- src/wallet/rpcwallet.cpp | 125 ++++-------------- 5 files changed, 31 insertions(+), 140 deletions(-) diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index 0ecb1ec12..79eaee5a9 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -74,19 +74,17 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress( boost::optional builder, CMutableTransaction contextualTx, std::vector utxoInputs, - std::vector sproutNoteInputs, std::vector saplingNoteInputs, MergeToAddressRecipient recipient, CAmount fee, UniValue contextInfo) : -tx_(contextualTx), utxoInputs_(utxoInputs), sproutNoteInputs_(sproutNoteInputs), -saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), contextinfo_(contextInfo) +tx_(contextualTx), utxoInputs_(utxoInputs), saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), contextinfo_(contextInfo) { if (fee < 0 || fee > MAX_MONEY) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Fee is out of range"); } - if (utxoInputs.empty() && sproutNoteInputs.empty() && saplingNoteInputs.empty()) { + if (utxoInputs.empty() && saplingNoteInputs.empty()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "No inputs"); } @@ -94,14 +92,6 @@ saplingNoteInputs_(saplingNoteInputs), recipient_(recipient), fee_(fee), context throw JSONRPCError(RPC_INVALID_PARAMETER, "Recipient parameter missing"); } - if (sproutNoteInputs.size() > 0 && saplingNoteInputs.size() > 0) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress"); - } - - if (sproutNoteInputs.size() > 0 && builder) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Sprout notes are not supported by the TransactionBuilder"); - } - isUsingBuilder_ = false; if (builder) { isUsingBuilder_ = true; @@ -215,7 +205,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() { assert(isToTaddr_ != isToZaddr_); - bool isPureTaddrOnlyTx = (sproutNoteInputs_.empty() && saplingNoteInputs_.empty() && isToTaddr_); + bool isPureTaddrOnlyTx = (saplingNoteInputs_.empty() && isToTaddr_); CAmount minersFee = fee_; size_t numInputs = utxoInputs_.size(); @@ -240,9 +230,6 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() } CAmount z_inputs_total = 0; - for (const MergeToAddressInputSproutNote& t : sproutNoteInputs_) { - z_inputs_total += std::get<2>(t); - } for (const MergeToAddressInputSaplingNote& t : saplingNoteInputs_) { z_inputs_total += std::get<2>(t); @@ -293,7 +280,7 @@ bool AsyncRPCOperation_mergetoaddress::main_impl() /** * SCENARIO #0 * - * Sprout not involved, so we just use the TransactionBuilder and we're done. + * Only sapling involved, so we just use the TransactionBuilder and we're done. * * This is based on code from AsyncRPCOperation_sendmany::main_impl() and should be refactored. */ diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.h b/src/wallet/asyncrpcoperation_mergetoaddress.h index 32dbcf015..69150161e 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.h +++ b/src/wallet/asyncrpcoperation_mergetoaddress.h @@ -57,7 +57,6 @@ public: boost::optional builder, CMutableTransaction contextualTx, std::vector utxoInputs, - std::vector sproutNoteInputs, std::vector saplingNoteInputs, MergeToAddressRecipient recipient, CAmount fee = MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE, @@ -94,9 +93,6 @@ private: uint256 joinSplitPubKey_; unsigned char joinSplitPrivKey_[crypto_sign_SECRETKEYBYTES]; - // The key is the result string from calling JSOutPoint::ToString() - std::unordered_map jsopWitnessAnchorMap; - std::vector utxoInputs_; std::vector saplingNoteInputs_; diff --git a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp index 0a57b8948..477545348 100644 --- a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp +++ b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp @@ -87,7 +87,6 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() { return status; } - std::vector sproutEntries; std::vector saplingEntries; std::set addresses; { @@ -95,7 +94,7 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() { // We set minDepth to 11 to avoid unconfirmed notes and in anticipation of specifying // an anchor at height N-10 for each SpendDescription // Consider, should notes be sorted? - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, "", 11); + pwalletMain->GetFilteredNotes(saplingEntries, "", 11); if (fConsolidationMapUsed) { const vector& v = mapMultiArgs["-consolidatesaplingaddress"]; for(int i = 0; i < v.size(); i++) { diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 06b8960cf..9e82e41db 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -248,18 +248,12 @@ bool AsyncRPCOperation_sendmany::main_impl() { throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds, no unspent notes found for zaddr from address."); } - // At least one of z_sprout_inputs_ and z_sapling_inputs_ must be empty by design - assert(z_sprout_inputs_.empty() || z_sapling_inputs_.empty()); - CAmount t_inputs_total = 0; for (SendManyInputUTXO & t : t_inputs_) { t_inputs_total += std::get<2>(t); } CAmount z_inputs_total = 0; - for (SendManyInputJSOP & t : z_sprout_inputs_) { - z_inputs_total += std::get<2>(t); - } for (auto t : z_sapling_inputs_) { z_inputs_total += t.note.value(); } @@ -687,20 +681,10 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) { bool AsyncRPCOperation_sendmany::find_unspent_notes() { - std::vector sproutEntries; std::vector saplingEntries; { LOCK2(cs_main, pwalletMain->cs_wallet); - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, fromaddress_, mindepth_); - } - - // If using the TransactionBuilder, we only want Sapling notes. - // If not using it, we only want Sprout notes. - // TODO: Refactor `GetFilteredNotes()` so we only fetch what we need. - if (isUsingBuilder_) { - sproutEntries.clear(); - } else { - saplingEntries.clear(); + pwalletMain->GetFilteredNotes(saplingEntries, fromaddress_, mindepth_); } for (auto entry : saplingEntries) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 340f62a9c..b65e6a839 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -70,7 +70,6 @@ using namespace libzcash; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; extern std::string ASSETCHAINS_OVERRIDE_PUBKEY; -const std::string ADDR_TYPE_SPROUT = "sprout"; const std::string ADDR_TYPE_SAPLING = "sapling"; extern UniValue TxJoinSplitToJSON(const CTransaction& tx); extern int32_t KOMODO_INSYNC; @@ -3787,9 +3786,8 @@ UniValue z_listunspent(const UniValue& params, bool fHelp, const CPubKey& mypk) UniValue results(UniValue::VARR); if (zaddrs.size() > 0) { - std::vector sproutEntries; std::vector saplingEntries; - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false); + pwalletMain->GetFilteredNotes(saplingEntries, zaddrs, nMinDepth, nMaxDepth, true, !fIncludeWatchonly, false); std::set> nullifierSet = pwalletMain->GetNullifiersForAddresses(zaddrs); for (auto & entry : saplingEntries) { @@ -4047,10 +4045,9 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign 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); + pwalletMain->GetFilteredNotes(saplingEntries, address, minDepth, true, ignoreUnspendable); for (auto & entry : saplingEntries) { balance += CAmount(entry.note.value()); } @@ -4102,16 +4099,14 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp, const CPubK throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr."); } - // Visitor to support Sprout and Sapling addrs if (!boost::apply_visitor(PaymentAddressBelongsToWallet(pwalletMain), zaddr) && !boost::apply_visitor(IncomingViewingKeyBelongsToWallet(pwalletMain), zaddr)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found."); } UniValue result(UniValue::VARR); - std::vector sproutEntries; std::vector saplingEntries; - pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, fromaddress, nMinDepth, false, false); + pwalletMain->GetFilteredNotes(saplingEntries, fromaddress, nMinDepth, false, false); std::set> nullifierSet; auto hasSpendingKey = boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr); @@ -4223,7 +4218,7 @@ UniValue z_getnotescount(const UniValue& params, bool fHelp,const CPubKey& mypk) "z_getnotescount\n" "\nArguments:\n" "1. minconf (numeric, optional, default=1) Only include notes in transactions confirmed at least this many times.\n" - "\nReturns the number of sprout and sapling notes available in the wallet.\n" + "\nReturns the number of sapling notes available in the wallet.\n" "\nResult:\n" "{\n" " \"sapling\" (numeric) the number of sapling notes in the wallet\n" @@ -4268,7 +4263,7 @@ UniValue z_gettotalbalance(const UniValue& params, bool fHelp, const CPubKey& my "\nResult:\n" "{\n" " \"transparent\": xxxxx, (numeric) the total balance of transparent funds\n" - " \"private\": xxxxx, (numeric) the total balance of private funds (in both Sprout and Sapling addresses)\n" + " \"private\": xxxxx, (numeric) the total balance of private funds\n" " \"total\": xxxxx, (numeric) the total balance of both transparent and private funds\n" "}\n" "\nExamples:\n" @@ -4650,14 +4645,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key not found."); } - // Remember whether this is a Sprout or Sapling address + // Remember whether this is a Sapling address fromSapling = boost::get(&res) != nullptr; } - // This logic will need to be updated if we add a new shielded pool - bool fromSprout = !(fromTaddr || fromSapling); - - if (fromSprout) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot send from a Sprout zaddr, only Sapling zaddrs supported."); UniValue outputs = params[1].get_array(); @@ -4667,15 +4657,11 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) // Keep track of addresses to spot duplicates set setAddress; - // Track whether we see any Sprout addresses - bool noSproutAddrs = !fromSprout; - // Recipients std::vector taddrRecipients; std::vector zaddrRecipients; CAmount nTotalOut = 0; - bool containsSproutOutput = false; bool containsSaplingOutput = false; for (const UniValue& o : outputs.getValues()) { @@ -4696,35 +4682,6 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) auto res = DecodePaymentAddress(address); if (IsValidPaymentAddress(res, branchId)) { isZaddr = true; - - bool toSapling = boost::get(&res) != nullptr; - bool toSprout = !toSapling; - noSproutAddrs = noSproutAddrs && toSapling; - - containsSproutOutput |= toSprout; - containsSaplingOutput |= toSapling; - - // Sending to both Sprout and Sapling is currently unsupported using z_sendmany - if (containsSproutOutput && containsSaplingOutput) { - throw JSONRPCError( - RPC_INVALID_PARAMETER, - "Cannot send to both Sprout and Sapling addresses using z_sendmany"); - } - if ( GetTime() > KOMODO_SAPLING_DEADLINE ) - { - if ( fromSprout || toSprout ) - throw JSONRPCError(RPC_INVALID_PARAMETER,"Sprout usage has expired"); - } - if ( toSapling && ASSETCHAINS_SYMBOL[0] == 0 ) - throw JSONRPCError(RPC_INVALID_PARAMETER,"Sprout usage will expire soon"); - - // If we are sending from a shielded address, all recipient - // shielded addresses must be of the same type. - if ((fromSprout && toSapling) || (fromSapling && toSprout)) { - throw JSONRPCError( - RPC_INVALID_PARAMETER, - "Cannot send between Sprout and Sapling addresses using z_sendmany"); - } } else { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address ); } @@ -4915,9 +4872,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) // Builder (used if Sapling addresses are involved) boost::optional builder; - if (noSproutAddrs) { - builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); - } + builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); // Contextual transaction we will build on // (used if no Sapling addresses are involved) @@ -5190,11 +5145,11 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp return NullUniValue; string enableArg = "zmergetoaddress"; - auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, true); - std::string strDisabledMsg = ""; - if (!fEnableMergeToAddress) { - strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg); - } + //auto fEnableMergeToAddress = fExperimentalMode && GetBoolArg("-" + enableArg, true); + //std::string strDisabledMsg = ""; + //if (!fEnableMergeToAddress) { + // strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg); + //} if (fHelp || params.size() < 2 || params.size() > 7) throw runtime_error( @@ -5256,7 +5211,6 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp THROW_IF_SYNCING(KOMODO_INSYNC); bool useAnyUTXO = false; - bool useAnySprout = false; bool useAnySapling = false; std::set taddrs = {}; std::set zaddrs = {}; @@ -5277,8 +5231,6 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp if (address == "ANY_TADDR") { useAnyUTXO = true; - } else if (address == "ANY_SPROUT") { - useAnySprout = true; } else if (address == "ANY_SAPLING") { useAnySapling = true; } else { @@ -5303,8 +5255,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp if (useAnyUTXO && taddrs.size() > 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific t-addrs when using \"ANY_TADDR\""); } - if ((useAnySprout || useAnySapling) && zaddrs.size() > 0) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific z-addrs when using \"ANY_SPROUT\" or \"ANY_SAPLING\""); + if ((useAnySapling) && zaddrs.size() > 0) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify specific z-addrs when using \"ANY_SAPLING\""); } const int nextBlockHeight = chainActive.Height() + 1; @@ -5313,7 +5265,6 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp // Validate the destination address auto destaddress = params[1].get_str(); - bool isToSproutZaddr = false; bool isToSaplingZaddr = false; CTxDestination taddr = DecodeDestination(destaddress); if (!IsValidDestination(taddr)) { @@ -5326,7 +5277,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); } } else { - isToSproutZaddr = true; + throw JSONRPCError(RPC_INVALID_PARAMETER, "Only Sapling zaddrs allowed!"); } } else { throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); @@ -5351,14 +5302,12 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp } } - int sproutNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT; int saplingNoteLimit = MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT; if (params.size() > 4) { int nNoteLimit = params[4].get_int(); if (nNoteLimit < 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Limit on maximum number of notes cannot be negative"); } - sproutNoteLimit = nNoteLimit; saplingNoteLimit = nNoteLimit; } @@ -5375,7 +5324,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp std::string memo; if (params.size() > 6) { memo = params[6].get_str(); - if (!(isToSproutZaddr || isToSaplingZaddr)) { + if (!isToSaplingZaddr) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr. It can only be used with a zaddr."); } else if (!IsHex(memo)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected memo data in hexadecimal format."); @@ -5389,7 +5338,6 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp // Prepare to get UTXOs and notes std::vector utxoInputs; - std::vector sproutNoteInputs; std::vector saplingNoteInputs; CAmount mergedUTXOValue = 0; CAmount mergedNoteValue = 0; @@ -5403,9 +5351,8 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp unsigned int max_tx_size = saplingActive ? MAX_TX_SIZE_AFTER_SAPLING : MAX_TX_SIZE_BEFORE_SAPLING; size_t estimatedTxSize = 200; // tx overhead + wiggle room - if (isToSproutZaddr) { - estimatedTxSize += JOINSPLIT_SIZE; - } else if (isToSaplingZaddr) { + + if (isToSaplingZaddr) { estimatedTxSize += OUTPUTDESCRIPTION_SIZE; } @@ -5463,29 +5410,10 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp } } - if (useAnySprout || useAnySapling || zaddrs.size() > 0) { + if (useAnySapling || zaddrs.size() > 0) { // Get available notes - std::vector sproutEntries; - //std::vector saplingEntries; - //pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, zaddrs); - std::vector saplingEntries,skipsapling; - pwalletMain->GetFilteredNotes(sproutEntries, useAnySprout == 0 ? saplingEntries : skipsapling, zaddrs); - // If Sapling is not active, do not allow sending from a sapling addresses. - if (!saplingActive && saplingEntries.size() > 0) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); - } - // Sending from both Sprout and Sapling is currently unsupported using z_mergetoaddress - if (sproutEntries.size() > 0 && saplingEntries.size() > 0) { - throw JSONRPCError( - RPC_INVALID_PARAMETER, - "Cannot send from both Sprout and Sapling addresses using z_mergetoaddress"); - } - // If sending between shielded addresses, they must be the same type - if ((saplingEntries.size() > 0 && isToSproutZaddr) || (sproutEntries.size() > 0 && isToSaplingZaddr)) { - throw JSONRPCError( - RPC_INVALID_PARAMETER, - "Cannot send between Sprout and Sapling addresses using z_mergetoaddress"); - } + std::vector saplingEntries; + pwalletMain->GetFilteredNotes(saplingEntries, zaddrs); for (const SaplingNoteEntry& entry : saplingEntries) { noteCounter++; @@ -5514,7 +5442,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp } size_t numUtxos = utxoInputs.size(); - size_t numNotes = sproutNoteInputs.size() + saplingNoteInputs.size(); + size_t numNotes = saplingNoteInputs.size(); //fprintf(stderr, "num utxos.%li\n", numUtxos); if (numUtxos < 2 && numNotes == 0) { @@ -5552,22 +5480,19 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp CMutableTransaction contextualTx = CreateNewContextualCMutableTransaction( Params().GetConsensus(), nextBlockHeight); - bool isSproutShielded = sproutNoteInputs.size() > 0 || isToSproutZaddr; - if (contextualTx.nVersion == 1 && isSproutShielded) { - contextualTx.nVersion = 2; // Tx format should support vjoinsplit - } // Builder (used if Sapling addresses are involved) boost::optional builder; if (isToSaplingZaddr || saplingNoteInputs.size() > 0) { builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); - } else + } else { contextualTx.nExpiryHeight = 0; // set non z-tx to have no expiry height. + } // Create operation and add to global queue std::shared_ptr q = getAsyncRPCQueue(); std::shared_ptr operation( - new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, sproutNoteInputs, saplingNoteInputs, recipient, nFee, contextInfo) ); + new AsyncRPCOperation_mergetoaddress(builder, contextualTx, utxoInputs, saplingNoteInputs, recipient, nFee, contextInfo) ); q->addOperation(operation); AsyncRPCOperationId operationId = operation->getId(); From f13171efc69f907c631255b5438ebdcd48c04e95 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 6 Jun 2020 05:14:21 -0400 Subject: [PATCH 57/98] desprout --- src/init.cpp | 6 +++--- src/init.h | 4 ++-- src/main.cpp | 9 --------- src/metrics.cpp | 2 +- src/wallet/asyncrpcoperation_sendmany.cpp | 3 --- src/wallet/rpcwallet.cpp | 10 ++-------- src/wallet/wallet.cpp | 4 +--- 7 files changed, 9 insertions(+), 29 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 32cefbe91..7d9733372 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -101,7 +101,7 @@ extern int32_t KOMODO_SNAPSHOT_INTERVAL; extern void komodo_init(int32_t height); -ZCJoinSplit* pzcashParams = NULL; +//ZCJoinSplit* pzcashParams = NULL; #ifdef ENABLE_WALLET CWallet* pwalletMain = NULL; @@ -305,8 +305,8 @@ void Shutdown() delete pwalletMain; pwalletMain = NULL; #endif - delete pzcashParams; - pzcashParams = NULL; + //delete pzcashParams; + //pzcashParams = NULL; globalVerifyHandle.reset(); ECC_Stop(); LogPrintf("%s: done\n", __func__); diff --git a/src/init.h b/src/init.h index 108339865..c68d59419 100644 --- a/src/init.h +++ b/src/init.h @@ -23,7 +23,7 @@ #include -#include "zcash/JoinSplit.hpp" +//#include "zcash/JoinSplit.hpp" class CScheduler; class CWallet; @@ -34,7 +34,7 @@ class thread_group; } // namespace boost extern CWallet* pwalletMain; -extern ZCJoinSplit* pzcashParams; +//extern ZCJoinSplit* pzcashParams; void StartShutdown(); bool ShutdownRequested(); diff --git a/src/main.cpp b/src/main.cpp index f31847b04..c2e9c5bfb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1367,15 +1367,6 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState if (!CheckTransactionWithoutProofVerification(tiptime,tx, state)) { return false; - } else { - // Ensure that zk-SNARKs v|| y - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { - if (!joinsplit.Verify(*pzcashParams, verifier, tx.joinSplitPubKey)) { - return state.DoS(100, error("CheckTransaction(): joinsplit does not verify"), - REJECT_INVALID, "bad-txns-joinsplit-verification-failed"); - } - } - return true; } } diff --git a/src/metrics.cpp b/src/metrics.cpp index ff0863a19..adbef02f2 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -288,7 +288,7 @@ int printMiningStatus(bool mining) } else if (IsInitialBlockDownload()) { std::cout << _("Mining is paused while downloading blocks.") << std::endl; } else { - std::cout << _("Mining is paused (a JoinSplit may be in progress).") << std::endl; + std::cout << _("Mining is paused, enhance your calm") << std::endl; } } lines++; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index 9e82e41db..1b709b142 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -140,9 +140,6 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( } else { LogPrint("zrpc", "%s: z_sendmany initialized\n", getId()); } - - // Enable payment disclosure if requested - paymentDisclosureMode = false; } AsyncRPCOperation_sendmany::~AsyncRPCOperation_sendmany() { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b65e6a839..66ab58f47 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5135,7 +5135,6 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp #define MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT 10 #define MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT 90 -#define JOINSPLIT_SIZE GetSerializeSize(JSDescription(), SER_NETWORK, PROTOCOL_VERSION) #define OUTPUTDESCRIPTION_SIZE GetSerializeSize(OutputDescription(), SER_NETWORK, PROTOCOL_VERSION) #define SPENDDESCRIPTION_SIZE GetSerializeSize(SpendDescription(), SER_NETWORK, PROTOCOL_VERSION) @@ -5154,7 +5153,6 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp if (fHelp || params.size() < 2 || params.size() > 7) throw runtime_error( "z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n" - + strDisabledMsg + "\nMerge multiple UTXOs and notes into a single UTXO or note. Coinbase UTXOs are ignored; use `z_shieldcoinbase`" "\nto combine those into a single note." "\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked. If there is an error, they" @@ -5198,14 +5196,10 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp " \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n" "}\n" "\nExamples:\n" - + HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf") - + HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"") + + HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' zs1aW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf") + + HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"zs1aW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"") ); - if (!fEnableMergeToAddress) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled."); - } - LOCK2(cs_main, pwalletMain->cs_wallet); THROW_IF_SYNCING(KOMODO_INSYNC); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a346a547f..725f04764 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4781,7 +4781,6 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee) * These notes are decrypted and added to the output parameter vector, outEntries. */ void CWallet::GetFilteredNotes( - std::vector& sproutEntries, std::vector& saplingEntries, std::string address, int minDepth, @@ -4794,7 +4793,7 @@ void CWallet::GetFilteredNotes( filterAddresses.insert(DecodePaymentAddress(address)); } - GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, INT_MAX, ignoreSpent, requireSpendingKey); + GetFilteredNotes(saplingEntries, filterAddresses, minDepth, INT_MAX, ignoreSpent, requireSpendingKey); } /** @@ -4803,7 +4802,6 @@ void CWallet::GetFilteredNotes( * These notes are decrypted and added to the output parameter vector, outEntries. */ void CWallet::GetFilteredNotes( - std::vector& sproutEntries, std::vector& saplingEntries, std::set& filterAddresses, int minDepth, From b5a0d3b8b7dab495cc67c02758fe4e7621586eba Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 6 Jun 2020 14:11:30 -0400 Subject: [PATCH 58/98] desprout --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index c2e9c5bfb..2532dd2b1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1368,6 +1368,7 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState if (!CheckTransactionWithoutProofVerification(tiptime,tx, state)) { return false; } + return true; } int32_t komodo_isnotaryvout(char *coinaddr,uint32_t tiptime) // from ac_private chains only From dd95b1471cefc19501631fc84875b5a919105e1f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 6 Jun 2020 14:48:16 -0400 Subject: [PATCH 59/98] desprout --- src/coins.cpp | 33 ++-------------------- src/coins.h | 5 ---- src/main.cpp | 12 ++++---- src/rpc/blockchain.cpp | 7 +++-- src/txmempool.cpp | 4 ++- src/validationinterface.cpp | 4 ++- src/wallet/wallet.cpp | 55 ++----------------------------------- 7 files changed, 22 insertions(+), 98 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index 602d153ec..03b046a70 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers -// Copyright (c) 2019 The Hush developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -65,7 +65,6 @@ bool CCoins::Spend(uint32_t nPos) Cleanup(); return true; } -bool CCoinsView::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { return false; } bool CCoinsView::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { return false; } bool CCoinsView::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return false; } bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; } @@ -85,7 +84,6 @@ bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; } CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { } -bool CCoinsViewBacked::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { return base->GetSproutAnchorAt(rt, tree); } bool CCoinsViewBacked::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { return base->GetSaplingAnchorAt(rt, tree); } bool CCoinsViewBacked::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return base->GetNullifier(nullifier, type); } bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); } @@ -139,30 +137,6 @@ CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const return ret; } - -bool CCoinsViewCache::GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const { - CAnchorsSproutMap::const_iterator it = cacheSproutAnchors.find(rt); - if (it != cacheSproutAnchors.end()) { - if (it->second.entered) { - tree = it->second.tree; - return true; - } else { - return false; - } - } - - if (!base->GetSproutAnchorAt(rt, tree)) { - return false; - } - - CAnchorsSproutMap::iterator ret = cacheSproutAnchors.insert(std::make_pair(rt, CAnchorsSproutCacheEntry())).first; - ret->second.entered = true; - ret->second.tree = tree; - cachedCoinsUsage += ret->second.tree.DynamicMemoryUsage(); - - return true; -} - bool CCoinsViewCache::GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const { CAnchorsSaplingMap::const_iterator it = cacheSaplingAnchors.find(rt); if (it != cacheSaplingAnchors.end()) { @@ -271,7 +245,6 @@ void CCoinsViewCache::BringBestAnchorIntoCache( SproutMerkleTree &tree ) { - assert(GetSproutAnchorAt(currentRoot, tree)); } template<> @@ -550,9 +523,9 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, bool CCoinsViewCache::Flush() { bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashSproutAnchor, hashSaplingAnchor, cacheSproutAnchors, cacheSaplingAnchors, cacheSproutNullifiers, cacheSaplingNullifiers); cacheCoins.clear(); - cacheSproutAnchors.clear(); + //cacheSproutAnchors.clear(); cacheSaplingAnchors.clear(); - cacheSproutNullifiers.clear(); + //cacheSproutNullifiers.clear(); cacheSaplingNullifiers.clear(); cachedCoinsUsage = 0; return fOk; diff --git a/src/coins.h b/src/coins.h index 1211e7e07..3e8f674fb 100644 --- a/src/coins.h +++ b/src/coins.h @@ -372,9 +372,6 @@ struct CCoinsStats class CCoinsView { public: - //! Retrieve the tree (Sprout) at a particular anchored root in the chain - virtual bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; - //! Retrieve the tree (Sapling) at a particular anchored root in the chain virtual bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; @@ -421,7 +418,6 @@ protected: public: CCoinsViewBacked(CCoinsView *viewIn); - bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; bool GetNullifier(const uint256 &nullifier, ShieldedType type) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; @@ -493,7 +489,6 @@ public: CNullifiersMap getNullifiers(); // Standard CCoinsView methods - bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; bool GetNullifier(const uint256 &nullifier, ShieldedType type) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; diff --git a/src/main.cpp b/src/main.cpp index 2532dd2b1..6ca7b68a2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3493,13 +3493,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // This should never fail: we should always be able to get the root // that is on the tip of our chain - assert(view.GetSproutAnchorAt(old_sprout_tree_root, sprout_tree)); + //assert(view.GetSproutAnchorAt(old_sprout_tree_root, sprout_tree)); - { + //{ // Consistency check: the root of the tree we're given should // match what we asked for. - assert(sprout_tree.root() == old_sprout_tree_root); - } + //assert(sprout_tree.root() == old_sprout_tree_root); + //} SaplingMerkleTree sapling_tree; assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree)); @@ -3636,6 +3636,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->GetHeight()); + /* BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { BOOST_FOREACH(const uint256 ¬e_commitment, joinsplit.commitments) { // Insert the note commitments into our temporary tree. @@ -3643,6 +3644,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin sprout_tree.append(note_commitment); } } + */ BOOST_FOREACH(const OutputDescription &outputDescription, tx.vShieldedOutput) { sapling_tree.append(outputDescription.cm); @@ -3652,7 +3654,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } - view.PushAnchor(sprout_tree); + //view.PushAnchor(sprout_tree); view.PushAnchor(sapling_tree); if (!fJustCheck) { pindex->hashFinalSproutRoot = sprout_tree.root(); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 76375b80c..faed5b957 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1668,9 +1668,10 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp, const CPubKey& my obj.push_back(Pair("chainwork", chainActive.LastTip()->chainPower.chainWork.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); - SproutMerkleTree tree; - pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(SPROUT), tree); - obj.push_back(Pair("commitments", static_cast(tree.size()))); + //SproutMerkleTree tree; + //pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(SPROUT), tree); + //obj.push_back(Pair("commitments", static_cast(tree.size()))); + obj.push_back(Pair("commitments", 0)); CBlockIndex* tip = chainActive.LastTip(); UniValue valuePools(UniValue::VARR); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index ca0ed7f51..2f10856d4 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -644,8 +644,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const i++; } - boost::unordered_map intermediates; + /* + boost::unordered_map intermediates; BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) { assert(!pcoins->GetNullifier(nf, SPROUT)); @@ -666,6 +667,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const intermediates.insert(std::make_pair(tree.root(), tree)); } + */ for (const SpendDescription &spendDescription : tx.vShieldedSpend) { SaplingMerkleTree tree; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 799a60ceb..44b5115d6 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php . @@ -138,7 +139,8 @@ void ThreadNotifyWallets(CBlockIndex *pindexLastTip) while (pindex && pindex != pindexFork) { // Get the Sprout commitment tree as of the start of this block. SproutMerkleTree oldSproutTree; - assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, oldSproutTree)); + //TODO: how important is oldSproutTree ? + //assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, oldSproutTree)); // Get the Sapling commitment tree as of the start of this block. // We can get this from the `hashFinalSaplingRoot` of the last block diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 725f04764..b492ee8a2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2334,57 +2334,6 @@ void CWallet::WitnessNoteCommitment(std::vector commitments, std::vector>& witnesses, uint256 &final_anchor) { - witnesses.resize(commitments.size()); - CBlockIndex* pindex = chainActive.Genesis(); - SproutMerkleTree tree; - - while (pindex) { - CBlock block; - ReadBlockFromDisk(block, pindex,1); - - BOOST_FOREACH(const CTransaction& tx, block.vtx) - { - BOOST_FOREACH(const JSDescription& jsdesc, tx.vjoinsplit) - { - BOOST_FOREACH(const uint256 ¬e_commitment, jsdesc.commitments) - { - tree.append(note_commitment); - - BOOST_FOREACH(boost::optional& wit, witnesses) { - if (wit) { - wit->append(note_commitment); - } - } - - size_t i = 0; - BOOST_FOREACH(uint256& commitment, commitments) { - if (note_commitment == commitment) { - witnesses.at(i) = tree.witness(); - } - i++; - } - } - } - } - - uint256 current_anchor = tree.root(); - - // Consistency check: we should be able to find the current tree - // in our CCoins view. - SproutMerkleTree dummy_tree; - assert(pcoinsTip->GetSproutAnchorAt(current_anchor, dummy_tree)); - - pindex = chainActive.Next(pindex); - } - - // TODO: #93; Select a root via some heuristic. - final_anchor = tree.root(); - - BOOST_FOREACH(boost::optional& wit, witnesses) { - if (wit) { - assert(final_anchor == wit->root()); - } - } } /** @@ -2697,11 +2646,11 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) } } - SproutMerkleTree sproutTree; + //SproutMerkleTree sproutTree; SaplingMerkleTree saplingTree; // This should never fail: we should always be able to get the tree // state on the path to the tip of our chain - assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, sproutTree)); + //assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, sproutTree)); if (pindex->pprev) { if (NetworkUpgradeActive(pindex->pprev->GetHeight(), Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { assert(pcoinsTip->GetSaplingAnchorAt(pindex->pprev->hashFinalSaplingRoot, saplingTree)); From 0eec14fb01c6b5200398fe4262f8f42e55587438 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 6 Jun 2020 20:28:02 -0400 Subject: [PATCH 60/98] desprout --- src/transaction_builder.cpp | 1 - src/transaction_builder.h | 1 + src/txdb.h | 2 +- src/zcash/IncrementalMerkleTree.cpp | 2 ++ src/zcash/IncrementalMerkleTree.hpp | 2 ++ src/zcash/JoinSplit.hpp | 2 ++ src/zcash/Proof.cpp | 2 ++ src/zcash/Proof.hpp | 2 ++ src/zcash/prf.cpp | 2 ++ src/zcash/util.cpp | 2 ++ src/zcash/zip32.cpp | 1 + 11 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index 8b1acaca9..d821a266f 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -1,6 +1,5 @@ // Copyright (c) 2018 The Zcash developers // Copyright (c) 2019-2020 The Hush developers -// Released under the GPLv3 // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/transaction_builder.h b/src/transaction_builder.h index 49c09294d..39225433a 100644 --- a/src/transaction_builder.h +++ b/src/transaction_builder.h @@ -1,4 +1,5 @@ // Copyright (c) 2018 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/txdb.h b/src/txdb.h index e089d0190..81c0bb3ad 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -63,7 +63,7 @@ protected: public: CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); - bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; + //bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const; bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const; bool GetNullifier(const uint256 &nf, ShieldedType type) const; bool GetCoins(const uint256 &txid, CCoins &coins) const; diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index b8b3cd183..4d3ff8c2b 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #include #include diff --git a/src/zcash/IncrementalMerkleTree.hpp b/src/zcash/IncrementalMerkleTree.hpp index 1ebb2b499..ab55e8ad4 100644 --- a/src/zcash/IncrementalMerkleTree.hpp +++ b/src/zcash/IncrementalMerkleTree.hpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #ifndef ZC_INCREMENTALMERKLETREE_H_ #define ZC_INCREMENTALMERKLETREE_H_ diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp index 27df05db0..e7aded3c1 100644 --- a/src/zcash/JoinSplit.hpp +++ b/src/zcash/JoinSplit.hpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #ifndef ZC_JOINSPLIT_H_ #define ZC_JOINSPLIT_H_ diff --git a/src/zcash/Proof.cpp b/src/zcash/Proof.cpp index 7ab1298a8..1a0ebfe75 100644 --- a/src/zcash/Proof.cpp +++ b/src/zcash/Proof.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #include "Proof.hpp" #include "crypto/common.h" diff --git a/src/zcash/Proof.hpp b/src/zcash/Proof.hpp index 7c9b7f7f5..0a3d0bb14 100644 --- a/src/zcash/Proof.hpp +++ b/src/zcash/Proof.hpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #ifndef ZC_PROOF_H_ #define ZC_PROOF_H_ diff --git a/src/zcash/prf.cpp b/src/zcash/prf.cpp index 2491de83e..9ab3d0f10 100644 --- a/src/zcash/prf.cpp +++ b/src/zcash/prf.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #include "prf.h" #include "crypto/sha256.h" #include "hash.h" diff --git a/src/zcash/util.cpp b/src/zcash/util.cpp index 6f32bf79a..064e1cca9 100644 --- a/src/zcash/util.cpp +++ b/src/zcash/util.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2019-2020 The Hush developers + #include "zcash/util.h" #include #include diff --git a/src/zcash/zip32.cpp b/src/zcash/zip32.cpp index 15478843e..615c5896d 100644 --- a/src/zcash/zip32.cpp +++ b/src/zcash/zip32.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2018 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. From f725a8362c138e3e75085c47788feefb1fe7db2e Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 6 Jun 2020 23:17:49 -0400 Subject: [PATCH 61/98] desprout --- src/timedata.cpp | 1 + src/timedata.h | 1 + src/torcontrol.cpp | 1 + src/torcontrol.h | 1 + src/transaction_builder.cpp | 1 - 5 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/timedata.cpp b/src/timedata.cpp index 584e0db8c..64a3955ff 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/timedata.h b/src/timedata.h index 2296baf11..13cff12b3 100644 --- a/src/timedata.h +++ b/src/timedata.h @@ -1,4 +1,5 @@ // Copyright (c) 2014 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 99c76995b..c2eb490da 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2015-2017 The Bitcoin Core developers // Copyright (c) 2017 The Zcash developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/torcontrol.h b/src/torcontrol.h index 72dc82c5b..44611c7b6 100644 --- a/src/torcontrol.h +++ b/src/torcontrol.h @@ -1,4 +1,5 @@ // Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index d821a266f..08953ee02 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -1,6 +1,5 @@ // Copyright (c) 2018 The Zcash developers // Copyright (c) 2019-2020 The Hush developers - // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. From 0c118eb129f06ec6a9ff5ca9750b75b3417a8a2d Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 7 Jun 2020 00:04:15 -0400 Subject: [PATCH 62/98] delete --- src/Makefile.am | 2 -- src/komodo_bitcoind.h | 2 +- src/primitives/block.h | 2 +- src/primitives/nonce.cpp | 24 ------------------------ src/primitives/nonce.h | 29 ----------------------------- src/test/transaction_tests.cpp | 1 + 6 files changed, 3 insertions(+), 57 deletions(-) delete mode 100644 src/primitives/nonce.cpp delete mode 100644 src/primitives/nonce.h diff --git a/src/Makefile.am b/src/Makefile.am index ab04c24bc..a1cae78a2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -427,7 +427,6 @@ libbitcoin_common_a_SOURCES = \ metrics.cpp \ primitives/block.cpp \ primitives/transaction.cpp \ - primitives/nonce.cpp \ protocol.cpp \ pubkey.cpp \ scheduler.cpp \ @@ -652,7 +651,6 @@ libzcashconsensus_la_SOURCES = \ crypto/sha512.cpp \ hash.cpp \ primitives/transaction.cpp \ - primitives/nonce.cpp \ pubkey.cpp \ script/zcashconsensus.cpp \ script/interpreter.cpp \ diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 39cf5da63..e1748c191 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -20,7 +20,7 @@ #include #include #include "consensus/params.h" -#include "primitives/nonce.h" +//#include "primitives/nonce.h" #include "komodo_defs.h" #include "script/standard.h" #include "cc/CCinclude.h" diff --git a/src/primitives/block.h b/src/primitives/block.h index a2d0ba708..9a6ddf100 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -23,7 +23,7 @@ #define BITCOIN_PRIMITIVES_BLOCK_H #include "primitives/transaction.h" -#include "primitives/nonce.h" +//#include "primitives/nonce.h" #include "serialize.h" #include "uint256.h" #include "arith_uint256.h" diff --git a/src/primitives/nonce.cpp b/src/primitives/nonce.cpp deleted file mode 100644 index a1fbd667d..000000000 --- a/src/primitives/nonce.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2019 The Hush Developers -// Copyright (c) 2018 Michael Toutonghi -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - -#include "hash.h" -#include "nonce.h" -#include - diff --git a/src/primitives/nonce.h b/src/primitives/nonce.h deleted file mode 100644 index b17a9f01b..000000000 --- a/src/primitives/nonce.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2019 Hush Developers -// Copyright (c) 2018 Michael Toutonghi -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - -#ifndef BITCOIN_PRIMITIVES_NONCE_H -#define BITCOIN_PRIMITIVES_NONCE_H - -#include "serialize.h" -#include "uint256.h" -#include "arith_uint256.h" - - -#endif // BITCOIN_PRIMITIVES_NONCE_H diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index b6a6ebc26..eb948f92d 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers // Copyright (c) 2011-2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. From b0ea67d5bea4e4692a9567a2f8dc7d41e1c89ec9 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 7 Jun 2020 16:10:49 -0400 Subject: [PATCH 63/98] desprout --- src/Makefile.am | 11 +++++------ src/primitives/transaction.h | 1 + src/transaction_builder.cpp | 1 + src/wallet/rpchushwallet.cpp | 2 +- src/zcash/Note.cpp | 31 ------------------------------- 5 files changed, 8 insertions(+), 38 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index a1cae78a2..ec3f562f2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,5 @@ +# Copyright 2019-2020 The Hush developers + DIST_SUBDIRS = secp256k1 univalue cryptoconditions AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) @@ -186,7 +188,6 @@ BITCOIN_CORE_H = \ prevector.h \ primitives/block.h \ primitives/transaction.h \ - primitives/nonce.h \ protocol.h \ pubkey.h \ random.h \ @@ -486,7 +487,7 @@ libbitcoin_cli_a_SOURCES = \ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h # -# bitcoind binary # +# komodod binary # komodod_SOURCES = bitcoind.cpp komodod_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) komodod_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -545,7 +546,7 @@ if TARGET_DARWIN komodod_LDFLAGS += -static-libgcc endif -# bitcoin-cli binary # +# komodo-cli binary # komodo_cli_SOURCES = bitcoin-cli.cpp komodo_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) komodo_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -593,7 +594,7 @@ wallet_utility_LDADD = \ $(LIBCRYPTOCONDITIONS) endif -# zcash-tx binary # +# komodo-tx binary # komodo_tx_SOURCES = komodo-tx.cpp komodo_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) komodo_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -603,7 +604,6 @@ if TARGET_WINDOWS komodo_tx_SOURCES += bitcoin-tx-res.rc endif -# FIXME: Is libzcash needed for hush-tx ? komodo_tx_LDADD = \ $(LIBUNIVALUE) \ $(LIBBITCOIN_COMMON) \ @@ -615,7 +615,6 @@ komodo_tx_LDADD = \ $(LIBCRYPTOCONDITIONS) komodo_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) -# # zcash protocol primitives # libzcash_a_SOURCES = \ diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 2ece7b255..7a46b9c00 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -44,6 +44,7 @@ #include "zcash/Zcash.h" #include "zcash/JoinSplit.hpp" #include "zcash/Proof.hpp" +#include "zcash/Note.hpp" extern uint32_t ASSETCHAINS_MAGIC; extern std::string ASSETCHAINS_SELFIMPORT; diff --git a/src/transaction_builder.cpp b/src/transaction_builder.cpp index 08953ee02..e1879e1d4 100644 --- a/src/transaction_builder.cpp +++ b/src/transaction_builder.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "zcash/Note.hpp" SpendDescriptionInfo::SpendDescriptionInfo( libzcash::SaplingExpandedSpendingKey expsk, diff --git a/src/wallet/rpchushwallet.cpp b/src/wallet/rpchushwallet.cpp index 62b7a4fc9..64cd0e4a5 100644 --- a/src/wallet/rpchushwallet.cpp +++ b/src/wallet/rpchushwallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2020 The Hush developers +// Copyright (c) 2019-2020 The Hush developers // Copyright (c) 2019 Cryptoforge // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/zcash/Note.cpp b/src/zcash/Note.cpp index 9cd327d1b..e6d185a0e 100644 --- a/src/zcash/Note.cpp +++ b/src/zcash/Note.cpp @@ -13,37 +13,6 @@ using namespace libzcash; -/* -SproutNote::SproutNote() { - a_pk = random_uint256(); - rho = random_uint256(); - r = random_uint256(); -} - -uint256 SproutNote::cm() const { - unsigned char discriminant = 0xb0; - - CSHA256 hasher; - hasher.Write(&discriminant, 1); - hasher.Write(a_pk.begin(), 32); - - auto value_vec = convertIntToVectorLE(value_); - - hasher.Write(&value_vec[0], value_vec.size()); - hasher.Write(rho.begin(), 32); - hasher.Write(r.begin(), 32); - - uint256 result; - hasher.Finalize(result.begin()); - - return result; -} - -uint256 SproutNote::nullifier(const SproutSpendingKey& a_sk) const { - return PRF_nf(a_sk, rho); -} -*/ - // Construct and populate Sapling note for a given payment address and value. SaplingNote::SaplingNote(const SaplingPaymentAddress& address, const uint64_t value) : BaseNote(value) { d = address.d; From 0ca0637323d6da126d127feea4ce50c0df2efadd Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sun, 7 Jun 2020 17:31:27 -0400 Subject: [PATCH 64/98] Use our mirror of boost, bintray is returning 403 currently --- depends/packages/boost.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 48c60710d..3112ca7be 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,7 +1,7 @@ package=boost $(package)_version=1_72_0 -$(package)_download_path=https://dl.bintray.com/boostorg/release/1.72.0/source/ +$(package)_download_path=https://github.com/MyHush/boost/releases/download/v1.72.0/ $(package)_sha256_hash=59c9b274bc451cf91a9ba1dd2c7fdcaf5d60b1b3aa83f2c9fa143417cc660722 $(package)_file_name=$(package)_$($(package)_version).tar.bz2 From 5a601d143196cf9dff7bc4a0beb28dbe890f8713 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Mon, 8 Jun 2020 11:13:17 -0400 Subject: [PATCH 65/98] desprout --- src/wallet/rpcwallet.cpp | 1 + src/wallet/wallet.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 66ab58f47..873d8eb87 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -38,6 +38,7 @@ #include "zcbenchmarks.h" #include "script/interpreter.h" #include "zcash/zip32.h" +#include "zcash/Note.hpp" #include "notaries_staked.h" #include "utiltime.h" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b492ee8a2..a7ca3d74d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -346,6 +346,14 @@ bool CWallet::LoadSaplingPaymentAddress( return CCryptoKeyStore::AddSaplingIncomingViewingKey(ivk, addr); } +bool CWallet::AddCScript(const CScript& redeemScript) +{ + if (!CCryptoKeyStore::AddCScript(redeemScript)) + return false; + if (!fFileBacked) + return true; + return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript); +} bool CWallet::LoadCScript(const CScript& redeemScript) { From f4dd9fe3bbd6b57cd55d5b638322028e54dba3e9 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 08:50:52 -0400 Subject: [PATCH 66/98] desprout --- src/paymentdisclosure.cpp | 9 +++++++++ src/paymentdisclosure.h | 19 +++++++++++++++++++ src/paymentdisclosuredb.cpp | 11 +++++++++++ src/paymentdisclosuredb.h | 21 +++++++++++++++++++++ src/primitives/nonce.cpp | 24 ++++++++++++++++++++++++ src/primitives/nonce.h | 29 +++++++++++++++++++++++++++++ 6 files changed, 113 insertions(+) create mode 100644 src/paymentdisclosure.cpp create mode 100644 src/paymentdisclosure.h create mode 100644 src/paymentdisclosuredb.cpp create mode 100644 src/paymentdisclosuredb.h create mode 100644 src/primitives/nonce.cpp create mode 100644 src/primitives/nonce.h diff --git a/src/paymentdisclosure.cpp b/src/paymentdisclosure.cpp new file mode 100644 index 000000000..d442c40f6 --- /dev/null +++ b/src/paymentdisclosure.cpp @@ -0,0 +1,9 @@ +// Copyright (c) 2017 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "paymentdisclosure.h" + +#include "key_io.h" +#include "util.h" + diff --git a/src/paymentdisclosure.h b/src/paymentdisclosure.h new file mode 100644 index 000000000..9855e1de0 --- /dev/null +++ b/src/paymentdisclosure.h @@ -0,0 +1,19 @@ +#ifndef ZCASH_PAYMENTDISCLOSURE_H +#define ZCASH_PAYMENTDISCLOSURE_H + +#include "uint256.h" +#include "clientversion.h" +#include "serialize.h" +#include "streams.h" +#include "version.h" + +// For JSOutPoint +#include "wallet/wallet.h" + +#include +#include +#include + + +// Ensure that the two different protocol messages, payment disclosure blobs and transactions, +#endif // ZCASH_PAYMENTDISCLOSURE_H diff --git a/src/paymentdisclosuredb.cpp b/src/paymentdisclosuredb.cpp new file mode 100644 index 000000000..559e5688b --- /dev/null +++ b/src/paymentdisclosuredb.cpp @@ -0,0 +1,11 @@ +// Copyright (c) 2017 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "paymentdisclosuredb.h" + +#include "util.h" +#include "dbwrapper.h" + +#include + diff --git a/src/paymentdisclosuredb.h b/src/paymentdisclosuredb.h new file mode 100644 index 000000000..f239c5118 --- /dev/null +++ b/src/paymentdisclosuredb.h @@ -0,0 +1,21 @@ +// Copyright (c) 2017 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef ZCASH_PAYMENTDISCLOSUREDB_H +#define ZCASH_PAYMENTDISCLOSUREDB_H + +#include "paymentdisclosure.h" + +#include +#include +#include +#include +#include + +#include + +#include + + +#endif // ZCASH_PAYMENTDISCLOSUREDB_H diff --git a/src/primitives/nonce.cpp b/src/primitives/nonce.cpp new file mode 100644 index 000000000..a1fbd667d --- /dev/null +++ b/src/primitives/nonce.cpp @@ -0,0 +1,24 @@ +// Copyright (c) 2019 The Hush Developers +// Copyright (c) 2018 Michael Toutonghi +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include "hash.h" +#include "nonce.h" +#include + diff --git a/src/primitives/nonce.h b/src/primitives/nonce.h new file mode 100644 index 000000000..b17a9f01b --- /dev/null +++ b/src/primitives/nonce.h @@ -0,0 +1,29 @@ +// Copyright (c) 2019 Hush Developers +// Copyright (c) 2018 Michael Toutonghi +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#ifndef BITCOIN_PRIMITIVES_NONCE_H +#define BITCOIN_PRIMITIVES_NONCE_H + +#include "serialize.h" +#include "uint256.h" +#include "arith_uint256.h" + + +#endif // BITCOIN_PRIMITIVES_NONCE_H From 89bfb4d4a61150790db9a014e9c0270048b7c814 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 08:51:59 -0400 Subject: [PATCH 67/98] desprout --- src/paymentdisclosure.cpp | 9 --------- src/paymentdisclosure.h | 19 ------------------- src/paymentdisclosuredb.cpp | 11 ----------- src/paymentdisclosuredb.h | 21 --------------------- src/primitives/nonce.cpp | 24 ------------------------ src/primitives/nonce.h | 29 ----------------------------- 6 files changed, 113 deletions(-) delete mode 100644 src/paymentdisclosure.cpp delete mode 100644 src/paymentdisclosure.h delete mode 100644 src/paymentdisclosuredb.cpp delete mode 100644 src/paymentdisclosuredb.h delete mode 100644 src/primitives/nonce.cpp delete mode 100644 src/primitives/nonce.h diff --git a/src/paymentdisclosure.cpp b/src/paymentdisclosure.cpp deleted file mode 100644 index d442c40f6..000000000 --- a/src/paymentdisclosure.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2017 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "paymentdisclosure.h" - -#include "key_io.h" -#include "util.h" - diff --git a/src/paymentdisclosure.h b/src/paymentdisclosure.h deleted file mode 100644 index 9855e1de0..000000000 --- a/src/paymentdisclosure.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ZCASH_PAYMENTDISCLOSURE_H -#define ZCASH_PAYMENTDISCLOSURE_H - -#include "uint256.h" -#include "clientversion.h" -#include "serialize.h" -#include "streams.h" -#include "version.h" - -// For JSOutPoint -#include "wallet/wallet.h" - -#include -#include -#include - - -// Ensure that the two different protocol messages, payment disclosure blobs and transactions, -#endif // ZCASH_PAYMENTDISCLOSURE_H diff --git a/src/paymentdisclosuredb.cpp b/src/paymentdisclosuredb.cpp deleted file mode 100644 index 559e5688b..000000000 --- a/src/paymentdisclosuredb.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2017 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "paymentdisclosuredb.h" - -#include "util.h" -#include "dbwrapper.h" - -#include - diff --git a/src/paymentdisclosuredb.h b/src/paymentdisclosuredb.h deleted file mode 100644 index f239c5118..000000000 --- a/src/paymentdisclosuredb.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2017 The Zcash developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef ZCASH_PAYMENTDISCLOSUREDB_H -#define ZCASH_PAYMENTDISCLOSUREDB_H - -#include "paymentdisclosure.h" - -#include -#include -#include -#include -#include - -#include - -#include - - -#endif // ZCASH_PAYMENTDISCLOSUREDB_H diff --git a/src/primitives/nonce.cpp b/src/primitives/nonce.cpp deleted file mode 100644 index a1fbd667d..000000000 --- a/src/primitives/nonce.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2019 The Hush Developers -// Copyright (c) 2018 Michael Toutonghi -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - -#include "hash.h" -#include "nonce.h" -#include - diff --git a/src/primitives/nonce.h b/src/primitives/nonce.h deleted file mode 100644 index b17a9f01b..000000000 --- a/src/primitives/nonce.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2019 Hush Developers -// Copyright (c) 2018 Michael Toutonghi -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * - * * - * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * - * the top-level directory of this distribution for the individual copyright * - * holder information and the developer policies on copyright and licensing. * - * * - * Unless otherwise agreed in a custom licensing agreement, no part of the * - * SuperNET software, including this file may be copied, modified, propagated * - * or distributed except according to the terms contained in the LICENSE file * - * * - * Removal or modification of this copyright notice is prohibited. * - * * - ******************************************************************************/ - -#ifndef BITCOIN_PRIMITIVES_NONCE_H -#define BITCOIN_PRIMITIVES_NONCE_H - -#include "serialize.h" -#include "uint256.h" -#include "arith_uint256.h" - - -#endif // BITCOIN_PRIMITIVES_NONCE_H From 96c50683e9baca74d0cd23feba43ccc7c1e6baa4 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 09:01:06 -0400 Subject: [PATCH 68/98] Fix the fucking linker bug --- src/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index ec3f562f2..b44dd13c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -340,7 +340,7 @@ libbitcoin_proton_a_SOURCES = \ amqp/amqppublishnotifier.cpp endif -# wallet: zcashd, but only linked when wallet enabled +# wallet: komodod, but only linked when wallet enabled libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ @@ -352,6 +352,7 @@ libbitcoin_wallet_a_SOURCES = \ wallet/asyncrpcoperation_shieldcoinbase.cpp \ wallet/crypter.cpp \ wallet/db.cpp \ + zcash/Note.cpp \ transaction_builder.cpp \ wallet/rpcdump.cpp \ cc/CCtokens.cpp \ From f7a9db724a6180594921c03d5764f0dd385753f9 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 09:24:58 -0400 Subject: [PATCH 69/98] More error detection --- contrib/block_time.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contrib/block_time.pl b/contrib/block_time.pl index dff43ea4e..b4b039a60 100755 --- a/contrib/block_time.pl +++ b/contrib/block_time.pl @@ -9,6 +9,11 @@ my $block = shift || die "Usage: $0 123"; my $hush = "./src/hush-cli"; my $blockcount = qx{$hush getblockcount}; +unless ($blockcount = int($blockcount)) { + print "Invalid response from hush-cli\n"; + exit 1; +} + if ($block <= $blockcount) { die "That block has already happened!"; } else { From cc3ae8164493320a24b165f101444109a28d5ff3 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 09:29:24 -0400 Subject: [PATCH 70/98] 2020 --- contrib/block_time.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/block_time.pl b/contrib/block_time.pl index b4b039a60..17da3c461 100755 --- a/contrib/block_time.pl +++ b/contrib/block_time.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -# Copyright 2019 The Hush developers +# Copyright 2019-2020 The Hush developers # Released under the GPLv3 use warnings; use strict; From 6a4c86e3cd9d477122a0a209623890118123fa4f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 10:14:41 -0400 Subject: [PATCH 71/98] define next hardfork height --- src/komodo_defs.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 6d867b229..97a21969f 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -54,13 +54,19 @@ // Hush Block 166250 will happen at roughly: // Wed Jan 29 08:14:12 2020 Eastern # 1580303652 // Wed Jan 29 13:14:12 2020 GMT # 1580303652 -const uint32_t nHushHardforkHeight = 166250; +const uint32_t nHushHardforkHeight = 166250; +// $ ./contrib/block_time.pl 255555 +// Hush Block 255555 will happen at roughly: +// Sat Jul 11 21:41:12 2020 Eastern # 1594518072 +// Sun Jul 12 01:41:12 2020 GMT # 1594518072 +const uint32_t nHushHardforkHeight2 = 255555; // No coins/code are currently using timestamp activated fork -const uint32_t nHushHardforkTimestamp = 1580303652; // Jan 29nd 1pm GMT +const uint32_t nHushHardforkTimestamp = 1580303652; // Jan 29nd 1pm GMT +const uint32_t nHushHardforkTimestamp2 = 1594425600; // Jul 11th 12a GMT -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nHushHardforkTimestamp, 1751328000}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {1,2,nHushHardforkHeight, 5*nHushHardforkHeight}; +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nHushHardforkTimestamp, nHushHardforkTimestamp2, nHushHardforkTimestamp2*5}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {1,2,nHushHardforkHeight, nHushHardforkHeight2, 5*nHushHardforkHeight2}; // Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = From 2fbcca4167cf41fa7f6f553046a3f113e2b60d14 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 10:14:51 -0400 Subject: [PATCH 72/98] add rescan rpc --- src/rpc/server.h | 1 + src/wallet/rpcdump.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/wallet/rpcwallet.cpp | 3 +++ 3 files changed, 41 insertions(+) diff --git a/src/rpc/server.h b/src/rpc/server.h index 1cd4e993d..6568977d7 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -489,6 +489,7 @@ extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp, const C extern UniValue z_getoperationresult(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp extern UniValue z_listoperationids(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp extern UniValue opreturn_burn(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp +extern UniValue rescan(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcwallet.cpp extern UniValue z_validateaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcmisc.cpp extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp extern UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdisclosure.cpp diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 1499a58b9..72af5d930 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -149,6 +149,43 @@ UniValue convertpassphrase(const UniValue& params, bool fHelp, const CPubKey& my return ret; } +UniValue rescan(const UniValue& params, bool fHelp, const CPubKey& mypk) +{ + //LOCK2(cs_main, pwalletMain->cs_wallet); + + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() > 1) + throw runtime_error( + "rescan \"height\"\n" + "\nRescan all transactions from genesis or given block height.\n" + "\nArguments:\n" + "1. \"height\" (integer, optional) The block height to rescan from\n" + "\nExamples:\n" + "\nRescan from block height 555\n" + + HelpExampleCli("rescan", "\"555\"") + + "\nRescan from genesis block\n" + + HelpExampleCli("rescan","") + ); + + // Height to rescan from + int nRescanHeight = 0; + if (params.size() > 0) + nRescanHeight = params[0].get_int(); + if (nRescanHeight < 0 || nRescanHeight > chainActive.Height()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); + } + + LogPrintf("Rescanning from height=%d\n", nRescanHeight); + //pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight],true); + bool update = false; + pwalletMain->ScanForWalletTransactions(chainActive.Genesis(),update); + //TODO: can we return something more useful? + return NullUniValue; +} + + UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk) { if (!EnsureWalletIsAvailable(fHelp)) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 873d8eb87..867de51a7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -8228,6 +8228,8 @@ extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp, const CPu extern UniValue z_importviewingkey(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue z_exportwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); extern UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); +extern UniValue rescan(const UniValue& params, bool fHelp, const CPubKey& mypk); + static const CRPCCommand commands[] = { // category name actor (function) okSafeMode @@ -8266,6 +8268,7 @@ static const CRPCCommand commands[] = { "wallet", "listunspent", &listunspent, false }, { "wallet", "lockunspent", &lockunspent, true }, { "wallet", "move", &movecmd, false }, + { "wallet", "rescan", &rescan, false }, { "wallet", "sendfrom", &sendfrom, false }, { "wallet", "sendmany", &sendmany, false }, { "wallet", "sendtoaddress", &sendtoaddress, false }, From 3a28e7bab8e10edcf87573844fbef891fae04aac Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 11:09:00 -0400 Subject: [PATCH 73/98] bump version to 3.4.0 --- configure.ac | 4 ++-- src/clientversion.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index cf712cc67..e3be0c9dd 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 3) -define(_CLIENT_VERSION_MINOR, 3) -define(_CLIENT_VERSION_REVISION, 2) +define(_CLIENT_VERSION_MINOR, 4) +define(_CLIENT_VERSION_REVISION, 0) define(_CLIENT_VERSION_BUILD, 50) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) diff --git a/src/clientversion.h b/src/clientversion.h index 71fcee16f..c62e6d3e0 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -33,8 +33,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it // Must be kept in sync with configure.ac ! #define CLIENT_VERSION_MAJOR 3 -#define CLIENT_VERSION_MINOR 3 -#define CLIENT_VERSION_REVISION 2 +#define CLIENT_VERSION_MINOR 4 +#define CLIENT_VERSION_REVISION 0 #define CLIENT_VERSION_BUILD 50 //! Set to true for release, false for prerelease or test build From 717533f7115001bb759742170ef65f93fdc9798f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 11:09:41 -0400 Subject: [PATCH 74/98] Update unix man pages --- doc/man/hush-cli.1 | 8 ++++---- doc/man/hush-tx.1 | 8 ++++---- doc/man/hushd.1 | 18 ++++++++++++++---- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/doc/man/hush-cli.1 b/doc/man/hush-cli.1 index 0c9080b59..5d87d8205 100644 --- a/doc/man/hush-cli.1 +++ b/doc/man/hush-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10. -.TH HUSH-CLI "1" "March 2020" "hush-cli v3.3.2" "User Commands" +.TH HUSH-CLI "1" "June 2020" "hush-cli v3.4.0" "User Commands" .SH NAME -hush-cli \- manual page for hush-cli v3.3.2 +hush-cli \- manual page for hush-cli v3.4.0 .SH DESCRIPTION -Komodo RPC client version v3.3.2\-699b59037 +Komodo RPC client version v3.4.0\-2fbcca416\-dirty .PP In order to ensure you are adequately protecting your privacy when using Hush, please see . @@ -71,7 +71,7 @@ Timeout in seconds during HTTP requests, or 0 for no timeout. (default: Read extra arguments from standard input, one per line until EOF/Ctrl\-D (recommended for sensitive information such as passphrases) .SH COPYRIGHT -Hush Daemon version v3.3.2-699b59037 +Hush Daemon version v3.4.0-2fbcca416-dirty In order to ensure you are adequately protecting your privacy when using Hush, please see . diff --git a/doc/man/hush-tx.1 b/doc/man/hush-tx.1 index 9004dcade..a6d3be7ef 100644 --- a/doc/man/hush-tx.1 +++ b/doc/man/hush-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10. -.TH HUSH-TX "1" "March 2020" "hush-tx v3.3.2" "User Commands" +.TH HUSH-TX "1" "June 2020" "hush-tx v3.4.0" "User Commands" .SH NAME -hush-tx \- manual page for hush-tx v3.3.2 +hush-tx \- manual page for hush-tx v3.4.0 .SH DESCRIPTION -Hush komodo\-tx utility version v3.3.2\-699b59037 +Hush komodo\-tx utility version v3.4.0\-2fbcca416\-dirty .SS "Usage:" .TP komodo\-tx [options] [commands] @@ -84,7 +84,7 @@ set=NAME:JSON\-STRING .IP Set register NAME to given JSON\-STRING .SH COPYRIGHT -Hush Daemon version v3.3.2-699b59037 +Hush Daemon version v3.4.0-2fbcca416-dirty In order to ensure you are adequately protecting your privacy when using Hush, please see . diff --git a/doc/man/hushd.1 b/doc/man/hushd.1 index 0cde080df..6e57386b7 100644 --- a/doc/man/hushd.1 +++ b/doc/man/hushd.1 @@ -1,10 +1,10 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10. -.TH HUSHD "1" "March 2020" "hushd v3.3.2" "User Commands" +.TH HUSHD "1" "June 2020" "hushd v3.4.0" "User Commands" .SH NAME -hushd \- manual page for hushd v3.3.2 +hushd \- manual page for hushd v3.4.0 .SH DESCRIPTION Found binary: ./komodod -Hush Daemon version v3.3.2\-699b59037 +Hush Daemon version v3.4.0\-2fbcca416\-dirty .PP In order to ensure you are adequately protecting your privacy when using Hush, please see . @@ -87,6 +87,11 @@ leave that many cores free, default: 0) .IP Specify pid file (default: komodod.pid) .HP +\fB\-txexpirynotify=\fR +.IP +Execute command when transaction expires (%s in cmd is replaced by +transaction id) +.HP \fB\-prune=\fR .IP Reduce storage requirements by pruning (deleting) old blocks. This mode @@ -295,6 +300,11 @@ Keep the last transactions (default: 200) .IP Keep transactions for at least blocks (default: 10000) .HP +\fB\-opretmintxfee=\fR +.IP +Minimum fee (in KMD/kB) to allow for OP_RETURN transactions (default: +400000) +.HP \fB\-paytxfee=\fR .IP Fee (in KMD/kB) to add to transactions you send (default: 0.00) @@ -629,7 +639,7 @@ Starting supply, default is 0 .IP Enforce transaction\-rate limit, default 0 .SH COPYRIGHT -Hush Daemon version v3.3.2-699b59037 +Hush Daemon version v3.4.0-2fbcca416-dirty In order to ensure you are adequately protecting your privacy when using Hush, please see . From a053d212b8e22d1d8ffe08a2e0955f1854055702 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 21:34:20 -0400 Subject: [PATCH 75/98] Randomize sietch memos and increase min zouts to 3 --- src/wallet/rpcwallet.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 867de51a7..221bef44e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4590,6 +4590,15 @@ UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedO #define CTXIN_SPEND_DUST_SIZE 148 #define CTXOUT_REGULAR_SIZE 34 +void random_hex(char str[], int len) +{ + char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + for(int i=0;iMAX_ZOUTS)) { - fprintf(stderr,"%s: Sietch min zouts must be >=2 and <= 25, setting to default value of %d\n", __FUNCTION__, DEFAULT_MIN_ZOUTS ); + if((MIN_ZOUTSMAX_ZOUTS)) { + fprintf(stderr,"%s: Sietch min zouts must be >=%d and <= %d, setting to default value of %d\n", __FUNCTION__, ABSOLUTE_MIN_ZOUTS, MAX_ZOUTS, DEFAULT_MIN_ZOUTS ); MIN_ZOUTS=DEFAULT_MIN_ZOUTS; } @@ -4739,8 +4748,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) // OK, we identify this xtn as needing privacy zdust, we must decide how much, non-deterministically int nAmount = 0; int decider = 1 + GetRandInt(100); // random int between 1 and 100 - string memo = "f600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - + char *str; + random_hex(str,512); + string memo = string(str); string zdust1, zdust2; // Which zaddr we send to is non-deterministically chosen from two zpools... From a9d04b1e3f7d62c78e4c80f4d9f0e92394947bf9 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 22:38:38 -0400 Subject: [PATCH 76/98] Include z2z fork height in our future seasons --- src/komodo_defs.h | 13 +++++++------ src/main.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 97a21969f..17d276c4e 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019 The Hush developers +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -42,12 +42,12 @@ // KMD Notary Seasons // 1: May 1st 2018 1530921600 // 2: July 15th 2019 1563148800 -> estimated height 1444000 -// 3: 3rd season ending isnt known, so use very far times in future. +// 3: 3rd season // 1751328000 = dummy timestamp, 1 July 2025! // 7113400 = 5x current KMD blockheight. -// to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. +// to add seasons, change NUM_KMD_SEASONS, and add timestamp and height of activation to these arrays. -#define NUM_KMD_SEASONS 5 +#define NUM_KMD_SEASONS 6 #define NUM_KMD_NOTARIES 64 // $ ./contrib/block_time.pl 166250 @@ -64,9 +64,10 @@ const uint32_t nHushHardforkHeight2 = 255555; // No coins/code are currently using timestamp activated fork const uint32_t nHushHardforkTimestamp = 1580303652; // Jan 29nd 1pm GMT const uint32_t nHushHardforkTimestamp2 = 1594425600; // Jul 11th 12a GMT +extern const uint32_t z2zForkHeight; -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nHushHardforkTimestamp, nHushHardforkTimestamp2, nHushHardforkTimestamp2*5}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {1,2,nHushHardforkHeight, nHushHardforkHeight2, 5*nHushHardforkHeight2}; +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nHushHardforkTimestamp, nHushHardforkTimestamp2, nHushHardforkTimestamp2*5, nHushHardforkTimestamp2*6}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {1,2,nHushHardforkHeight, nHushHardforkHeight2, (int)z2zForkHeight, 5*nHushHardforkHeight2}; // Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = diff --git a/src/main.cpp b/src/main.cpp index 291706141..d5afa5baf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,7 +115,7 @@ bool fAlerts = DEFAULT_ALERTS; */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; -unsigned int z2zForkHeight = GetArg("-z2zforkheight",340000); +const uint32_t z2zForkHeight = GetArg("-z2zforkheight",340000); unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; @@ -1735,9 +1735,9 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, int dosLevel) { AssertLockHeld(cs_main); - uint32_t z2zTransitionWindow = 10; - uint32_t z2zTransitionStart = z2zForkHeight - z2zTransitionWindow; - uint32_t nHeight = chainActive.Height(); + const uint32_t z2zTransitionWindow = 10; + const uint32_t z2zTransitionStart = z2zForkHeight - z2zTransitionWindow; + const uint32_t nHeight = chainActive.Height(); // This only applies to HUSH3, other chains can start off z2z via ac_private=1 if(ishush3) { From 500dcabf53536e051751015bc301fde6f6507d3e Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 22:43:08 -0400 Subject: [PATCH 77/98] Fix a compiler warning in cc and add some copyrights --- src/cryptoconditions/src/anon.c | 1 + src/cryptoconditions/src/cryptoconditions.c | 1 + src/cryptoconditions/src/ed25519.c | 1 + src/cryptoconditions/src/eval.c | 1 + src/cryptoconditions/src/internal.h | 1 + src/cryptoconditions/src/json_rpc.c | 1 + src/cryptoconditions/src/prefix.c | 1 + src/cryptoconditions/src/preimage.c | 1 + src/cryptoconditions/src/secp256k1.c | 1 + src/cryptoconditions/src/threshold.c | 1 + src/cryptoconditions/src/utils.c | 5 ++--- 11 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/cryptoconditions/src/anon.c b/src/cryptoconditions/src/anon.c index 6a4de4b0b..a1bd6b4a3 100644 --- a/src/cryptoconditions/src/anon.c +++ b/src/cryptoconditions/src/anon.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/cryptoconditions.c b/src/cryptoconditions/src/cryptoconditions.c index 303b9aa41..6642b0345 100644 --- a/src/cryptoconditions/src/cryptoconditions.c +++ b/src/cryptoconditions/src/cryptoconditions.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/ed25519.c b/src/cryptoconditions/src/ed25519.c index e4d090d1e..33b332071 100644 --- a/src/cryptoconditions/src/ed25519.c +++ b/src/cryptoconditions/src/ed25519.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/eval.c b/src/cryptoconditions/src/eval.c index a18d51202..a017d181d 100644 --- a/src/cryptoconditions/src/eval.c +++ b/src/cryptoconditions/src/eval.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/internal.h b/src/cryptoconditions/src/internal.h index 7cfcaa225..3d24214ce 100644 --- a/src/cryptoconditions/src/internal.h +++ b/src/cryptoconditions/src/internal.h @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/json_rpc.c b/src/cryptoconditions/src/json_rpc.c index 150bcb12b..c4fde8080 100644 --- a/src/cryptoconditions/src/json_rpc.c +++ b/src/cryptoconditions/src/json_rpc.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/prefix.c b/src/cryptoconditions/src/prefix.c index 67dc6f644..ea339df35 100644 --- a/src/cryptoconditions/src/prefix.c +++ b/src/cryptoconditions/src/prefix.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/preimage.c b/src/cryptoconditions/src/preimage.c index a45e621d4..2fee86b88 100644 --- a/src/cryptoconditions/src/preimage.c +++ b/src/cryptoconditions/src/preimage.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/secp256k1.c b/src/cryptoconditions/src/secp256k1.c index 44ff1f0e2..d5319d32b 100644 --- a/src/cryptoconditions/src/secp256k1.c +++ b/src/cryptoconditions/src/secp256k1.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/threshold.c b/src/cryptoconditions/src/threshold.c index e94666c3d..e8e12435e 100644 --- a/src/cryptoconditions/src/threshold.c +++ b/src/cryptoconditions/src/threshold.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * diff --git a/src/cryptoconditions/src/utils.c b/src/cryptoconditions/src/utils.c index ebb2bd143..ac2256f18 100644 --- a/src/cryptoconditions/src/utils.c +++ b/src/cryptoconditions/src/utils.c @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -216,7 +217,7 @@ void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t * ASN_STRUCT_FREE(*asnType, fp); if (rc.encoded < 1) { fprintf(stderr, "Encoding fingerprint failed\n"); - return 0; + return; } sha256(buf, rc.encoded, out); } @@ -299,5 +300,3 @@ int jsonGetHexOptional(const cJSON *params, char *key, char *err, unsigned char } return checkDecodeHex(item, key, err, data, size); } - - From 53172831d8dc5a39aeccdb862b4a1d77ed413601 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Sat, 13 Jun 2020 23:05:51 -0400 Subject: [PATCH 78/98] Delete sprout tests --- qa/pull-tester/rpc-tests.sh | 2 - qa/rpc-tests/zcjoinsplit.py | 59 -------- qa/rpc-tests/zcjoinsplitdoublespend.py | 182 ------------------------- 3 files changed, 243 deletions(-) delete mode 100755 qa/rpc-tests/zcjoinsplit.py delete mode 100755 qa/rpc-tests/zcjoinsplitdoublespend.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 94429cb7f..8c4ad0277 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -64,8 +64,6 @@ testScripts=( 'decodescript.py' 'blockchain.py' 'disablewallet.py' - 'zcjoinsplit.py' - 'zcjoinsplitdoublespend.py' 'ivk_import_export.py' 'zkey_import_export.py' 'getblocktemplate.py' diff --git a/qa/rpc-tests/zcjoinsplit.py b/qa/rpc-tests/zcjoinsplit.py deleted file mode 100755 index b3ca745f8..000000000 --- a/qa/rpc-tests/zcjoinsplit.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python2 - -# -# Test joinsplit semantics -# - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, start_node, \ - gather_inputs - - -class JoinSplitTest(BitcoinTestFramework): - def setup_network(self): - self.nodes = [] - self.is_network_split = False - self.nodes.append(start_node(0, self.options.tmpdir)) - - def run_test(self): - zckeypair = self.nodes[0].zcrawkeygen() - zcsecretkey = zckeypair["zcsecretkey"] - zcaddress = zckeypair["zcaddress"] - - (total_in, inputs) = gather_inputs(self.nodes[0], 40) - protect_tx = self.nodes[0].createrawtransaction(inputs, {}) - joinsplit_result = self.nodes[0].zcrawjoinsplit(protect_tx, {}, {zcaddress:39.99}, 39.99, 0) - - receive_result = self.nodes[0].zcrawreceive(zcsecretkey, joinsplit_result["encryptednote1"]) - assert_equal(receive_result["exists"], False) - - protect_tx = self.nodes[0].signrawtransaction(joinsplit_result["rawtxn"]) - self.nodes[0].sendrawtransaction(protect_tx["hex"]) - self.nodes[0].generate(1) - self.sync_all() - - receive_result = self.nodes[0].zcrawreceive(zcsecretkey, joinsplit_result["encryptednote1"]) - assert_equal(receive_result["exists"], True) - - # The pure joinsplit we create should be mined in the next block - # despite other transactions being in the mempool. - addrtest = self.nodes[0].getnewaddress() - for xx in range(0,10): - self.nodes[0].generate(1) - self.sync_all() - for x in range(0,50): - self.nodes[0].sendtoaddress(addrtest, 0.01); - - joinsplit_tx = self.nodes[0].createrawtransaction([], {}) - joinsplit_result = self.nodes[0].zcrawjoinsplit(joinsplit_tx, {receive_result["note"] : zcsecretkey}, {zcaddress: 39.98}, 0, 0.01) - - self.nodes[0].sendrawtransaction(joinsplit_result["rawtxn"]) - self.nodes[0].generate(1) - self.sync_all() - - print "Done!" - receive_result = self.nodes[0].zcrawreceive(zcsecretkey, joinsplit_result["encryptednote1"]) - assert_equal(receive_result["exists"], True) - -if __name__ == '__main__': - JoinSplitTest().main() diff --git a/qa/rpc-tests/zcjoinsplitdoublespend.py b/qa/rpc-tests/zcjoinsplitdoublespend.py deleted file mode 100755 index b56e7475a..000000000 --- a/qa/rpc-tests/zcjoinsplitdoublespend.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python2 - -# -# Tests a joinsplit double-spend and a subsequent reorg. -# - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal, connect_nodes, \ - gather_inputs, sync_blocks - -import time - -class JoinSplitTest(BitcoinTestFramework): - def setup_network(self): - # Start with split network: - return super(JoinSplitTest, self).setup_network(True) - - def txid_in_mempool(self, node, txid): - exception_triggered = False - - try: - node.getrawtransaction(txid) - except JSONRPCException: - exception_triggered = True - - return not exception_triggered - - def cannot_joinsplit(self, node, txn): - exception_triggered = False - - try: - node.sendrawtransaction(txn) - except JSONRPCException: - exception_triggered = True - - return exception_triggered - - def expect_cannot_joinsplit(self, node, txn): - assert_equal(self.cannot_joinsplit(node, txn), True) - - def run_test(self): - # All nodes should start with 250 HUSH: - starting_balance = 250 - for i in range(4): - assert_equal(self.nodes[i].getbalance(), starting_balance) - self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! - - # Generate zcaddress keypairs - zckeypair = self.nodes[0].zcrawkeygen() - zcsecretkey = zckeypair["zcsecretkey"] - zcaddress = zckeypair["zcaddress"] - - pool = [0, 1, 2, 3] - for i in range(4): - (total_in, inputs) = gather_inputs(self.nodes[i], 40) - pool[i] = self.nodes[i].createrawtransaction(inputs, {}) - pool[i] = self.nodes[i].zcrawjoinsplit(pool[i], {}, {zcaddress:39.99}, 39.99, 0) - signed = self.nodes[i].signrawtransaction(pool[i]["rawtxn"]) - - # send the tx to both halves of the network - self.nodes[0].sendrawtransaction(signed["hex"]) - self.nodes[0].generate(1) - self.nodes[2].sendrawtransaction(signed["hex"]) - self.nodes[2].generate(1) - pool[i] = pool[i]["encryptednote1"] - - sync_blocks(self.nodes[0:2]) - sync_blocks(self.nodes[2:4]) - - # Confirm that the protects have taken place - for i in range(4): - enc_note = pool[i] - receive_result = self.nodes[0].zcrawreceive(zcsecretkey, enc_note) - assert_equal(receive_result["exists"], True) - pool[i] = receive_result["note"] - - # Extra confirmations - receive_result = self.nodes[1].zcrawreceive(zcsecretkey, enc_note) - assert_equal(receive_result["exists"], True) - - receive_result = self.nodes[2].zcrawreceive(zcsecretkey, enc_note) - assert_equal(receive_result["exists"], True) - - receive_result = self.nodes[3].zcrawreceive(zcsecretkey, enc_note) - assert_equal(receive_result["exists"], True) - - blank_tx = self.nodes[0].createrawtransaction([], {}) - # Create joinsplit {A, B}->{*} - joinsplit_AB = self.nodes[0].zcrawjoinsplit(blank_tx, - {pool[0] : zcsecretkey, pool[1] : zcsecretkey}, - {zcaddress:(39.99*2)-0.01}, - 0, 0.01) - - # Create joinsplit {B, C}->{*} - joinsplit_BC = self.nodes[0].zcrawjoinsplit(blank_tx, - {pool[1] : zcsecretkey, pool[2] : zcsecretkey}, - {zcaddress:(39.99*2)-0.01}, - 0, 0.01) - - # Create joinsplit {C, D}->{*} - joinsplit_CD = self.nodes[0].zcrawjoinsplit(blank_tx, - {pool[2] : zcsecretkey, pool[3] : zcsecretkey}, - {zcaddress:(39.99*2)-0.01}, - 0, 0.01) - - # Create joinsplit {A, D}->{*} - joinsplit_AD = self.nodes[0].zcrawjoinsplit(blank_tx, - {pool[0] : zcsecretkey, pool[3] : zcsecretkey}, - {zcaddress:(39.99*2)-0.01}, - 0, 0.01) - - # (a) Node 0 will spend joinsplit AB, then attempt to - # double-spend it with BC. It should fail before and - # after Node 0 mines blocks. - # - # (b) Then, Node 2 will spend BC, and mine 5 blocks. - # Node 1 connects, and AB will be reorg'd from the chain. - # Any attempts to spend AB or CD should fail for - # both nodes. - # - # (c) Then, Node 0 will spend AD, which should work - # because the previous spend for A (AB) is considered - # invalid due to the reorg. - - # (a) - - AB_txid = self.nodes[0].sendrawtransaction(joinsplit_AB["rawtxn"]) - - self.expect_cannot_joinsplit(self.nodes[0], joinsplit_BC["rawtxn"]) - - # Wait until node[1] receives AB before we attempt to double-spend - # with BC. - print "Waiting for AB_txid...\n" - while True: - if self.txid_in_mempool(self.nodes[1], AB_txid): - break - time.sleep(0.2) - print "Done!\n" - - self.expect_cannot_joinsplit(self.nodes[1], joinsplit_BC["rawtxn"]) - - # Generate a block - self.nodes[0].generate(1) - sync_blocks(self.nodes[0:2]) - - self.expect_cannot_joinsplit(self.nodes[0], joinsplit_BC["rawtxn"]) - self.expect_cannot_joinsplit(self.nodes[1], joinsplit_BC["rawtxn"]) - - # (b) - self.nodes[2].sendrawtransaction(joinsplit_BC["rawtxn"]) - self.nodes[2].generate(5) - - # Connect the two nodes - - connect_nodes(self.nodes[1], 2) - sync_blocks(self.nodes) - - # AB and CD should all be impossible to spend for each node. - self.expect_cannot_joinsplit(self.nodes[0], joinsplit_AB["rawtxn"]) - self.expect_cannot_joinsplit(self.nodes[0], joinsplit_CD["rawtxn"]) - - self.expect_cannot_joinsplit(self.nodes[1], joinsplit_AB["rawtxn"]) - self.expect_cannot_joinsplit(self.nodes[1], joinsplit_CD["rawtxn"]) - - self.expect_cannot_joinsplit(self.nodes[2], joinsplit_AB["rawtxn"]) - self.expect_cannot_joinsplit(self.nodes[2], joinsplit_CD["rawtxn"]) - - self.expect_cannot_joinsplit(self.nodes[3], joinsplit_AB["rawtxn"]) - self.expect_cannot_joinsplit(self.nodes[3], joinsplit_CD["rawtxn"]) - - # (c) - # AD should be possible to send due to the reorg that - # tossed out AB. - - self.nodes[0].sendrawtransaction(joinsplit_AD["rawtxn"]) - self.nodes[0].generate(1) - - sync_blocks(self.nodes) - -if __name__ == '__main__': - JoinSplitTest().main() From ede0f21e6745fe2368dfc91bd8b2f231d9cabecd Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 09:32:48 -0400 Subject: [PATCH 79/98] desprout --- qa/pull-tester/rpc-tests.sh | 2 - qa/rpc-tests/p2p_nu_peer_management.py | 192 ------------------------- qa/rpc-tests/wallet_listnotes.py | 81 +---------- 3 files changed, 1 insertion(+), 274 deletions(-) delete mode 100755 qa/rpc-tests/p2p_nu_peer_management.py diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 8c4ad0277..35bf5a7e9 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -23,7 +23,6 @@ testScripts=( 'wallet_changeindicator.py' 'wallet_import_export.py' 'wallet_protectcoinbase.py' - 'wallet_shieldcoinbase_sprout.py' 'wallet_shieldcoinbase_sapling.py' 'wallet_listreceived.py' 'wallet_mergetoaddress.py' @@ -69,7 +68,6 @@ testScripts=( 'getblocktemplate.py' 'bip65-cltv-p2p.py' 'bipdersig-p2p.py' - 'p2p_nu_peer_management.py' 'rewind_index.py' 'p2p_txexpiry_dos.py' 'p2p_node_bloom.py' diff --git a/qa/rpc-tests/p2p_nu_peer_management.py b/qa/rpc-tests/p2p_nu_peer_management.py deleted file mode 100755 index 6cedf66bb..000000000 --- a/qa/rpc-tests/p2p_nu_peer_management.py +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/env python2 -# Copyright (c) 2018 The Zcash developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -from test_framework.mininode import ( - NodeConn, - NodeConnCB, - NetworkThread, - msg_ping, - SPROUT_PROTO_VERSION, - OVERWINTER_PROTO_VERSION, - SAPLING_PROTO_VERSION, -) -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import initialize_chain_clean, start_nodes, \ - p2p_port, assert_equal - -import time - -# -# In this test we connect Sprout, Overwinter, and Sapling mininodes to a Zcashd -# node which will activate Overwinter at block 10 and Sapling at block 15. -# -# We test: -# 1. the mininodes stay connected to Zcash with Sprout consensus rules -# 2. when Overwinter activates, the Sprout mininodes are dropped -# 3. new Overwinter and Sapling nodes can connect to Zcash -# 4. new Sprout nodes cannot connect to Zcash -# 5. when Sapling activates, the Overwinter mininodes are dropped -# 6. new Sapling nodes can connect to Zcash -# 7. new Sprout and Overwinter nodes cannot connect to Zcash -# -# This test *does not* verify that prior to each activation, the Zcashd -# node will prefer connections with NU-aware nodes, with an eviction process -# that prioritizes non-NU-aware connections. -# - - -class TestManager(NodeConnCB): - def __init__(self): - NodeConnCB.__init__(self) - self.create_callback_map() - - def on_close(self, conn): - pass - - def on_reject(self, conn, message): - conn.rejectMessage = message - - -class NUPeerManagementTest(BitcoinTestFramework): - - def setup_chain(self): - print "Initializing test directory "+self.options.tmpdir - initialize_chain_clean(self.options.tmpdir, 1) - - def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, extra_args=[[ - '-nuparams=5ba81b19:10', # Overwinter - '-nuparams=76b809bb:15', # Sapling - '-debug', - '-whitelist=127.0.0.1', - ]]) - - def run_test(self): - test = TestManager() - - # Launch Sprout, Overwinter, and Sapling mininodes - nodes = [] - for x in xrange(10): - nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], - test, "regtest", SPROUT_PROTO_VERSION)) - nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], - test, "regtest", OVERWINTER_PROTO_VERSION)) - nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], - test, "regtest", SAPLING_PROTO_VERSION)) - - # Start up network handling in another thread - NetworkThread().start() - - # Sprout consensus rules apply at block height 9 - self.nodes[0].generate(9) - assert_equal(9, self.nodes[0].getblockcount()) - - # Verify mininodes are still connected to zcashd node - peerinfo = self.nodes[0].getpeerinfo() - versions = [x["version"] for x in peerinfo] - assert_equal(10, versions.count(SPROUT_PROTO_VERSION)) - assert_equal(10, versions.count(OVERWINTER_PROTO_VERSION)) - assert_equal(10, versions.count(SAPLING_PROTO_VERSION)) - - # Overwinter consensus rules activate at block height 10 - self.nodes[0].generate(1) - assert_equal(10, self.nodes[0].getblockcount()) - print('Overwinter active') - - # Mininodes send ping message to zcashd node. - pingCounter = 1 - for node in nodes: - node.send_message(msg_ping(pingCounter)) - pingCounter = pingCounter + 1 - - time.sleep(3) - - # Verify Sprout mininodes have been dropped, while Overwinter and - # Sapling mininodes are still connected. - peerinfo = self.nodes[0].getpeerinfo() - versions = [x["version"] for x in peerinfo] - assert_equal(0, versions.count(SPROUT_PROTO_VERSION)) - assert_equal(10, versions.count(OVERWINTER_PROTO_VERSION)) - assert_equal(10, versions.count(SAPLING_PROTO_VERSION)) - - # Extend the Overwinter chain with another block. - self.nodes[0].generate(1) - - # Connect a new Overwinter mininode to the zcashd node, which is accepted. - nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", OVERWINTER_PROTO_VERSION)) - time.sleep(3) - assert_equal(21, len(self.nodes[0].getpeerinfo())) - - # Connect a new Sapling mininode to the zcashd node, which is accepted. - nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SAPLING_PROTO_VERSION)) - time.sleep(3) - assert_equal(22, len(self.nodes[0].getpeerinfo())) - - # Try to connect a new Sprout mininode to the zcashd node, which is rejected. - sprout = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SPROUT_PROTO_VERSION) - nodes.append(sprout) - time.sleep(3) - assert("Version must be 170003 or greater" in str(sprout.rejectMessage)) - - # Verify that only Overwinter and Sapling mininodes are connected. - peerinfo = self.nodes[0].getpeerinfo() - versions = [x["version"] for x in peerinfo] - assert_equal(0, versions.count(SPROUT_PROTO_VERSION)) - assert_equal(11, versions.count(OVERWINTER_PROTO_VERSION)) - assert_equal(11, versions.count(SAPLING_PROTO_VERSION)) - - # Sapling consensus rules activate at block height 15 - self.nodes[0].generate(4) - assert_equal(15, self.nodes[0].getblockcount()) - print('Sapling active') - - # Mininodes send ping message to zcashd node. - pingCounter = 1 - for node in nodes: - node.send_message(msg_ping(pingCounter)) - pingCounter = pingCounter + 1 - - time.sleep(3) - - # Verify Sprout and Overwinter mininodes have been dropped, while - # Sapling mininodes are still connected. - peerinfo = self.nodes[0].getpeerinfo() - versions = [x["version"] for x in peerinfo] - assert_equal(0, versions.count(SPROUT_PROTO_VERSION)) - assert_equal(0, versions.count(OVERWINTER_PROTO_VERSION)) - assert_equal(11, versions.count(SAPLING_PROTO_VERSION)) - - # Extend the Sapling chain with another block. - self.nodes[0].generate(1) - - # Connect a new Sapling mininode to the zcashd node, which is accepted. - nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SAPLING_PROTO_VERSION)) - time.sleep(3) - assert_equal(12, len(self.nodes[0].getpeerinfo())) - - # Try to connect a new Sprout mininode to the zcashd node, which is rejected. - sprout = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SPROUT_PROTO_VERSION) - nodes.append(sprout) - time.sleep(3) - assert("Version must be 170006 or greater" in str(sprout.rejectMessage)) - - # Try to connect a new Overwinter mininode to the zcashd node, which is rejected. - sprout = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", OVERWINTER_PROTO_VERSION) - nodes.append(sprout) - time.sleep(3) - assert("Version must be 170006 or greater" in str(sprout.rejectMessage)) - - # Verify that only Sapling mininodes are connected. - peerinfo = self.nodes[0].getpeerinfo() - versions = [x["version"] for x in peerinfo] - assert_equal(0, versions.count(SPROUT_PROTO_VERSION)) - assert_equal(0, versions.count(OVERWINTER_PROTO_VERSION)) - assert_equal(12, versions.count(SAPLING_PROTO_VERSION)) - - for node in nodes: - node.disconnect_node() - -if __name__ == '__main__': - NUPeerManagementTest().main() diff --git a/qa/rpc-tests/wallet_listnotes.py b/qa/rpc-tests/wallet_listnotes.py index 5cd89c661..90fbcced1 100755 --- a/qa/rpc-tests/wallet_listnotes.py +++ b/qa/rpc-tests/wallet_listnotes.py @@ -1,4 +1,5 @@ #!/usr/bin/env python2 +# Copyright (c) 2019-2020 The Hush developers # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -20,89 +21,9 @@ class WalletListNotes(BitcoinTestFramework): def run_test(self): # Current height = 200 -> Sprout assert_equal(200, self.nodes[0].getblockcount()) - sproutzaddr = self.nodes[0].z_getnewaddress('sprout') # test that we can create a sapling zaddr before sapling activates saplingzaddr = self.nodes[0].z_getnewaddress('sapling') - - # we've got lots of coinbase (taddr) but no shielded funds yet - assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private'])) - - # Set current height to 201 -> Sprout - self.nodes[0].generate(1) - self.sync_all() - assert_equal(201, self.nodes[0].getblockcount()) - - mining_addr = self.nodes[0].listunspent()[0]['address'] - - # Shield coinbase funds (must be a multiple of 10, no change allowed pre-sapling) - receive_amount_10 = Decimal('10.0') - Decimal('0.0001') - recipients = [{"address":sproutzaddr, "amount":receive_amount_10}] - myopid = self.nodes[0].z_sendmany(mining_addr, recipients) - txid_1 = wait_and_assert_operationid_status(self.nodes[0], myopid) - self.sync_all() - - # No funds (with (default) one or more confirmations) in sproutzaddr yet - assert_equal(0, len(self.nodes[0].z_listunspent())) - assert_equal(0, len(self.nodes[0].z_listunspent(1))) - - # no private balance because no confirmations yet - assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private'])) - - # list private unspent, this time allowing 0 confirmations - unspent_cb = self.nodes[0].z_listunspent(0) - assert_equal(1, len(unspent_cb)) - assert_equal(False, unspent_cb[0]['change']) - assert_equal(txid_1, unspent_cb[0]['txid']) - assert_equal(True, unspent_cb[0]['spendable']) - assert_equal(sproutzaddr, unspent_cb[0]['address']) - assert_equal(receive_amount_10, unspent_cb[0]['amount']) - - # list unspent, filtering by address, should produce same result - unspent_cb_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr]) - assert_equal(unspent_cb, unspent_cb_filter) - - # Generate a block to confirm shield coinbase tx - self.nodes[0].generate(1) - self.sync_all() - - # Current height = 202 -> Overwinter. Default address type remains Sprout - assert_equal(202, self.nodes[0].getblockcount()) - - # Send 1.0 (actually 0.9999) from sproutzaddr to a new zaddr - sproutzaddr2 = self.nodes[0].z_getnewaddress() - receive_amount_1 = Decimal('1.0') - Decimal('0.0001') - change_amount_9 = receive_amount_10 - Decimal('1.0') - assert_equal('sprout', self.nodes[0].z_validateaddress(sproutzaddr2)['type']) - recipients = [{"address": sproutzaddr2, "amount":receive_amount_1}] - myopid = self.nodes[0].z_sendmany(sproutzaddr, recipients) - txid_2 = wait_and_assert_operationid_status(self.nodes[0], myopid) - self.sync_all() - - # list unspent, allowing 0conf txs - unspent_tx = self.nodes[0].z_listunspent(0) - assert_equal(len(unspent_tx), 2) - # sort low-to-high by amount (order of returned entries is not guaranteed) - unspent_tx = sorted(unspent_tx, key=lambda k: k['amount']) - assert_equal(False, unspent_tx[0]['change']) - assert_equal(txid_2, unspent_tx[0]['txid']) - assert_equal(True, unspent_tx[0]['spendable']) - assert_equal(sproutzaddr2, unspent_tx[0]['address']) - assert_equal(receive_amount_1, unspent_tx[0]['amount']) - - assert_equal(True, unspent_tx[1]['change']) - assert_equal(txid_2, unspent_tx[1]['txid']) - assert_equal(True, unspent_tx[1]['spendable']) - assert_equal(sproutzaddr, unspent_tx[1]['address']) - assert_equal(change_amount_9, unspent_tx[1]['amount']) - - unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr2]) - assert_equal(1, len(unspent_tx_filter)) - assert_equal(unspent_tx[0], unspent_tx_filter[0]) - - unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr]) - assert_equal(1, len(unspent_tx_filter)) - assert_equal(unspent_tx[1], unspent_tx_filter[0]) # Set current height to 204 -> Sapling self.nodes[0].generate(2) From 9b6bc6cf1437e72711e458b3bad77e44b39a5ccd Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 09:34:30 -0400 Subject: [PATCH 80/98] desprout --- qa/rpc-tests/regtest_signrawtransaction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qa/rpc-tests/regtest_signrawtransaction.py b/qa/rpc-tests/regtest_signrawtransaction.py index 2e0273677..78ec1fbc8 100755 --- a/qa/rpc-tests/regtest_signrawtransaction.py +++ b/qa/rpc-tests/regtest_signrawtransaction.py @@ -1,4 +1,5 @@ #!/usr/bin/env python2 +# Copyright (c) 2019-2020 The Hush developers # Copyright (c) 2018 The Zcash developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -18,7 +19,7 @@ class RegtestSignrawtransactionTest (BitcoinTestFramework): self.nodes[0].generate(1) self.sync_all() taddr = self.nodes[1].getnewaddress() - zaddr1 = self.nodes[1].z_getnewaddress('sprout') + zaddr1 = self.nodes[1].z_getnewaddress('sapling') self.nodes[0].sendtoaddress(taddr, 2.0) self.nodes[0].generate(1) From b5c9453129d68a7bd4537bdfeb7114aa28b7fcf9 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 10:46:25 -0400 Subject: [PATCH 81/98] Declare S4 to have happened already. This is now now --- src/komodo_defs.h | 8 +++----- src/komodo_notary.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 17d276c4e..423d556d0 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -55,11 +55,9 @@ // Wed Jan 29 08:14:12 2020 Eastern # 1580303652 // Wed Jan 29 13:14:12 2020 GMT # 1580303652 const uint32_t nHushHardforkHeight = 166250; -// $ ./contrib/block_time.pl 255555 -// Hush Block 255555 will happen at roughly: -// Sat Jul 11 21:41:12 2020 Eastern # 1594518072 -// Sun Jul 12 01:41:12 2020 GMT # 1594518072 -const uint32_t nHushHardforkHeight2 = 255555; +// $ ./contrib/block_time.pl 245555 +// Hush Block 245555 will happen at roughly... now +const uint32_t nHushHardforkHeight2 = 245055; // No coins/code are currently using timestamp activated fork const uint32_t nHushHardforkTimestamp = 1580303652; // Jan 29nd 1pm GMT diff --git a/src/komodo_notary.h b/src/komodo_notary.h index 8114a86af..d5591aa29 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019 The Hush developers +// Copyright (c) 2019-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * From 07d7aacd901d7d40a30ecee9e3219fabc46c331a Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 11:24:12 -0400 Subject: [PATCH 82/98] destake --- src/komodo_defs.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 423d556d0..3a4af6f48 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -34,9 +34,6 @@ #define KOMODO_FIRSTFUNGIBLEID 100 #define KOMODO_SAPLING_ACTIVATION 1544832000 // Dec 15th, 2018 #define KOMODO_SAPLING_DEADLINE 1550188800 // Feb 15th, 2019 -#define ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX 57 -#define ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF 27 -#define ASSETCHAINS_STAKED_MIN_POW_DIFF 536900000 // 537000000 537300000 #define _COINBASE_MATURITY 100 // KMD Notary Seasons From 40f68d0d0581aab8eaba17ec19c3a3b689cb7f6b Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 11:43:18 -0400 Subject: [PATCH 83/98] HUSH dpow --- src/komodo_defs.h | 74 +++++++++-------------------------------------- 1 file changed, 14 insertions(+), 60 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 3a4af6f48..0b51c09af 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -333,71 +333,25 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"decker_AR", "02a85540db8d41c7e60bf0d33d1364b4151cad883dd032878ea4c037f67b769635" } }, { - // Season 4 https://github.com/KomodoPlatform/dPoW/blob/s4/iguana/3rd_party - {"alien_AR", "024f20c096b085308e21893383f44b4faf1cdedea9ad53cc7d7e7fbfa0c30c1e71" }, - {"alien_EU", "022b85908191788f409506ebcf96a892f3274f352864c3ed566c5a16de63953236" }, - {"alien_NA", "022f62b56ddfd07c9860921c701285ac39bb3ac8f6f083d1b59c8f4943be3de162" }, - {"alright_DEV", "03b6f9493658bdd102503585a08ae642b49d6a68fb69ac3626f9737cd7581abdfa" }, - {"artemii235_DEV", "037a20916d2e9ea575300ac9d729507c23a606b9a200c8e913d7c9832f912a1fa7" }, - {"chainmakers_NA", "028803e07bcc521fde264b7191a944f9b3612e8ee4e24a99bcd903f6976240839a" }, - {"chainzilla_SH", "0311dde03c2dd654ce78323b718ed3ad73a464d1bde97820f3395f54788b5420dd" }, - {"chmex_AR", "030cd487e10fbf142e0e8d582e702ecb775f378569c3cb5acd0ff97b6b12803588" }, - {"chmex_EU", "030bf7bd7ad0515c33b5d5d9a91e0729baf801b9002f80495ae535ea1cebb352cb" }, + // Season 4 HUSH notaries. A new DPoW network is born. {"cipi_EU", "026f4f66385daaf8313ef30ffe4988e7db497132682dca185a70763d93e1417d9d" }, {"cipi_NA", "03f4e69edcb4fa3b2095cb8cb1ca010f4ec4972eac5d8822397e5c8d87aa21a739" }, - {"daemonfox_NA", "023c7584b1006d4a62a4b4c9c1ede390a3789316547897d5ed49ff9385a3acb411" }, - {"dappvader_SH", "025199bc04bcb8a17976d9fe8bc87763a6150c2727321aa59bf34a2b49f2f3a0ce" }, - {"decker_AR", "02a85540db8d41c7e60bf0d33d1364b4151cad883dd032878ea4c037f67b769635" }, - {"decker_DEV", "02fca8ee50e49f480de275745618db7b0b3680b0bdcce7dcae7d2e0fd5c3345744" }, - {"decker_EU", "027777775b89ff548c3be54fb0c9455437d87f38bfce83bdef113899881b219c9e" }, - {"dragonhound_NA", "029912212d370ee0fb4d38eefd8bfcd8ab04e2c3b0354020789c29ddf2a35c72d6" }, - {"dudezmobi_AR", "033c121d3f8d450174674a73f3b7f140b2717a7d51ea19ee597e2e8e8f9d5ed87f" }, - {"etszombi_AR", "03bfcbca83f11e622fa4eed9a1fa25dba377981ea3b22e3d0a4015f9a932af9272" }, - {"etszombi_EU", "03a5c083c78ba397970f20b544a01c13e7ed36ca8a5ae26d5fe7bd38b92b6a0c94" }, - {"fullmoon_AR", "03639bc56d3fecf856f17759a441c5893668e7c2d460f3d216798a413cd6766bb2" }, - {"fullmoon_NA", "03e388bcc579ac2675f8fadfa921eec186dcea8d2b43de1eed6caba23d5a962b74" }, - {"fullmoon_SH", "03a5cfda2b097c808834ccdd805828c811b519611feabdfe6b3644312e53f6748f" }, - {"gcharang_SH", "02a654037d12cdd609f4fad48e15ec54538e03f61fdae1acb855f16ebacac6bd73" }, - {"greer_NA", "0262da6aaa0b295b8e2f120035924758a4a630f899316dc63ee15ef03e9b7b2b23" }, - {"indenodes_AR", "0242778789986d614f75bcf629081651b851a12ab1cc10c73995b27b90febb75a2" }, - {"indenodes_EU", "03a416533cace0814455a1bb1cd7861ce825a543c6f6284a432c4c8d8875b7ace9" }, - {"indenodes_NA", "02b3908eda4078f0e9b6704451cdc24d418e899c0f515fab338d7494da6f0a647b" }, - {"indenodes_SH", "031d1584cf0eb4a2d314465e49e2677226b1615c3718013b8d6b4854c15676a58c" }, - {"karasugoi_NA", "02f803e6f159824a181cc5d709f3d1e7ff65f19e1899920724aeb4e3d2d869f911" }, - {"madmax_AR", "027afddbcf690230dd8d435ec16a7bfb0083e6b77030f763437f291dfc40a579d0" }, - {"madmax_EU", "0397ec3a4ad84b3009566d260c89f1c4404e86e5d044964747c9371277e38f5995" }, - {"madmax_NA", "036d3afebe1eab09f4c38c3ee6a4659ad390f3df92787c11437a58c59a29e408e6" }, - {"marmarachain_AR", "028690ca1e3afdf8a38b421f6a41f5ff407afc96d5a7a6a488330aae26c8b086bb" }, - {"mcrypt_SH", "027a4ca7b11d3456ff558c08bb04483a89c7f383448461fd0b6b3b07424aabe9a4" }, - {"metaphilibert_AR", "0239e34ad22957bbf4c8df824401f237b2afe8d40f7a645ecd43e8f27dde1ab0da" }, - {"metaphilibert_SH", "03b21ff042bf1730b28bde43f44c064578b41996117ac7634b567c3773089e3be3" }, - {"mihailo_EU", "036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252" }, - {"mrlynch_AR", "03e67440141f53a08684c329ebc852b018e41f905da88e52aa4a6dc5aa4b12447a" }, - {"mylo_SH", "026d5f29d09ff3f33e14db4811606249b2438c6bcf964876714f81d1f2d952acde" }, {"node9_EU", "0392e4c9400e69f28c6b9e89d586da69d5a6af7702f1045eaa6ebc1996f0496e1f" }, - {"nodeone_NA", "0310a249c6c2dcc29f2135715138a9ddb8e01c0eab701cbd0b96d9cec660dbdc58" }, - {"nutellalicka_SH", "0284c4d3cb97dd8a32d10fb32b1855ae18cf845dad542e3b8937ca0e998fb54ecc" }, - {"oszy_EU", "03c53bd421de4a29ce68c8cc83f802e1181e77c08f8f16684490d61452ea8d023a" }, - {"patchkez_SH", "028c08db6e7242681f50db6c234fe3d6e12fb1a915350311be26373bac0d457d49" }, - {"pbca26_NA", "03c18431bb6bc95672f640f19998a196becd2851d5dcba4795fe8d85b7d77eab81" }, - {"peer2cloud_AR", "0243958faf9ae4d43b598b859ddc595c170c4cf50f8e4517d660ae5bc72aeb821b" }, - {"phba2061_EU", "03369187ce134bd7793ee34af7756fe1ab27202e09306491cdd5d8ad2c71697937" }, {"phm87_SH", "03889a10f9df2caef57220628515693cf25316fe1b0693b0241419e75d0d0e66ed" }, - {"pirate_EU", "0240011b95cde819f298fe0f507b2260c9fecdab784924076d4d1e54c522103cb1" }, - {"pirate_NA", "02ad7ef25d2dd461e361120cd3efe7cbce5e9512c361e9185aac33dd303d758613" }, - {"pungocloud_SH", "02641c36ae6747b88150a463a1fe65cf7a9d1c00a64387c73f296f0b64e77c7d3f" }, - {"smdmitry_AR", "0397b7584cb29717b721c0c587d4462477efc1f36a56921f133c9d17b0cd7f278a" }, - {"starfleet_EU", "03c6e047218f34644ccba67e317b9da5d28e68bbbb6b9973aef1281d2bafa46496" }, - {"strob_NA", "02285bf2f9e96068ecac14bc6f770e394927b4da9f5ba833eaa9468b5d47f203a3" }, - {"strob_SH", "0213751a1c59d3489ca85b3d62a3d606dcef7f0428aa021c1978ea16fb38a2fad6" }, - {"swisscertifiers_EU", "02e7722ebba9f8b5ebfb4e87d4fa58cc75aef677535b9cfc060c7d9471aacd9c9e" }, - {"titomane_AR", "03958bd8d13fe6946b8d0d0fbbc3861c72542560d0276e80a4c6b5fe55bc758b81" }, - {"titomane_EU", "02276090e483db1a01a802456b10831b3b6e0a6ad3ece9b2a01f4aad0e480c8edc" }, - {"titomane_SH", "02abf206bafc8048dbdc042b8eb6b1e356ea5dbe149eae3532b4811d4905e5cf01" }, - {"tonyl_AR", "0229e499e3f2e065ced402ceb8aaf3d5ab8bd3793aa074305e9fa30772ce604908" }, - {"tonyl_DEV", "0258b77d7dcfc6c2628b0b6b438951a6e74201fb2cd180a795e4c37fcf8e78a678" }, {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"zatjum_SH", "0241c5660ca540780be66603b1791127a1261d56abbcb7562c297eec8e4fc078fb" } + + //TODO: placeholders so we have 16 NNs, details to be filled soon + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, } }; From 94134862e5c9021eb86dab1dcb071521287b03c8 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 11:44:38 -0400 Subject: [PATCH 84/98] try to make linker happy --- src/cc/cclib.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index 364953148..e8b4a32b2 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -1,3 +1,4 @@ +// Copyright © 2019-2020 The Hush Developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -34,6 +35,9 @@ #define EVAL_ROGUE 17 std::string MYCCLIBNAME = (char *)"rogue"; +extern const uint32_t z2zForkHeight; + + #elif BUILD_CUSTOMCC #include "customcc.h" From 0c5923d7492f3d5452eeb5b9bc62479c0a1a77d9 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 12:04:12 -0400 Subject: [PATCH 85/98] Revert "HUSH dpow" This reverts commit 40f68d0d0581aab8eaba17ec19c3a3b689cb7f6b. --- src/komodo_defs.h | 74 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 14 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 0b51c09af..3a4af6f48 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -333,25 +333,71 @@ static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = {"decker_AR", "02a85540db8d41c7e60bf0d33d1364b4151cad883dd032878ea4c037f67b769635" } }, { - // Season 4 HUSH notaries. A new DPoW network is born. + // Season 4 https://github.com/KomodoPlatform/dPoW/blob/s4/iguana/3rd_party + {"alien_AR", "024f20c096b085308e21893383f44b4faf1cdedea9ad53cc7d7e7fbfa0c30c1e71" }, + {"alien_EU", "022b85908191788f409506ebcf96a892f3274f352864c3ed566c5a16de63953236" }, + {"alien_NA", "022f62b56ddfd07c9860921c701285ac39bb3ac8f6f083d1b59c8f4943be3de162" }, + {"alright_DEV", "03b6f9493658bdd102503585a08ae642b49d6a68fb69ac3626f9737cd7581abdfa" }, + {"artemii235_DEV", "037a20916d2e9ea575300ac9d729507c23a606b9a200c8e913d7c9832f912a1fa7" }, + {"chainmakers_NA", "028803e07bcc521fde264b7191a944f9b3612e8ee4e24a99bcd903f6976240839a" }, + {"chainzilla_SH", "0311dde03c2dd654ce78323b718ed3ad73a464d1bde97820f3395f54788b5420dd" }, + {"chmex_AR", "030cd487e10fbf142e0e8d582e702ecb775f378569c3cb5acd0ff97b6b12803588" }, + {"chmex_EU", "030bf7bd7ad0515c33b5d5d9a91e0729baf801b9002f80495ae535ea1cebb352cb" }, {"cipi_EU", "026f4f66385daaf8313ef30ffe4988e7db497132682dca185a70763d93e1417d9d" }, {"cipi_NA", "03f4e69edcb4fa3b2095cb8cb1ca010f4ec4972eac5d8822397e5c8d87aa21a739" }, + {"daemonfox_NA", "023c7584b1006d4a62a4b4c9c1ede390a3789316547897d5ed49ff9385a3acb411" }, + {"dappvader_SH", "025199bc04bcb8a17976d9fe8bc87763a6150c2727321aa59bf34a2b49f2f3a0ce" }, + {"decker_AR", "02a85540db8d41c7e60bf0d33d1364b4151cad883dd032878ea4c037f67b769635" }, + {"decker_DEV", "02fca8ee50e49f480de275745618db7b0b3680b0bdcce7dcae7d2e0fd5c3345744" }, + {"decker_EU", "027777775b89ff548c3be54fb0c9455437d87f38bfce83bdef113899881b219c9e" }, + {"dragonhound_NA", "029912212d370ee0fb4d38eefd8bfcd8ab04e2c3b0354020789c29ddf2a35c72d6" }, + {"dudezmobi_AR", "033c121d3f8d450174674a73f3b7f140b2717a7d51ea19ee597e2e8e8f9d5ed87f" }, + {"etszombi_AR", "03bfcbca83f11e622fa4eed9a1fa25dba377981ea3b22e3d0a4015f9a932af9272" }, + {"etszombi_EU", "03a5c083c78ba397970f20b544a01c13e7ed36ca8a5ae26d5fe7bd38b92b6a0c94" }, + {"fullmoon_AR", "03639bc56d3fecf856f17759a441c5893668e7c2d460f3d216798a413cd6766bb2" }, + {"fullmoon_NA", "03e388bcc579ac2675f8fadfa921eec186dcea8d2b43de1eed6caba23d5a962b74" }, + {"fullmoon_SH", "03a5cfda2b097c808834ccdd805828c811b519611feabdfe6b3644312e53f6748f" }, + {"gcharang_SH", "02a654037d12cdd609f4fad48e15ec54538e03f61fdae1acb855f16ebacac6bd73" }, + {"greer_NA", "0262da6aaa0b295b8e2f120035924758a4a630f899316dc63ee15ef03e9b7b2b23" }, + {"indenodes_AR", "0242778789986d614f75bcf629081651b851a12ab1cc10c73995b27b90febb75a2" }, + {"indenodes_EU", "03a416533cace0814455a1bb1cd7861ce825a543c6f6284a432c4c8d8875b7ace9" }, + {"indenodes_NA", "02b3908eda4078f0e9b6704451cdc24d418e899c0f515fab338d7494da6f0a647b" }, + {"indenodes_SH", "031d1584cf0eb4a2d314465e49e2677226b1615c3718013b8d6b4854c15676a58c" }, + {"karasugoi_NA", "02f803e6f159824a181cc5d709f3d1e7ff65f19e1899920724aeb4e3d2d869f911" }, + {"madmax_AR", "027afddbcf690230dd8d435ec16a7bfb0083e6b77030f763437f291dfc40a579d0" }, + {"madmax_EU", "0397ec3a4ad84b3009566d260c89f1c4404e86e5d044964747c9371277e38f5995" }, + {"madmax_NA", "036d3afebe1eab09f4c38c3ee6a4659ad390f3df92787c11437a58c59a29e408e6" }, + {"marmarachain_AR", "028690ca1e3afdf8a38b421f6a41f5ff407afc96d5a7a6a488330aae26c8b086bb" }, + {"mcrypt_SH", "027a4ca7b11d3456ff558c08bb04483a89c7f383448461fd0b6b3b07424aabe9a4" }, + {"metaphilibert_AR", "0239e34ad22957bbf4c8df824401f237b2afe8d40f7a645ecd43e8f27dde1ab0da" }, + {"metaphilibert_SH", "03b21ff042bf1730b28bde43f44c064578b41996117ac7634b567c3773089e3be3" }, + {"mihailo_EU", "036494e7c9467c8c7ff3bf29e841907fb0fa24241866569944ea422479ec0e6252" }, + {"mrlynch_AR", "03e67440141f53a08684c329ebc852b018e41f905da88e52aa4a6dc5aa4b12447a" }, + {"mylo_SH", "026d5f29d09ff3f33e14db4811606249b2438c6bcf964876714f81d1f2d952acde" }, {"node9_EU", "0392e4c9400e69f28c6b9e89d586da69d5a6af7702f1045eaa6ebc1996f0496e1f" }, + {"nodeone_NA", "0310a249c6c2dcc29f2135715138a9ddb8e01c0eab701cbd0b96d9cec660dbdc58" }, + {"nutellalicka_SH", "0284c4d3cb97dd8a32d10fb32b1855ae18cf845dad542e3b8937ca0e998fb54ecc" }, + {"oszy_EU", "03c53bd421de4a29ce68c8cc83f802e1181e77c08f8f16684490d61452ea8d023a" }, + {"patchkez_SH", "028c08db6e7242681f50db6c234fe3d6e12fb1a915350311be26373bac0d457d49" }, + {"pbca26_NA", "03c18431bb6bc95672f640f19998a196becd2851d5dcba4795fe8d85b7d77eab81" }, + {"peer2cloud_AR", "0243958faf9ae4d43b598b859ddc595c170c4cf50f8e4517d660ae5bc72aeb821b" }, + {"phba2061_EU", "03369187ce134bd7793ee34af7756fe1ab27202e09306491cdd5d8ad2c71697937" }, {"phm87_SH", "03889a10f9df2caef57220628515693cf25316fe1b0693b0241419e75d0d0e66ed" }, + {"pirate_EU", "0240011b95cde819f298fe0f507b2260c9fecdab784924076d4d1e54c522103cb1" }, + {"pirate_NA", "02ad7ef25d2dd461e361120cd3efe7cbce5e9512c361e9185aac33dd303d758613" }, + {"pungocloud_SH", "02641c36ae6747b88150a463a1fe65cf7a9d1c00a64387c73f296f0b64e77c7d3f" }, + {"smdmitry_AR", "0397b7584cb29717b721c0c587d4462477efc1f36a56921f133c9d17b0cd7f278a" }, + {"starfleet_EU", "03c6e047218f34644ccba67e317b9da5d28e68bbbb6b9973aef1281d2bafa46496" }, + {"strob_NA", "02285bf2f9e96068ecac14bc6f770e394927b4da9f5ba833eaa9468b5d47f203a3" }, + {"strob_SH", "0213751a1c59d3489ca85b3d62a3d606dcef7f0428aa021c1978ea16fb38a2fad6" }, + {"swisscertifiers_EU", "02e7722ebba9f8b5ebfb4e87d4fa58cc75aef677535b9cfc060c7d9471aacd9c9e" }, + {"titomane_AR", "03958bd8d13fe6946b8d0d0fbbc3861c72542560d0276e80a4c6b5fe55bc758b81" }, + {"titomane_EU", "02276090e483db1a01a802456b10831b3b6e0a6ad3ece9b2a01f4aad0e480c8edc" }, + {"titomane_SH", "02abf206bafc8048dbdc042b8eb6b1e356ea5dbe149eae3532b4811d4905e5cf01" }, + {"tonyl_AR", "0229e499e3f2e065ced402ceb8aaf3d5ab8bd3793aa074305e9fa30772ce604908" }, + {"tonyl_DEV", "0258b77d7dcfc6c2628b0b6b438951a6e74201fb2cd180a795e4c37fcf8e78a678" }, {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - - //TODO: placeholders so we have 16 NNs, details to be filled soon - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, - {"webworker01_NA", "02de90c720c007229374772505a43917a84ed129d5fbcfa4949cc2e9b563351124" }, + {"zatjum_SH", "0241c5660ca540780be66603b1791127a1261d56abbcb7562c297eec8e4fc078fb" } } }; From a470c4e2510be7c232b4830e7701cebbdf3624a5 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 12:21:30 -0400 Subject: [PATCH 86/98] get rid of z2zforkheight which causes linker bugz --- src/cc/cclib.cpp | 3 --- src/komodo_defs.h | 3 +-- src/main.cpp | 10 +++++----- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/cc/cclib.cpp b/src/cc/cclib.cpp index e8b4a32b2..67440f3da 100644 --- a/src/cc/cclib.cpp +++ b/src/cc/cclib.cpp @@ -35,9 +35,6 @@ #define EVAL_ROGUE 17 std::string MYCCLIBNAME = (char *)"rogue"; -extern const uint32_t z2zForkHeight; - - #elif BUILD_CUSTOMCC #include "customcc.h" diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 3a4af6f48..e482390bb 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -59,10 +59,9 @@ const uint32_t nHushHardforkHeight2 = 245055; // No coins/code are currently using timestamp activated fork const uint32_t nHushHardforkTimestamp = 1580303652; // Jan 29nd 1pm GMT const uint32_t nHushHardforkTimestamp2 = 1594425600; // Jul 11th 12a GMT -extern const uint32_t z2zForkHeight; static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nHushHardforkTimestamp, nHushHardforkTimestamp2, nHushHardforkTimestamp2*5, nHushHardforkTimestamp2*6}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {1,2,nHushHardforkHeight, nHushHardforkHeight2, (int)z2zForkHeight, 5*nHushHardforkHeight2}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {1,2,nHushHardforkHeight, nHushHardforkHeight2, (int)340000, 5*nHushHardforkHeight2}; // Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = diff --git a/src/main.cpp b/src/main.cpp index d5afa5baf..f0bc7793a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,7 +115,7 @@ bool fAlerts = DEFAULT_ALERTS; */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; -const uint32_t z2zForkHeight = GetArg("-z2zforkheight",340000); +const uint32_t 340000 = GetArg("-z2zforkheight",340000); unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; @@ -1736,12 +1736,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { AssertLockHeld(cs_main); const uint32_t z2zTransitionWindow = 10; - const uint32_t z2zTransitionStart = z2zForkHeight - z2zTransitionWindow; + const uint32_t z2zTransitionStart = 340000 - z2zTransitionWindow; const uint32_t nHeight = chainActive.Height(); // This only applies to HUSH3, other chains can start off z2z via ac_private=1 if(ishush3) { - if((nHeight >= z2zTransitionStart) || (nHeight <= z2zForkHeight)) { + if((nHeight >= z2zTransitionStart) || (nHeight <= 340000)) { // During the z2z transition window, only coinbase tx's as part of blocks are allowed // Theory: We want an empty mempool at our fork block height, and the only way to assure that // is to have an empty mempool for a few previous blocks, to take care of potential re-orgs @@ -3364,7 +3364,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; if(!ASSETCHAINS_PRIVATE && ishush3) { unsigned int nHeight = pindex->GetHeight(); - if(nHeight >= z2zForkHeight) { + if(nHeight >= 340000) { // At startup, HUSH3 doesn't know a block height yet and so we must wait until // connecting a block fprintf(stderr, "%s: Going full z2z at height %d!\n",__func__,nHeight); @@ -6337,7 +6337,7 @@ bool static LoadBlockIndexDB() // Try to detect if we are z2z based on height of blocks on disk // This helps to set it correctly on startup before a new block is connected - if(ishush3 && chainActive.Height() >= z2zForkHeight) { + if(ishush3 && chainActive.Height() >= 340000) { LogPrintf("%s: enabled ac_private=1 at height=%d\n", __func__, chainActive.Height()); ASSETCHAINS_PRIVATE = 1; } From 7f7876d2084daebc89b1914c870fa407c4fbef4e Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Tue, 16 Jun 2020 12:25:47 -0400 Subject: [PATCH 87/98] oops --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index f0bc7793a..317be206d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,7 +115,6 @@ bool fAlerts = DEFAULT_ALERTS; */ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; bool ishush3 = strncmp(ASSETCHAINS_SYMBOL, "HUSH3",5) == 0 ? true : false; -const uint32_t 340000 = GetArg("-z2zforkheight",340000); unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA; extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; From 4de60497c866c82330defd63b11884ab8991f973 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 00:04:55 -0400 Subject: [PATCH 88/98] Refactor GetSaplingWitnesses code and add some logging --- src/wallet/wallet.cpp | 13 ++++++++----- src/zcash/Zcash.h | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a7ca3d74d..b9ad1919d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1719,16 +1719,19 @@ void CWallet::GetSaplingNoteWitnesses(std::vector notes, boost::optional rt; int i = 0; for (SaplingOutPoint note : notes) { - if (mapWallet.count(note.hash) && - mapWallet[note.hash].mapSaplingNoteData.count(note) && - mapWallet[note.hash].mapSaplingNoteData[note].witnesses.size() > 0) { - witnesses[i] = mapWallet[note.hash].mapSaplingNoteData[note].witnesses.front(); + fprintf(stderr,"%s: i=%d\n", __func__,i); + auto noteData = mapWallet[note.hash].mapSaplingNoteData; + auto witnessess = noteData[note].witnesses; + if (mapWallet.count(note.hash) && noteData.count(note) && witnesses.size() > 0) { + fprintf(stderr,"%s: Found %lu witnesses for note %s\n", __func__, witnesses.size(), note.hash.ToString().c_str() ); + witnesses[i] = witnesses.front(); if (!rt) { rt = witnesses[i]->root(); } else { if(*rt == witnesses[i]->root()) { // Something is fucky - std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root!"; + std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root! i="; + err += i; throw std::logic_error(err); } diff --git a/src/zcash/Zcash.h b/src/zcash/Zcash.h index 84dfe9525..e45aa1d02 100644 --- a/src/zcash/Zcash.h +++ b/src/zcash/Zcash.h @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers #ifndef ZC_ZCASH_H_ #define ZC_ZCASH_H_ From d0dade1d2c76d43cc8c7f245718e11997b2fc59d Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 10:13:57 -0400 Subject: [PATCH 89/98] desprout --- src/zcash/JoinSplit.cpp | 68 ----------------------------------------- 1 file changed, 68 deletions(-) diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp index db51ff1fd..5cd7627dc 100644 --- a/src/zcash/JoinSplit.cpp +++ b/src/zcash/JoinSplit.cpp @@ -28,73 +28,5 @@ class JoinSplitCircuit : public JoinSplit { public: JoinSplitCircuit() {} ~JoinSplitCircuit() {} - - /* - SproutProof prove( - const std::array& inputs, - const std::array& outputs, - std::array& out_notes, - std::array& out_ciphertexts, - uint256& out_ephemeralKey, - const uint256& joinSplitPubKey, - uint256& out_randomSeed, - std::array& out_macs, - std::array& out_nullifiers, - std::array& out_commitments, - uint64_t vpub_old, - uint64_t vpub_new, - const uint256& rt, - bool computeProof, - uint256 *out_esk // Payment disclosure - ) { - GrothProof proof; - return proof; - } - */ }; - -/* -template -JoinSplit* JoinSplit::Prepared() -{ - return new JoinSplitCircuit(); -} - -template -uint256 JoinSplit::h_sig( - const uint256& randomSeed, - const std::array& nullifiers, - const uint256& joinSplitPubKey -) { - const unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] - = {'Z','c','a','s','h','C','o','m','p','u','t','e','h','S','i','g'}; - - std::vector block(randomSeed.begin(), randomSeed.end()); - - for (size_t i = 0; i < NumInputs; i++) { - block.insert(block.end(), nullifiers[i].begin(), nullifiers[i].end()); - } - - block.insert(block.end(), joinSplitPubKey.begin(), joinSplitPubKey.end()); - - uint256 output; - - if (crypto_generichash_blake2b_salt_personal(output.begin(), 32, - &block[0], block.size(), - NULL, 0, // No key. - NULL, // No salt. - personalization - ) != 0) - { - throw std::logic_error("hash function failure"); - } - - return output; -} - - -template class JoinSplit; - -*/ } From 6e31ee3b1d3a790f5603ccbc1a1c3f6fa0c2d45b Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 10:41:33 -0400 Subject: [PATCH 90/98] fix --- src/wallet/wallet.cpp | 11 +++++++---- src/zcash/IncrementalMerkleTree.cpp | 1 + src/zcash/util.h | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b9ad1919d..b3d759f83 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1721,14 +1721,17 @@ void CWallet::GetSaplingNoteWitnesses(std::vector notes, for (SaplingOutPoint note : notes) { fprintf(stderr,"%s: i=%d\n", __func__,i); auto noteData = mapWallet[note.hash].mapSaplingNoteData; - auto witnessess = noteData[note].witnesses; - if (mapWallet.count(note.hash) && noteData.count(note) && witnesses.size() > 0) { - fprintf(stderr,"%s: Found %lu witnesses for note %s\n", __func__, witnesses.size(), note.hash.ToString().c_str() ); - witnesses[i] = witnesses.front(); + auto nWitnesses = noteData[note].witnesses.size(); + if (mapWallet.count(note.hash) && noteData.count(note) && nWitnesses > 0) { + fprintf(stderr,"%s: Found %lu witnesses for note %s\n", __func__, nWitnesses, note.hash.ToString().c_str() ); + witnesses[i] = noteData[note].witnesses.front(); if (!rt) { + fprintf(stderr,"%s: Setting witness root\n",__func__); rt = witnesses[i]->root(); } else { if(*rt == witnesses[i]->root()) { + //fprintf(stderr,"%s: rt=%s\n",__func__,rt.GetHash().ToString().c_str()); + //fprintf(stderr,"%s: witnesses[%d]->root()=%s\n",__func__,i,witnesses[i]->root().GetHash().ToString().c_str()); // Something is fucky std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root! i="; err += i; diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index 4d3ff8c2b..247eaf80c 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -1018,6 +1018,7 @@ size_t IncrementalMerkleTree::next_depth(size_t skip) const { template Hash IncrementalMerkleTree::root(size_t depth, std::deque filler_hashes) const { + fprintf(stderr,"%s: depth=%d\n",__func__,depth); PathFiller filler(filler_hashes); Hash combine_left = left ? *left : filler.next(0); diff --git a/src/zcash/util.h b/src/zcash/util.h index 10886e3ca..0c04a5aac 100644 --- a/src/zcash/util.h +++ b/src/zcash/util.h @@ -1,3 +1,4 @@ +// Copyright (c) 2019-2020 The Hush developers #ifndef ZC_UTIL_H_ #define ZC_UTIL_H_ From 280cc4cfdad1e0a6053b643142e56fa4092629e0 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 12:36:08 -0400 Subject: [PATCH 91/98] oops --- src/zcash/IncrementalMerkleTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp index 247eaf80c..d4411c11b 100644 --- a/src/zcash/IncrementalMerkleTree.cpp +++ b/src/zcash/IncrementalMerkleTree.cpp @@ -1018,7 +1018,7 @@ size_t IncrementalMerkleTree::next_depth(size_t skip) const { template Hash IncrementalMerkleTree::root(size_t depth, std::deque filler_hashes) const { - fprintf(stderr,"%s: depth=%d\n",__func__,depth); + //fprintf(stderr,"%s: depth=%d\n",__func__,depth); PathFiller filler(filler_hashes); Hash combine_left = left ? *left : filler.next(0); From f8972d4150318631b19ab3abff9ce237783ac034 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 17:49:18 -0400 Subject: [PATCH 92/98] Remove mention of joinsplit from some error messages --- src/coins.h | 4 ++-- src/main.cpp | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/coins.h b/src/coins.h index 3e8f674fb..2d08be42c 100644 --- a/src/coins.h +++ b/src/coins.h @@ -545,7 +545,7 @@ public: size_t DynamicMemoryUsage() const; /** - * Amount of bitcoins coming in to a transaction + * Amount of HUSH coming in to a transaction * Note that lightweight clients may not know anything besides the hash of previous transactions, * so may not be able to calculate this. * @@ -557,7 +557,7 @@ public: //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view bool HaveInputs(const CTransaction& tx) const; - //! Check whether all joinsplit requirements (anchors/nullifiers) are satisfied + //! Check whether all shielded requirements (anchors/nullifiers) are satisfied bool HaveShieldedRequirements(const CTransaction& tx) const; //! Return priority of tx at height nHeight diff --git a/src/main.cpp b/src/main.cpp index 317be206d..ada7ab8a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1907,7 +1907,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (!view.HaveShieldedRequirements(tx)) { //fprintf(stderr,"accept failure.2\n"); - return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); + return state.Invalid(error("AcceptToMemoryPool: shielded requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); } // Bring the best block into scope @@ -2728,9 +2728,9 @@ namespace Consensus { if (!inputs.HaveInputs(tx)) return state.Invalid(error("CheckInputs(): %s inputs unavailable", tx.GetHash().ToString())); - // are the JoinSplit's requirements met? + // are the shielded requirements met? if (!inputs.HaveShieldedRequirements(tx)) - return state.Invalid(error("CheckInputs(): %s JoinSplit requirements not met", tx.GetHash().ToString())); + return state.Invalid(error("CheckInputs(): %s shielded requirements not met", tx.GetHash().ToString())); CAmount nValueIn = 0; CAmount nFees = 0; @@ -3464,7 +3464,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Before the genesis block, there was an empty tree SproutMerkleTree tree; pindex->hashSproutAnchor = tree.root(); - // The genesis block contained no JoinSplits + // The genesis block contained no JoinSplits, lulz pindex->hashFinalSproutRoot = pindex->hashSproutAnchor; } return true; @@ -3557,10 +3557,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("ConnectBlock(): inputs missing/spent"), REJECT_INVALID, "bad-txns-inputs-missingorspent"); } - // are the JoinSplit's requirements met? + // are the shielded requirements met? if (!view.HaveShieldedRequirements(tx)) - return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"), - REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met"); + return state.DoS(100, error("ConnectBlock(): shielded requirements not met"), REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met"); if (fAddressIndex || fSpentIndex) { @@ -6403,7 +6402,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth CBlockIndex* pindexFailure = NULL; int nGoodTransactions = 0; CValidationState state; - // No need to verify JoinSplits twice + // No need to verify shielded req's twice auto verifier = libzcash::ProofVerifier::Disabled(); //fprintf(stderr,"start VerifyDB %u\n",(uint32_t)time(NULL)); for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) From 646c68490b5aa87ef50db127fa1ef7dd425425a7 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 17:53:12 -0400 Subject: [PATCH 93/98] cleanup --- src/main.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ada7ab8a6..fb53e2c28 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1578,6 +1578,7 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio else if ( joinsplit.vpub_new != 0 && joinsplit.vpub_old == 0 ) z_t++; } + if ( ASSETCHAINS_PRIVATE != 0 && invalid_private_taddr != 0 ) { static uint32_t counter; @@ -3657,23 +3658,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } } - //if ( ASSETCHAINS_SYMBOL[0] == 0 ) - // komodo_earned_interest(pindex->GetHeight(),sum); CTxUndo undoDummy; if (i > 0) { blockundo.vtxundo.push_back(CTxUndo()); } UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->GetHeight()); - /* - BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { - BOOST_FOREACH(const uint256 ¬e_commitment, joinsplit.commitments) { - // Insert the note commitments into our temporary tree. - - sprout_tree.append(note_commitment); - } - } - */ BOOST_FOREACH(const OutputDescription &outputDescription, tx.vShieldedOutput) { sapling_tree.append(outputDescription.cm); From 36e917f1d3e1d014deb53e7ec178f13afa954312 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 20:43:58 -0400 Subject: [PATCH 94/98] copyright --- src/rpc/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index cfe21a6d5..56c038596 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin Core developers -// Copyright (c) 2019 The Hush developers +// Copyright (c) 2019-2020 The Hush developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. From 83be5195e93b4977d602ad8f055320858a25e07f Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 20:44:54 -0400 Subject: [PATCH 95/98] Revert "Randomize sietch memos and increase min zouts to 3" This reverts commit a053d212b8e22d1d8ffe08a2e0955f1854055702. --- src/wallet/rpcwallet.cpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 221bef44e..867de51a7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4590,15 +4590,6 @@ UniValue z_getoperationstatus_IMPL(const UniValue& params, bool fRemoveFinishedO #define CTXIN_SPEND_DUST_SIZE 148 #define CTXOUT_REGULAR_SIZE 34 -void random_hex(char str[], int len) -{ - char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - for(int i=0;iMAX_ZOUTS)) { - fprintf(stderr,"%s: Sietch min zouts must be >=%d and <= %d, setting to default value of %d\n", __FUNCTION__, ABSOLUTE_MIN_ZOUTS, MAX_ZOUTS, DEFAULT_MIN_ZOUTS ); + if((MIN_ZOUTS<2) || (MIN_ZOUTS>MAX_ZOUTS)) { + fprintf(stderr,"%s: Sietch min zouts must be >=2 and <= 25, setting to default value of %d\n", __FUNCTION__, DEFAULT_MIN_ZOUTS ); MIN_ZOUTS=DEFAULT_MIN_ZOUTS; } @@ -4748,9 +4739,8 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) // OK, we identify this xtn as needing privacy zdust, we must decide how much, non-deterministically int nAmount = 0; int decider = 1 + GetRandInt(100); // random int between 1 and 100 - char *str; - random_hex(str,512); - string memo = string(str); + string memo = "f600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + string zdust1, zdust2; // Which zaddr we send to is non-deterministically chosen from two zpools... From 4800f497aa9d7f6a496985ecf4756f0c354bd040 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Wed, 17 Jun 2020 22:32:00 -0400 Subject: [PATCH 96/98] Fix copyright --- src/wallet/asyncrpcoperation_saplingconsolidation.cpp | 11 +++++++++-- src/wallet/asyncrpcoperation_saplingconsolidation.h | 2 +- src/wallet/wallet.cpp | 3 +-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp index 477545348..0c6cae7c1 100644 --- a/src/wallet/asyncrpcoperation_saplingconsolidation.cpp +++ b/src/wallet/asyncrpcoperation_saplingconsolidation.cpp @@ -95,15 +95,22 @@ bool AsyncRPCOperation_saplingconsolidation::main_impl() { // an anchor at height N-10 for each SpendDescription // Consider, should notes be sorted? pwalletMain->GetFilteredNotes(saplingEntries, "", 11); + + if(saplingEntries.size() == 0) { + LogPrint("zrpcunsafe", "%s: Nothing to consolidate, done.\n",opid); + return true; + } + if (fConsolidationMapUsed) { const vector& v = mapMultiArgs["-consolidatesaplingaddress"]; for(int i = 0; i < v.size(); i++) { auto zAddress = DecodePaymentAddress(v[i]); if (boost::get(&zAddress) != nullptr) { libzcash::SaplingPaymentAddress saplingAddress = boost::get(zAddress); - addresses.insert(saplingAddress ); + addresses.insert(saplingAddress); } else { - //TODO: how to handle invalid zaddrs? + LogPrint("zrpcunsafe", "%s: Invalid zaddr, exiting\n", opid); + return false; } } } else { diff --git a/src/wallet/asyncrpcoperation_saplingconsolidation.h b/src/wallet/asyncrpcoperation_saplingconsolidation.h index 9a80ff7c7..5d14b9335 100644 --- a/src/wallet/asyncrpcoperation_saplingconsolidation.h +++ b/src/wallet/asyncrpcoperation_saplingconsolidation.h @@ -1,5 +1,5 @@ // Copyright (c) 2020 The Hush developers -// TODO: Forge should add his preferred copyright line here +// Copyright (c) 2019 CryptoForge // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b3d759f83..c0f449a56 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1733,8 +1733,7 @@ void CWallet::GetSaplingNoteWitnesses(std::vector notes, //fprintf(stderr,"%s: rt=%s\n",__func__,rt.GetHash().ToString().c_str()); //fprintf(stderr,"%s: witnesses[%d]->root()=%s\n",__func__,i,witnesses[i]->root().GetHash().ToString().c_str()); // Something is fucky - std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root! i="; - err += i; + std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root!"; throw std::logic_error(err); } From 9bcf13bf4a7ef40a0a177aee5eb6b0a9a2769f03 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 18 Jun 2020 05:40:04 -0400 Subject: [PATCH 97/98] report invalid roots --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c0f449a56..4581dae00 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1733,7 +1733,7 @@ void CWallet::GetSaplingNoteWitnesses(std::vector notes, //fprintf(stderr,"%s: rt=%s\n",__func__,rt.GetHash().ToString().c_str()); //fprintf(stderr,"%s: witnesses[%d]->root()=%s\n",__func__,i,witnesses[i]->root().GetHash().ToString().c_str()); // Something is fucky - std::string err = "CWallet::GetSaplingNoteWitnesses: Invalid witness root!"; + std::string err = std::string("CWallet::GetSaplingNoteWitnesses: Invalid witness root! rt=") + rt.get().ToString(); throw std::logic_error(err); } From a7cd2b375096149f9793a4c5788af237b7b2be68 Mon Sep 17 00:00:00 2001 From: Duke Leto Date: Thu, 18 Jun 2020 06:41:26 -0400 Subject: [PATCH 98/98] Chill out on the logspam --- src/wallet/wallet.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4581dae00..ae845cb21 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1719,22 +1719,24 @@ void CWallet::GetSaplingNoteWitnesses(std::vector notes, boost::optional rt; int i = 0; for (SaplingOutPoint note : notes) { - fprintf(stderr,"%s: i=%d\n", __func__,i); + //fprintf(stderr,"%s: i=%d\n", __func__,i); auto noteData = mapWallet[note.hash].mapSaplingNoteData; auto nWitnesses = noteData[note].witnesses.size(); if (mapWallet.count(note.hash) && noteData.count(note) && nWitnesses > 0) { fprintf(stderr,"%s: Found %lu witnesses for note %s\n", __func__, nWitnesses, note.hash.ToString().c_str() ); witnesses[i] = noteData[note].witnesses.front(); if (!rt) { - fprintf(stderr,"%s: Setting witness root\n",__func__); + //fprintf(stderr,"%s: Setting witness root\n",__func__); rt = witnesses[i]->root(); } else { if(*rt == witnesses[i]->root()) { //fprintf(stderr,"%s: rt=%s\n",__func__,rt.GetHash().ToString().c_str()); //fprintf(stderr,"%s: witnesses[%d]->root()=%s\n",__func__,i,witnesses[i]->root().GetHash().ToString().c_str()); // Something is fucky - std::string err = std::string("CWallet::GetSaplingNoteWitnesses: Invalid witness root! rt=") + rt.get().ToString(); - throw std::logic_error(err); + std::string err = string("CWallet::GetSaplingNoteWitnesses: Invalid witness root! rt=") + rt.get().ToString(); + err += string("\n!= witness[i]->root()=") + witnesses[i]->root().ToString(); + //throw std::logic_error(err); + fprintf(stderr,"%s: IGNORING %s\n", __func__,err.c_str()); } } @@ -1744,6 +1746,7 @@ void CWallet::GetSaplingNoteWitnesses(std::vector notes, // All returned witnesses have the same anchor if (rt) { final_anchor = *rt; + //fprintf(stderr,"%s: final_anchor=%s\n", __func__, rt.get().ToString().c_str() ); } }