diff --git a/src/hdmint/tracker.cpp b/src/hdmint/tracker.cpp index 3af7d95a2e..0c2b7b84d3 100644 --- a/src/hdmint/tracker.cpp +++ b/src/hdmint/tracker.cpp @@ -387,6 +387,7 @@ bool CHDMintTracker::UpdateMetaStatus(const std::set& setMempool, CMint COutPoint outPoint; sigma::PublicCoin pubCoin(mint.GetPubCoinValue(), mint.denom); bool isMintInChain = GetOutPoint(outPoint, pubCoin); + LogPrintf("UpdateMetaStatus : isMintInChain: %d\n", isMintInChain); const uint256& txidMint = outPoint.hash; //See if there is internal record of spending this mint (note this is memory only, would reset on restart - next function checks this) @@ -396,10 +397,13 @@ bool CHDMintTracker::UpdateMetaStatus(const std::set& setMempool, CMint if(!isPendingSpend && fSpend) isPendingSpend = IsMempoolSpendOurs(setMempool, mint.hashSerial); + LogPrintf("UpdateMetaStatus : isPendingSpend: %d\n", isPendingSpend); + // See if there is a blockchain record of spending this mint CSigmaState *sigmaState = sigma::CSigmaState::GetState(); Scalar bnSerial; bool isConfirmedSpend = sigmaState->IsUsedCoinSerialHash(bnSerial, mint.hashSerial); + LogPrintf("UpdateMetaStatus : isConfirmedSpend: %d\n", isConfirmedSpend); bool isUsed = isPendingSpend || isConfirmedSpend; @@ -421,6 +425,8 @@ bool CHDMintTracker::UpdateMetaStatus(const std::set& setMempool, CMint mint.txid = txidMint; } + LogPrintf("UpdateMetaStatus : mint.txid = %d\n", mint.txid.GetHex()); + if (setMempool.count(mint.txid)) { if(mint.nHeight>-1) mint.nHeight = -1; if(mint.nId>-1) mint.nId = -1; @@ -550,6 +556,8 @@ void CHDMintTracker::UpdateMintStateFromMempool(const std::vector& std::set setMempool = GetMempoolTxids(); for (auto& pubcoin : pubCoins) { uint256 hashPubcoin = primitives::GetPubCoinValueHash(pubcoin); + + LogPrintf("UpdateMintStateFromMempool: hashPubcoin=%d\n", hashPubcoin.GetHex()); // Check hashPubcoin in db if(walletdb.ReadMintPoolPair(hashPubcoin, hashSeedMasterEntry, seedId, nCount)){ // If found in db but not in memory - this is likely a resync diff --git a/src/hdmint/wallet.cpp b/src/hdmint/wallet.cpp index c774ace493..cfe6b443dc 100644 --- a/src/hdmint/wallet.cpp +++ b/src/hdmint/wallet.cpp @@ -29,6 +29,7 @@ CHDMintWallet::CHDMintWallet(const std::string& strWalletFile) : tracker(strWall // Use MasterKeyId from HDChain as index for mintpool uint160 hashSeedMaster = pwalletMain->GetHDChain().masterKeyID; + LogPrintf("hashSeedMaster: %d\n", hashSeedMaster.GetHex()); if (!SetupWallet(hashSeedMaster)) { LogPrintf("%s: failed to save deterministic seed for hashseed %s\n", __func__, hashSeedMaster.GetHex()); @@ -37,7 +38,6 @@ CHDMintWallet::CHDMintWallet(const std::string& strWalletFile) : tracker(strWall } bool CHDMintWallet::SetupWallet(const uint160& hashSeedMaster, bool fResetCount) { - CWalletDB walletdb(strWalletFile); if (pwalletMain->IsLocked()) return false; @@ -65,29 +65,38 @@ bool CHDMintWallet::SetupWallet(const uint160& hashSeedMaster, bool fResetCount) } // Regenerate mintPool entry from given values -void CHDMintWallet::RegenerateMintPoolEntry(const uint160& mintHashSeedMaster, CKeyID& seedId, const int32_t& nCount) +std::pair CHDMintWallet::RegenerateMintPoolEntry(const uint160& mintHashSeedMaster, CKeyID& seedId, const int32_t& nCount) { + // hashPubcoin, hashSerial + std::pair nIndexes; + CWalletDB walletdb(strWalletFile); //Is locked if (pwalletMain->IsLocked()) - return; + throw ZerocoinException("Error: Please enter the wallet passphrase with walletpassphrase first."); uint512 seedZerocoin; if(!CreateZerocoinSeed(seedZerocoin, nCount, seedId, false)) - return; + throw ZerocoinException("Unable to create seed for mint regeneration."); GroupElement commitmentValue; sigma::PrivateCoin coin(sigma::Params::get_default(), sigma::CoinDenomination::SIGMA_DENOM_1); if(!SeedToZerocoin(seedZerocoin, commitmentValue, coin)) - return; + throw ZerocoinException("Unable to create zerocoin from seed in mint regeneration."); uint256 hashPubcoin = primitives::GetPubCoinValueHash(commitmentValue); + uint256 hashSerial = primitives::GetSerialHash(coin.getSerialNumber()); MintPoolEntry mintPoolEntry(mintHashSeedMaster, seedId, nCount); mintPool.Add(make_pair(hashPubcoin, mintPoolEntry)); - CWalletDB(strWalletFile).WritePubcoin(primitives::GetSerialHash(coin.getSerialNumber()), commitmentValue); + CWalletDB(strWalletFile).WritePubcoin(hashSerial, commitmentValue); CWalletDB(strWalletFile).WriteMintPoolPair(hashPubcoin, mintPoolEntry); - LogPrintf("%s : hashSeedMaster=%s hashPubcoin=%s count=%d\n", __func__, hashSeedMaster.GetHex(), hashPubcoin.GetHex(), nCount); + LogPrintf("%s : hashSeedMaster=%s hashPubcoin=%s seedId=%s\n count=%d\n", __func__, hashSeedMaster.GetHex(), hashPubcoin.GetHex(), seedId.GetHex(), nCount); + + nIndexes.first = hashPubcoin; + nIndexes.second = hashSerial; + + return nIndexes; } @@ -129,7 +138,7 @@ void CHDMintWallet::GenerateMintPool(int32_t nIndex) mintPool.Add(make_pair(hashPubcoin, mintPoolEntry)); CWalletDB(strWalletFile).WritePubcoin(primitives::GetSerialHash(coin.getSerialNumber()), commitmentValue); CWalletDB(strWalletFile).WriteMintPoolPair(hashPubcoin, mintPoolEntry); - LogPrintf("%s : hashSeedMaster=%s hashPubcoin=%s count=%d\n", __func__, hashSeedMaster.GetHex(), hashPubcoin.GetHex(), nLastCount); + LogPrintf("%s : hashSeedMaster=%s hashPubcoin=%s seedId=%d count=%d\n", __func__, hashSeedMaster.GetHex(), hashPubcoin.GetHex(), seedId.GetHex(), nLastCount); } // Update local + DB entries for count last generated @@ -142,12 +151,29 @@ bool CHDMintWallet::LoadMintPoolFromDB() { vector> listMintPool = CWalletDB(strWalletFile).ListMintPool(); - for (auto& mintPoolPair : listMintPool) + for (auto& mintPoolPair : listMintPool){ + LogPrintf("LoadMintPoolFromDB: hashPubcoin: %d hashSeedMaster: %d seedId: %d nCount: %s\n", + mintPoolPair.first.GetHex(), get<0>(mintPoolPair.second).GetHex(), get<1>(mintPoolPair.second).GetHex(), get<2>(mintPoolPair.second)); mintPool.Add(mintPoolPair); + } return true; } +bool CHDMintWallet::GetSerialForPubcoin(const std::vector>& serialPubcoinPairs, const uint256& hashPubcoin, uint256& hashSerial) +{ + bool fFound = false; + for(const auto& serialPubcoinPair : serialPubcoinPairs){ + if(hashPubcoin == primitives::GetPubCoinValueHash(serialPubcoinPair.second)){ + hashSerial = serialPubcoinPair.first; + fFound = true; + break; + } + } + + return fFound; +} + //Catch the counter up with the chain void CHDMintWallet::SyncWithChain(bool fGenerateMintPool, boost::optional>> listMints) { @@ -453,6 +479,9 @@ bool CHDMintWallet::GenerateMint(const sigma::CoinDenomination denom, sigma::Pri UpdateCountLocal(); } + LogPrintf("GenerateMint: hashSeedMaster: %s seedId: %s nCount: %d\n", + get<0>(mintPoolEntry.get()).GetHex(), get<1>(mintPoolEntry.get()).GetHex(), get<2>(mintPoolEntry.get())); + uint512 seedZerocoin; CreateZerocoinSeed(seedZerocoin, get<2>(mintPoolEntry.get()), get<1>(mintPoolEntry.get()), false); @@ -465,6 +494,7 @@ bool CHDMintWallet::GenerateMint(const sigma::CoinDenomination denom, sigma::Pri uint256 hashSerial = primitives::GetSerialHash(coin.getSerialNumber()); dMint = CHDMint(get<2>(mintPoolEntry.get()), get<1>(mintPoolEntry.get()), hashSerial, coin.getPublicCoin().getValue()); + LogPrintf("GenerateMint: hashPubcoin: %s\n", dMint.GetPubCoinHash().GetHex()); dMint.SetDenomination(denom); return true; diff --git a/src/hdmint/wallet.h b/src/hdmint/wallet.h index 9d94cadaf1..84d245ba90 100644 --- a/src/hdmint/wallet.h +++ b/src/hdmint/wallet.h @@ -35,9 +35,10 @@ class CHDMintWallet bool GenerateMint(const sigma::CoinDenomination denom, sigma::PrivateCoin& coin, CHDMint& dMint, boost::optional mintPoolEntry = boost::none); bool LoadMintPoolFromDB(); bool RegenerateMint(const CHDMint& dMint, CSigmaEntry& zerocoin); + bool GetSerialForPubcoin(const std::vector>& serialPubcoinPairs, const uint256& hashPubcoin, uint256& hashSerial); bool IsSerialInBlockchain(const uint256& hashSerial, int& nHeightTx, uint256& txidSpend, CTransaction& tx); bool TxOutToPublicCoin(const CTxOut& txout, sigma::PublicCoin& pubCoin, CValidationState& state); - void RegenerateMintPoolEntry(const uint160& mintHashSeedMaster, CKeyID& seedId, const int32_t& nCount); + std::pair RegenerateMintPoolEntry(const uint160& mintHashSeedMaster, CKeyID& seedId, const int32_t& nCount); void GenerateMintPool(int32_t nIndex = 0); bool SetMintSeedSeen(std::pair mintPoolEntryPair, const int& nHeight, const uint256& txid, const sigma::CoinDenomination& denom); bool SeedToZerocoin(const uint512& seedZerocoin, GroupElement& bnValue, sigma::PrivateCoin& coin); diff --git a/src/main.cpp b/src/main.cpp index 54e6c05b2d..1dced6e3f3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1820,6 +1820,7 @@ bool AcceptToMemoryPoolWorker( LogPrintf("Updating mint tracker state from Mempool.."); #ifdef ENABLE_WALLET if (zwalletMain) { + LogPrintf("Updating spend state from Mempool.."); zwalletMain->GetTracker().UpdateSpendStateFromMempool(zcSpendSerialsV3); } #endif @@ -1835,6 +1836,7 @@ bool AcceptToMemoryPoolWorker( } } if (zwalletMain) { + LogPrintf("Updating mint state from Mempool.."); zwalletMain->GetTracker().UpdateMintStateFromMempool(zcMintPubcoinsV3); } } @@ -3587,11 +3589,14 @@ ConnectTip(CValidationState &state, const CChainParams &chainparams, CBlockIndex #ifdef ENABLE_WALLET // Sync with HDMint wallet if (zwalletMain) { + LogPrintf("Checking if block contains wallet mints..\n"); if (pblock->sigmaTxInfo->spentSerials.size() > 0) { + LogPrintf("HDmint: UpdateSpendStateFromBlock. [height: %d]\n", GetHeight()); zwalletMain->GetTracker().UpdateSpendStateFromBlock(pblock->sigmaTxInfo->spentSerials); } if (pblock->sigmaTxInfo->mints.size() > 0) { + LogPrintf("HDmint: UpdateMintStateFromBlock. [height: %d]\n", GetHeight()); zwalletMain->GetTracker().UpdateMintStateFromBlock(pblock->sigmaTxInfo->mints); } } diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index de2118dc9a..7116b34f98 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -70,6 +70,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listunspent", 0 }, { "listunspent", 1 }, { "listunspent", 2 }, + { "regeneratemintpool", 0 }, { "listunspentmintzerocoins", 0 }, { "listunspentmintzerocoins", 1 }, { "listunspentmintzerocoins", 2 }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 313b1d024b..f835e0b29a 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2652,6 +2652,56 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) return result; } +UniValue regeneratemintpool(const UniValue ¶ms, bool fHelp) { + + if (pwalletMain->IsLocked()) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, + "Error: Please enter the wallet passphrase with walletpassphrase first."); + + if (!pwalletMain->IsHDSeedAvailable() || !zwalletMain) { + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, + "Error: Can only regenerate mintpool on a HD-enabled wallet."); + } + + CWalletDB walletdb(pwalletMain->strWalletFile); + vector> listMintPool = walletdb.ListMintPool(); + std::vector> serialPubcoinPairs = walletdb.ListSerialPubcoinPairs(); + + // + std::pair nIndexes; + + uint256 oldHashSerial; + uint256 oldHashPubcoin; + + bool reindexRequired = false; + + for (auto& mintPoolPair : listMintPool){ + LogPrintf("regeneratemintpool: hashPubcoin: %d hashSeedMaster: %d seedId: %d nCount: %s\n", + mintPoolPair.first.GetHex(), get<0>(mintPoolPair.second).GetHex(), get<1>(mintPoolPair.second).GetHex(), get<2>(mintPoolPair.second)); + + oldHashPubcoin = mintPoolPair.first; + bool hasSerial = zwalletMain->GetSerialForPubcoin(serialPubcoinPairs, oldHashPubcoin, oldHashSerial); + + MintPoolEntry entry = mintPoolPair.second; + nIndexes = zwalletMain->RegenerateMintPoolEntry(get<0>(entry),get<1>(entry),get<2>(entry)); + + if(nIndexes.first != oldHashPubcoin){ + walletdb.EraseMintPoolPair(oldHashPubcoin); + reindexRequired = true; + } + + if(!hasSerial || nIndexes.second != oldHashSerial){ + walletdb.ErasePubcoin(oldHashSerial); + reindexRequired = true; + } + } + + if(reindexRequired) + return "Mintpool issue corrected. Please shutdown zcoin and restart with -reindex flag."; + + return "No issues with mintpool detected."; +} + //[zcoin]: zerocoin section // zerocoin section @@ -4033,6 +4083,7 @@ static const CRPCCommand commands[] = { "wallet", "walletpassphrase", &walletpassphrase, true }, { "wallet", "removeprunedfunds", &removeprunedfunds, true }, { "wallet", "setmininput", &setmininput, false }, + { "wallet", "regeneratemintpool", ®eneratemintpool, false }, { "wallet", "listunspentmintzerocoins", &listunspentmintzerocoins, false }, { "wallet", "listunspentsigmamints", &listunspentsigmamints, false }, { "wallet", "mint", &mint, false }, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5f12f894f7..1556c80630 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -7906,8 +7906,6 @@ bool CWallet::InitLoadWallet() { zwalletMain = new CHDMintWallet(pwalletMain->strWalletFile); } - - RegisterValidationInterface(walletInstance); CBlockIndex *pindexRescan = chainActive.Tip(); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 85ee1c1b05..6151369553 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1327,6 +1327,11 @@ bool CWalletDB::ReadPubcoin(const uint256& hashSerial, GroupElement& pubcoin) return Read(make_pair(string("pubcoin"), hashSerial), pubcoin); } +bool CWalletDB::ErasePubcoin(const uint256& hashSerial) +{ + return Erase(make_pair(string("pubcoin"), hashSerial)); +} + std::vector> CWalletDB::ListSerialPubcoinPairs() { std::vector> listSerialPubcoin; @@ -1372,6 +1377,11 @@ std::vector> CWalletDB::ListSerialPubcoinPairs( } +bool CWalletDB::EraseMintPoolPair(const uint256& hashPubcoin) +{ + return Erase(make_pair(string("mintpool"), hashPubcoin)); +} + bool CWalletDB::WriteMintPoolPair(const uint256& hashPubcoin, const std::tuple& hashSeedMintPool) { return Write(make_pair(string("mintpool"), hashPubcoin), hashSeedMintPool); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 7b7ff1b8a7..617158bc7f 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -274,7 +274,9 @@ class CWalletDB : public CDB std::list ListHDMints(); bool WritePubcoin(const uint256& hashSerial, const GroupElement& hashPubcoin); bool ReadPubcoin(const uint256& hashSerial, GroupElement& hashPubcoin); + bool ErasePubcoin(const uint256& hashSerial); std::vector> ListSerialPubcoinPairs(); + bool EraseMintPoolPair(const uint256& hashPubcoin); bool WriteMintPoolPair(const uint256& hashPubcoin, const std::tuple& hashSeedMintPool); bool ReadMintPoolPair(const uint256& hashPubcoin, uint160& hashSeedMaster, CKeyID& seedId, int32_t& nCount); std::vector> ListMintPool();