]> Git Repo - VerusCoin.git/commitdiff
Prepare for new hash algorithm changes and removing coinbase shielding requirements
authormiketout <[email protected]>
Sun, 24 Nov 2019 22:23:26 +0000 (14:23 -0800)
committermiketout <[email protected]>
Sun, 24 Nov 2019 22:23:26 +0000 (14:23 -0800)
18 files changed:
src/cc/CCtx.cpp
src/chainparams.cpp
src/chainparams.h
src/crypto/verus_clhash.cpp
src/crypto/verus_clhash_portable.cpp
src/crypto/verus_hash.h
src/init.cpp
src/key_io.cpp
src/main.cpp
src/miner.cpp
src/rpc/pbaasrpc.cpp
src/scheduler.cpp
src/wallet-utility.cpp
src/wallet/asyncrpcoperation_sendmany.cpp
src/wallet/asyncrpcoperation_sendmany.h
src/wallet/rpcwallet.cpp
src/wallet/wallet.cpp
src/wallet/wallet.h

index fa3c8df01bbbfec887753d2fef4880162981d876..86aee339f7485347648f45b26e57cf96252e5fc9 100644 (file)
@@ -324,7 +324,7 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
     const CKeyStore& keystore = *pwalletMain;
     assert(pwalletMain != NULL);
     LOCK2(cs_main, pwalletMain->cs_wallet);
-    pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
+    pwalletMain->AvailableCoins(vecOutputs, false, NULL, false);
     utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos));
     BOOST_FOREACH(const COutput& out, vecOutputs)
     {
index c73e80e5d0d4f63ccb7a334078f5b35f108150da..711c093ee802c728e6c4ebe8aeeb141e7658dc44 100644 (file)
@@ -93,7 +93,7 @@ public:
         strNetworkID = "main";
         strCurrencyUnits = "KMD";
         bip44CoinType = 133; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md (ZCASH, should be VRSC)
-        consensus.fCoinbaseMustBeProtected = false; // true this is only true wuth Verus and enforced after block 12800
+        consensus.fCoinbaseMustBeProtected = false; // true this is only true wuth Verus and enforced after block 12800 (enforcement ending at solution V3)
         consensus.nSubsidySlowStartInterval = 20000;
         consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL;
         consensus.nPostBlossomSubsidyHalvingInterval = Consensus::POST_BLOSSOM_HALVING_INTERVAL;
@@ -201,7 +201,7 @@ public:
 
         vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
 
-        fMiningRequiresPeers = true;
+        //fMiningRequiresPeers = true;
         fDefaultConsistencyChecks = false;
         fRequireStandard = true;
         fMineBlocksOnDemand = false;
@@ -271,12 +271,17 @@ void *chainparams_commandline(void *ptr)
             mainParams.consensus.nLwmaPOSAjustedWeight = 46531;
         }
 
+        // this includes VRSCTEST, unlike the checkpoints and changes below
+        if (_IsVerusActive())
+        {
+            mainParams.consensus.fCoinbaseMustBeProtected = true;
+        }
+
         // only require coinbase protection on Verus from the Komodo family of coins
         if (strcmp(ASSETCHAINS_SYMBOL,"VRSC") == 0)
         {
             mainParams.consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 227520;
             mainParams.consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = 227520;
-            mainParams.consensus.fCoinbaseMustBeProtected = true;
             checkpointData = //(Checkpoints::CCheckpointData)
                 {
                     boost::assign::map_list_of
@@ -749,6 +754,18 @@ const CChainParams &Params() {
     return *pCurrentParams;
 }
 
+void DisableCoinbaseMustBeProtected()
+{
+    CChainParams &curParams = pCurrentParams ? *pCurrentParams : mainParams;
+    curParams.DisableCoinbaseMustBeProtected();
+}
+
+void EnableCoinbaseMustBeProtected()
+{
+    CChainParams &curParams = pCurrentParams ? *pCurrentParams : mainParams;
+    curParams.EnableCoinbaseMustBeProtected();
+}
+
 bool AreParamsInitialized()
 {
     return (pCurrentParams != NULL);
index 9d5fad1ff57c0e2b964401c9d1d9159758181ac4..a1a667917bb39af600b9a4a8d544ebdb83ab1c83 100644 (file)
@@ -103,6 +103,10 @@ public:
     std::string GetFoundersRewardAddressAtHeight(int height) const;
     CScript GetFoundersRewardScriptAtHeight(int height) const;
     std::string GetFoundersRewardAddressAtIndex(int i) const;
+    /** Enable disable coinbase protection on mainnet */
+    void DisableCoinbaseMustBeProtected() { consensus.fCoinbaseMustBeProtected = false; }
+    void EnableCoinbaseMustBeProtected() { consensus.fCoinbaseMustBeProtected = true; }
+
     /** Enforce coinbase consensus rule in regtest mode */
     void SetRegTestCoinbaseMustBeProtected() { consensus.fCoinbaseMustBeProtected = true; }
 
@@ -153,6 +157,8 @@ protected:
  */
 const CChainParams &Params();
 bool AreParamsInitialized();
+void DisableCoinbaseMustBeProtected();
+void EnableCoinbaseMustBeProtected();
 
 /** Return parameters for the given network. */
 CChainParams &Params(CBaseChainParams::Network network);
index 69d26b982c1458fcd11a1d0cde7a37dfae37195b..3b1cb8501422c675edfd2e503d1a9a565746066f 100644 (file)
@@ -224,7 +224,7 @@ inline void fixupkey(__m128i **pMoveScratch, verusclhash_descr *pdesc)
 */
 __m128i __verusclmulwithoutreduction64alignedrepeat(__m128i *randomsource, const __m128i buf[4], uint64_t keyMask, __m128i **pMoveScratch);
 
-bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count)
+bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint32_t solutionVersion, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count)
 {
        CVerusHashV2 &vh = vhw.GetState();
     verusclhasher &vclh = vh.vclh;
@@ -288,45 +288,6 @@ bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHas
         _mm_store_si128((u128 *)(&curBuf[32 + 16]), fill1);
         curBuf[32 + 15] = ch;
 
-        /*
-        if (!i)
-        {
-            std::cout << "pre-buffer = ";
-            std::cout << HexBytes(curBuf, 64);
-
-            std::cout << std::endl;
-            std::cout << "test_buf = [";
-            for (int k = 0; k < 64; k++)
-            {
-                if (k == 63)
-                {
-                    std::cout << strprintf("0x%02x]", *(curBuf + k));
-                }
-                else
-                {
-                    std::cout << strprintf("0x%02x, ", *(curBuf + k));
-                }
-            }
-            std::cout << std::endl;
-
-            std::cout << "test_key = [";
-            for (int k = 0; k < (((u128 *)hasherrefresh) - hashKey); k++)
-            {
-                std::cout << "0x";
-                std::cout << LEToHex(*(hashKey + k));
-                if (k == (((u128 *)hasherrefresh) - hashKey) - 1)
-                {
-                    std::cout << "]";
-                }
-                else
-                {
-                    std::cout << ", ";
-                }
-            }
-            std::cout << std::endl;
-        }
-        */
-
                // run verusclhash on the buffer
         //const uint64_t intermediate = vclh(curBuf, hashKey, pMoveScratch);
         __m128i  acc = __verusclmulwithoutreduction64alignedrepeat(hashKey, (const __m128i *)curBuf, vclh.keyMask, pMoveScratch);
@@ -340,18 +301,6 @@ bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHas
 
                haraka512_keyed_local((unsigned char *)&curHash, curBuf, hashKey + vh.IntermediateTo128Offset(intermediate));
 
-        /*
-        if (!i)
-        {
-            std::cout << "intermediate: ";
-            std::cout << LEToHex(intermediate);
-            std::cout << std::endl;
-            std::cout << "hashBytes: ";
-            std::cout << HexBytes((unsigned char *)&curHash, 32);
-            std::cout << std::endl;
-        }
-        */
-
         if (compResult[3] > compTarget[3] || (compResult[3] == compTarget[3] && compResult[2] > compTarget[2]) ||
             (compResult[3] == compTarget[3] && compResult[2] == compTarget[2] && compResult[1] > compTarget[1]) ||
             (compResult[3] == compTarget[3] && compResult[2] == compTarget[2] && compResult[1] == compTarget[1] && compResult[0] > compTarget[0]))
index 2a0322f9ea7ce391a945a0795b6b12a9967e3df7..a14b71182b39a7848477f35da328814f17fa973a 100644 (file)
@@ -650,7 +650,7 @@ uint64_t verusclhash_port(void * random, const unsigned char buf[64], uint64_t k
     return precompReduction64_port(acc);
 }
 
-bool mine_verus_v2_port(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count)
+bool mine_verus_v2_port(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint32_t solutionVersion, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count)
 {
        CVerusHashV2 &vh = vhw.GetState();
     verusclhasher &vclh = vh.vclh;
index 727f1f80adc2b8f6fb6a03a259953a5e30ab253d..fb502e97dc47e966f53c5f992d35f13f296d8228 100644 (file)
@@ -218,22 +218,6 @@ class CVerusHashV2
 \r
             // get the final hash with a mutated dynamic key for each hash result\r
             (*haraka512KeyedFunction)(hash, curBuf, key + IntermediateTo128Offset(intermediate));\r
-\r
-            /*\r
-            // TEST BEGIN\r
-            // test against the portable version\r
-            uint256 testHash1 = *(uint256 *)hash, testHash2;\r
-            FillExtra((u128 *)curBuf);\r
-            u128 *hashKey = ((u128 *)vclh.gethashkey());\r
-            uint64_t temp = verusclhash_port(key, curBuf, vclh.keyMask);\r
-            FillExtra(&temp);\r
-            haraka512_keyed((unsigned char *)&testHash2, curBuf, hashKey + IntermediateTo128Offset(intermediate));\r
-            if (testHash1 != testHash2)\r
-            {\r
-                printf("Portable version failed! intermediate1: %lx, intermediate2: %lx\n", intermediate, temp);\r
-            }\r
-            // END TEST\r
-            */\r
         }\r
 \r
         inline unsigned char *CurBuffer()\r
index 751ea5941b71adeecea5f5a4c32ff7f32d19ff08..7402c9fd8c6a51315bf24a8751c95d704a41ca48 100644 (file)
@@ -1218,12 +1218,18 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
             CConstVerusSolutionVector::activationHeight.SetActivationHeight(CActivationHeight::SOLUTION_VERUSV2, 310000);
             CConstVerusSolutionVector::activationHeight.SetActivationHeight(CActivationHeight::SOLUTION_VERUSV3, 780000);
         }
-        else
+        else if (strcmp(ASSETCHAINS_SYMBOL,"VRSCTEST") == 0)
         {
             CConstVerusSolutionVector::activationHeight.SetActivationHeight(CActivationHeight::SOLUTION_VERUSV2, 1);
             CConstVerusSolutionVector::activationHeight.SetActivationHeight(CActivationHeight::SOLUTION_VERUSV3, 110);
             //CConstVerusSolutionVector::activationHeight.SetActivationHeight(CActivationHeight::SOLUTION_VERUSV4, 1);
         }
+        else
+        {
+            CConstVerusSolutionVector::activationHeight.SetActivationHeight(CActivationHeight::SOLUTION_VERUSV2, 1);
+            CConstVerusSolutionVector::activationHeight.SetActivationHeight(CActivationHeight::SOLUTION_VERUSV3, 1);
+            CConstVerusSolutionVector::activationHeight.SetActivationHeight(CActivationHeight::SOLUTION_VERUSV4, 1);
+        }
     }
 
     // Sanity check
index 7e76171a05dbdd78307e34f5f0dc07959d9e7da4..8388d8fde8f81a3af0783097033bc80ac665cce6 100644 (file)
@@ -22,6 +22,7 @@
 #include <algorithm>
 
 extern uint160 VERUS_CHAINID;
+extern std::string VERUS_CHAINNAME;
 
 namespace
 {
@@ -494,17 +495,48 @@ uint160 CCrossChainRPCData::GetConditionID(std::string name, int32_t condition)
     return Hash160(chainHash.begin(), chainHash.end());
 }
 
+std::string TrimLeading(const std::string &Name, unsigned char ch)
+{
+    std::string nameCopy = Name;
+    int removeSpaces;
+    for (removeSpaces = 0; removeSpaces < nameCopy.size(); removeSpaces++)
+    {
+        if (nameCopy[removeSpaces] != ch)
+        {
+            break;
+        }
+    }
+    if (removeSpaces)
+    {
+        nameCopy.erase(nameCopy.begin(), nameCopy.begin() + removeSpaces);
+    }
+    return nameCopy;
+}
+
+std::string TrimTrailing(const std::string &Name, unsigned char ch)
+{
+    std::string nameCopy = Name;
+    int removeSpaces;
+    for (removeSpaces = nameCopy.size() - 1; removeSpaces >= 0; removeSpaces--)
+    {
+        if (nameCopy[removeSpaces] != ch)
+        {
+            break;
+        }
+    }
+    nameCopy.resize(nameCopy.size() - removeSpaces);
+    return nameCopy;
+}
+
 std::vector<std::string> ParseSubNames(const std::string &Name, std::string &ChainOut)
 {
     std::string nameCopy = Name;
     std::string invalidChars = "\\/:*?\"<>|";
     for (int i = 0; i < nameCopy.size(); i++)
     {
-        if (invalidChars.find(nameCopy[i]) != std::string::npos)
-        {
-            nameCopy[i] = '_';
-        }
+        return std::vector<std::string>();
     }
+
     std::vector<std::string> retNames;
     boost::split(retNames, nameCopy, boost::is_any_of("@"));
     if (!retNames.size() || retNames.size() > 2)
@@ -528,6 +560,11 @@ std::vector<std::string> ParseSubNames(const std::string &Name, std::string &Cha
         {
             retNames[i] = std::string(retNames[i], 0, (KOMODO_ASSETCHAIN_MAXLEN - 1));
         }
+        // spaces are allowed, but no sub-name can have leading or trailing spaces
+        if (!retNames[i].size() || retNames[i] != TrimTrailing(TrimLeading(retNames[i], ' '), ' '))
+        {
+            return std::vector<std::string>();
+        }
     }
 
     // if no chain is specified, default to chain of the ID
@@ -536,7 +573,7 @@ std::vector<std::string> ParseSubNames(const std::string &Name, std::string &Cha
         if (retNames.size() == 1)
         {
             // by default, we assume the Verus chain for no suffix
-            ChainOut = "";
+            ChainOut = VERUS_CHAINNAME;
         }
         else
         {
index 831cb9cff5e65d3c913204be6792c4b9d5284db8..701ba38045425701601ba4392969412a49007b9a 100644 (file)
@@ -2671,9 +2671,12 @@ namespace Consensus {
                                      REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
                 }
 
-                // Ensure that coinbases cannot be spent to transparent outputs
-                // Disabled on regtest
-                if (fCoinbaseEnforcedProtectionEnabled &&
+                // As of solution version 3, we're done with the Zcash coinbase protection.
+                // After careful consideration, it seems that while there is no real privacy benefit to the
+                // coinbase protection beyond forcing the private address pool to be used at least a little by everyone, it does increase the size of the blockchain
+                // and often reduces privacy by mixing multiple coinbase payment addresses
+                if (CConstVerusSolutionVector::GetVersionByHeight(coins->nHeight) < CActivationHeight::SOLUTION_VERUSV3 &&
+                    fCoinbaseEnforcedProtectionEnabled &&
                     consensusParams.fCoinbaseMustBeProtected &&
                     !(tx.vout.size() == 0 || (tx.vout.size() == 1 && tx.vout[0].nValue == 0)) &&
                     (strcmp(ASSETCHAINS_SYMBOL, "VRSC") != 0 || (nSpendHeight >= 12800 && coins->nHeight >= 12800))) {
index 1bf90b6c9d9243d05371626f0ef3a782835ce62e..eadd9dfeb18753e72fb1082ebec8ed2d097a3284 100644 (file)
@@ -2294,9 +2294,9 @@ void static VerusStaker(CWallet *pwallet)
     }
 }
 
-typedef bool (*minefunction)(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
-bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
-bool mine_verus_v2_port(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
+typedef bool (*minefunction)(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint32_t solutionVersion, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
+bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint32_t solutionVersion, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
+bool mine_verus_v2_port(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint32_t solutionVersion, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
 
 void static BitcoinMiner_noeq(CWallet *pwallet)
 #else
@@ -2429,8 +2429,10 @@ void static BitcoinMiner_noeq()
             bool mergeMining = false;
             savebits = pblock->nBits;
 
+            uint32_t solutionVersion = CConstVerusSolutionVector::Version(pblock->nSolution);
             bool verusHashV2 = pblock->nVersion == CBlockHeader::VERUS_V2;
-            bool verusSolutionV4 = CConstVerusSolutionVector::Version(pblock->nSolution) >= CActivationHeight::SOLUTION_VERUSV4;
+            bool verusSolutionGTEV3 = solutionVersion >= CActivationHeight::SOLUTION_VERUSV3;
+            bool verusSolutionV4 = solutionVersion >= CActivationHeight::SOLUTION_VERUSV4;
 
             if ( ASSETCHAINS_SYMBOL[0] != 0 )
             {
@@ -2627,12 +2629,12 @@ void static BitcoinMiner_noeq()
                                 CPBaaSPreHeader savedHeader(*pblock);
 
                                 pblock->ClearNonCanonicalData();
-                                blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
+                                blockFound = (*mine_verus)(*pblock, ss2, solutionVersion, hashResult, uintTarget, start, &hashesToGo);
                                 savedHeader.SetBlockData(*pblock);
                             }
                             else
                             {
-                                blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
+                                blockFound = (*mine_verus)(*pblock, ss2, solutionVersion, hashResult, uintTarget, start, &hashesToGo);
                             }
 
                             arithHash = UintToArith256(hashResult);
index 75a0ff55eb3b75e528ecc5594ca6648a6672f717..53d1f9a0deb10d6a6c258c7b5b35aa4e29a608d5 100644 (file)
@@ -4183,7 +4183,7 @@ UniValue registernamecommitment(const UniValue& params, bool fHelp)
     // if either we have an invalid name or an implied parent, that is not valid
     if (name == "" || !parent.IsNull())
     {
-        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid name for commitment");
+        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid name for commitment. Names must not have leading or trailing spaces and must not include any of the following characters between parentheses (\\/:*?\"<>|)");
     }
 
     parent = ConnectedChains.ThisChain().GetChainID();
index ecd904cdec308a167f186327e92a2f86325f9b61..20532045d2d739d7d4b408741c1e84d2a2143ca8 100644 (file)
@@ -19,7 +19,6 @@ CScheduler::~CScheduler()
     assert(nThreadsServicingQueue == 0);
 }
 
-
 void CScheduler::serviceQueue()
 {
     boost::unique_lock<boost::mutex> lock(newTaskMutex);
index 8430b0103489d343ac1b0b81619928ced9c07d23..0089321b9b916c2137169e95be64f135eba422be 100644 (file)
@@ -13,6 +13,7 @@ char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
 bool PBAAS_TESTMODE;
 uint160 ASSETCHAINS_CHAINID;
 uint160 VERUS_CHAINID;
+std::string VERUS_CHAINNAME;
 int64_t MAX_MONEY = 200000000 * 100000000LL;
 uint64_t ASSETCHAINS_SUPPLY;
 uint16_t BITCOIND_RPCPORT = 7771;
index 6f34a236a9edaddffb8c9ac528e1258930b5ad34..58beb3b8ea6305337e6822168a63b7e1107721fb 100644 (file)
@@ -222,6 +222,8 @@ bool AsyncRPCOperation_sendmany::main_impl() {
     bool isPureTaddrOnlyTx = (isfromtaddr_ && z_outputs_.size() == 0);
     CAmount minersFee = fee_;
 
+    uint solutionVersion = CConstVerusSolutionVector::GetVersionByHeight(chainActive.Height() + 1);
+
     // When spending coinbase utxos, you can only specify a single zaddr as the change must go somewhere
     // and if there are multiple zaddrs, we don't know where to send it.
     if (isfromtaddr_) {
@@ -235,9 +237,9 @@ bool AsyncRPCOperation_sendmany::main_impl() {
             bool b = find_utxos(false);
             if (!b) {
                 if (isMultipleZaddrOutput) {
-                    throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any non-coinbase UTXOs to spend. Coinbase UTXOs can only be sent to a single zaddr recipient.");
+                    throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any coinbase UTXOs without shielding requirements to spend. Protected coinbase UTXOs can only be sent to a single zaddr recipient.");
                 } else {
-                    throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any non-coinbase UTXOs to spend.");
+                    throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any coinbase UTXOs without shielding requirements to spend.");
                 }
             }
         }
@@ -938,7 +940,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
     return true;
 }
 
-bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false) 
+bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptProtectedCoinbase=false) 
 {
     std::set<CTxDestination> destinations;
     destinations.insert(fromtaddr_);
@@ -948,7 +950,7 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false)
     vector<COutput> vecOutputs;
 
     LOCK2(cs_main, pwalletMain->cs_wallet);
-    pwalletMain->AvailableCoins(vecOutputs, false, NULL, true, fAcceptCoinbase);
+    pwalletMain->AvailableCoins(vecOutputs, false, NULL, false, true, fAcceptProtectedCoinbase);
 
     BOOST_FOREACH(const COutput& out, vecOutputs) {
         CTxDestination dest;
@@ -979,16 +981,9 @@ bool AsyncRPCOperation_sendmany::find_utxos(bool fAcceptCoinbase=false)
             }
         }
 
-        // By default we ignore coinbase outputs if coinbase shielding is required
-        // TODO: audit use of fAcceptCoinbase to ensure that in all cases when coinbase is not required to be shielded that this is skipped
-        bool isCoinbase = out.tx->IsCoinBase();
-        if (isCoinbase && fAcceptCoinbase==false) {
-            continue;
-        }
-
         CAmount nValue = out.tx->vout[out.i].nValue;
         
-        SendManyInputUTXO utxo(out.tx->GetHash(), out.i, nValue, isCoinbase, scriptPubKey);
+        SendManyInputUTXO utxo(out.tx->GetHash(), out.i, nValue, out.tx->IsCoinBase(), scriptPubKey);
         t_inputs_.push_back(utxo);
     }
 
index a9e9044217cd8fafc9f96a5a408111e02dd11922..4fa929d28eae1c20140f52a84816bac0add6086e 100644 (file)
@@ -111,7 +111,7 @@ private:
     void add_taddr_change_output_to_tx(CReserveKey& keyChange, CAmount amount);
     void add_taddr_outputs_to_tx();
     bool find_unspent_notes();
-    bool find_utxos(bool fAcceptCoinbase);
+    bool find_utxos(bool fAcceptProtectedCoinbase);
     std::array<unsigned char, ZC_MEMO_SIZE> get_memo_from_hex_string(std::string s);
     bool main_impl();
 
index a60495bc96f07bd8c422d1c93ab5b37de5585f6d..07ffd9db886b5d50673a8550bda16f2200d2e0c4 100644 (file)
@@ -4590,7 +4590,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
 
     // Get available utxos
     vector<COutput> vecOutputs;
-    pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true);
+    pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true, true);
 
     // Find unspent coinbase utxos and update estimated size
     BOOST_FOREACH(const COutput& out, vecOutputs) {
@@ -4720,7 +4720,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
         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`"
+            "\nMerge multiple UTXOs and notes into a single UTXO or note. Protected 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"
             "\nare unlocked.  The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
@@ -4929,7 +4929,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
     if (useAnyUTXO || taddrs.size() > 0) {
         // Get available utxos
         vector<COutput> vecOutputs;
-        pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
+        pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true, false);
 
         // Find unspent utxos and update estimated size
         for (const COutput& out : vecOutputs) {
index 5674808b408c5fae46211c771961d899818862cb..8e9824cbf5e744bd8bdd9cee8ead47c12e2f7637 100644 (file)
@@ -1496,13 +1496,14 @@ bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult,
     auto consensusParams = Params().GetConsensus();
     CValidationState state;
 
-    pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, !consensusParams.fCoinbaseMustBeProtected);
+    pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, true, false);
 
     if (pastBlockIndex = komodo_chainactive(nHeight - 100))
     {
         uint256 pastHash = pastBlockIndex->GetVerusEntropyHash();
         CPOSNonce curNonce;
         uint32_t srcIndex;
+        uint32_t solutionVersion = CConstVerusSolutionVector::activationHeight.ActiveVersion(nHeight);
 
         BOOST_FOREACH(COutput &txout, vecOutputs)
         {
@@ -1512,7 +1513,7 @@ bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult,
                 int32_t txSize = GetSerializeSize(s, *(CTransaction *)txout.tx);
 
                 //printf("Serialized size of transaction %s is %lu\n", txout.tx->GetHash().GetHex().c_str(), txSize);
-                if (txSize > MAX_TX_SIZE_FOR_STAKING)
+                if (solutionVersion >= CActivationHeight::SOLUTION_VERUSV4 && txSize > MAX_TX_SIZE_FOR_STAKING)
                 {
                     LogPrintf("Transaction %s is too large to stake. Serialized size == %lu\n", txout.tx->GetHash().GetHex().c_str(), txSize);
                 }
@@ -1522,8 +1523,7 @@ bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult,
                 uint256 txHash = txout.tx->GetHash();
                 checkStakeTx.vin.push_back(CTxIn(COutPoint(txHash, txout.i)));
 
-                if (txSize <= MAX_TX_SIZE_FOR_STAKING &&
-                    (!pwinner || UintToArith256(curNonce) > UintToArith256(pBlock->nNonce)) &&
+                if ((!pwinner || UintToArith256(curNonce) > UintToArith256(pBlock->nNonce)) &&
                     (Solver(txout.tx->vout[txout.i].scriptPubKey, whichType, vSolutions) && (whichType == TX_PUBKEY || whichType == TX_PUBKEYHASH)) &&
                     !cheatList.IsUTXOInList(COutPoint(txHash, txout.i), nHeight <= 100 ? 1 : nHeight-100) &&
                     view.AccessCoins(txHash) &&
@@ -1542,7 +1542,7 @@ bool CWallet::VerusSelectStakeOutput(CBlock *pBlock, arith_uint256 &hashResult,
             voutNum = pwinner->i;
             pBlock->nNonce = curNonce;
 
-            if (CConstVerusSolutionVector::activationHeight.ActiveVersion(nHeight) == CActivationHeight::SOLUTION_VERUSV4)
+            if (solutionVersion >= CActivationHeight::SOLUTION_VERUSV4)
             {
                 CDataStream txStream = CDataStream(SER_NETWORK, PROTOCOL_VERSION);
 
@@ -4357,13 +4357,14 @@ CAmount CWallet::GetImmatureWatchOnlyReserveBalance() const
 uint64_t komodo_interestnew(int32_t txheight,uint64_t nValue,uint32_t nLockTime,uint32_t tiptime);
 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);
 
-void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase) const
+void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue, bool fIncludeCoinBase, bool fIncludeProtectedCoinbase) const
 {
     uint64_t interest,*ptr;
     vCoins.clear();
 
     {
         LOCK2(cs_main, cs_wallet);
+        uint32_t nHeight = chainActive.Height() + 1;
         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
         {
             const uint256& wtxid = it->first;
@@ -4375,16 +4376,22 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
             if (fOnlyConfirmed && !pcoin->IsTrusted())
                 continue;
 
-            if (pcoin->IsCoinBase() && !fIncludeCoinBase)
+            bool isCoinbase = pcoin->IsCoinBase();
+            if (isCoinbase && !fIncludeCoinBase)
                 continue;
-
-            if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+            
+            if (isCoinbase && pcoin->GetBlocksToMaturity() > 0)
                 continue;
 
             int nDepth = pcoin->GetDepthInMainChain();
             if (nDepth < 0)
                 continue;
  
+            uint32_t coinHeight = nHeight - nDepth;
+            // even if we should include coinbases, we may opt to exclude protected coinbases, which must only be included when shielding
+            if (isCoinbase && !fIncludeProtectedCoinbase && Params().GetConsensus().fCoinbaseMustBeProtected && (CConstVerusSolutionVector::GetVersionByHeight(coinHeight) < CActivationHeight::SOLUTION_VERUSV3))
+                continue;
+
             for (int i = 0; i < pcoin->vout.size(); i++)
             {
                 isminetype mine = IsMine(pcoin->vout[i]);
@@ -4659,9 +4666,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
     return true;
 }
 
-bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet,  bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl) const
+bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet,  bool& fOnlyProtectedCoinbaseCoinsRet, bool& fNeedProtectedCoinbaseCoinsRet, const CCoinControl* coinControl) const
 {
-    // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos.
+    // Output parameter fOnlyProtectedCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos.
     uint64_t tmp; int32_t retval;
     //if ( interestp == 0 )
     //{
@@ -4669,15 +4676,15 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
     //    *interestp = 0;
     //}
     vector<COutput> vCoinsNoCoinbase, vCoinsWithCoinbase;
-    AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, false);
-    AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true);
-    fOnlyCoinbaseCoinsRet = vCoinsNoCoinbase.size() == 0 && vCoinsWithCoinbase.size() > 0;
+    AvailableCoins(vCoinsNoCoinbase, true, coinControl, false, true, false);
+    AvailableCoins(vCoinsWithCoinbase, true, coinControl, false, true, true);
+    fOnlyProtectedCoinbaseCoinsRet = vCoinsNoCoinbase.size() == 0 && vCoinsWithCoinbase.size() > 0;
 
     // If coinbase utxos can only be sent to zaddrs, exclude any coinbase utxos from coin selection.
     bool fProtectCoinbase = Params().GetConsensus().fCoinbaseMustBeProtected;
     vector<COutput> vCoins = (fProtectCoinbase) ? vCoinsNoCoinbase : vCoinsWithCoinbase;
 
-    // Output parameter fNeedCoinbaseCoinsRet is set to true if coinbase utxos need to be spent to meet target amount
+    // Output parameter fNeedProtectedCoinbaseCoinsRet is set to true if coinbase utxos that must be shielded need to be spent to meet target amount
     if (fProtectCoinbase && vCoinsWithCoinbase.size() > vCoinsNoCoinbase.size()) {
         CAmount value = 0;
         for (const COutput& out : vCoinsNoCoinbase) {
@@ -4698,7 +4705,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
                 if ( KOMODO_EXCHANGEWALLET == 0 )
                     valueWithCoinbase += out.tx->vout[out.i].interest;
             }
-            fNeedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue);
+            fNeedProtectedCoinbaseCoinsRet = (valueWithCoinbase >= nTargetValue);
         }
     }
     // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
@@ -5130,15 +5137,15 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
                 // Choose coins to use
                 set<pair<const CWalletTx*,unsigned int> > setCoins;
                 CAmount nValueIn = 0;
-                bool fOnlyCoinbaseCoins = false;
-                bool fNeedCoinbaseCoins = false;
+                bool fOnlyProtectedCoinbaseCoins = false;
+                bool fNeedProtectedCoinbaseCoins = false;
                 interest2 = 0;
-                if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyCoinbaseCoins, fNeedCoinbaseCoins, coinControl))
+                if (!SelectCoins(nTotalValue, setCoins, nValueIn, fOnlyProtectedCoinbaseCoins, fNeedProtectedCoinbaseCoins, coinControl))
                 {
-                    if (fOnlyCoinbaseCoins && Params().GetConsensus().fCoinbaseMustBeProtected) {
-                        strFailReason = _("Coinbase funds can only be sent to a zaddr");
-                    } else if (fNeedCoinbaseCoins) {
-                        strFailReason = _("Insufficient funds, coinbase funds can only be spent after they have been sent to a zaddr");
+                    if (fOnlyProtectedCoinbaseCoins) {
+                        strFailReason = _("Coinbase funds earned while shielding protection is active can only be sent to a zaddr");
+                    } else if (fNeedProtectedCoinbaseCoins) {
+                        strFailReason = _("Insufficient funds, protected coinbase funds can only be spent after they have been sent to a zaddr");
                     } else {
                         strFailReason = _("Insufficient funds");
                     }
index 441729ce068f9e7d6abd198f31cb1a7000222c4f..a761b300a2e450caa4612705e77a2516782afe0d 100644 (file)
@@ -1035,7 +1035,7 @@ public:
     //! check whether we are allowed to upgrade (or already support) to the named feature
     bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
 
-    void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, bool fIncludeCoinBase=true) const;
+    void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, bool fIncludeCoinBase=true, bool fIncludeProtectedCoinbase=true) const;
     void AvailableReserveCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeCoinBase) const;
     bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const;
     bool SelectReserveCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const;
This page took 0.064103 seconds and 4 git commands to generate.