Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RPC function to regenerate mint pool if incorrect indexes used #566

Merged
merged 7 commits into from
Aug 1, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/hdmint/tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ bool CHDMintTracker::UpdateMetaStatus(const std::set<uint256>& 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)
Expand All @@ -396,10 +397,13 @@ bool CHDMintTracker::UpdateMetaStatus(const std::set<uint256>& 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;

Expand All @@ -421,6 +425,8 @@ bool CHDMintTracker::UpdateMetaStatus(const std::set<uint256>& 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;
Expand Down Expand Up @@ -550,6 +556,8 @@ void CHDMintTracker::UpdateMintStateFromMempool(const std::vector<GroupElement>&
std::set<uint256> 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
Expand Down
49 changes: 40 additions & 9 deletions src/hdmint/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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;
Expand Down Expand Up @@ -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<uint256,uint256> CHDMintWallet::RegenerateMintPoolEntry(const uint160& mintHashSeedMaster, CKeyID& seedId, const int32_t& nCount)
{
// hashPubcoin, hashSerial
std::pair<uint256,uint256> 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;

}

Expand Down Expand Up @@ -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
Expand All @@ -142,12 +151,30 @@ bool CHDMintWallet::LoadMintPoolFromDB()
{
vector<std::pair<uint256, MintPoolEntry>> 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<std::pair<uint256, GroupElement>>& serialPubcoinPairs, const uint256& hashPubcoin, uint256& hashSerial)
{
bool fFound = false;
for(auto serialPubcoinPair : serialPubcoinPairs){
a-bezrukov marked this conversation as resolved.
Show resolved Hide resolved
GroupElement pubcoin = serialPubcoinPair.second;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify what you mean here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pubcoin is a copy now. I think making it GroupElement const & pubcoin = serialPubcoinPair.second will be better performance-wise.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be like this const GroupElement& pubcoin.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be more readable if we keep this line, only make it const reference.

if(hashPubcoin == primitives::GetPubCoinValueHash(pubcoin)){
hashSerial = serialPubcoinPair.first;
fFound = true;
break;
}
}

return fFound;
}

//Catch the counter up with the chain
void CHDMintWallet::SyncWithChain(bool fGenerateMintPool, boost::optional<std::list<std::pair<uint256, MintPoolEntry>>> listMints)
{
Expand Down Expand Up @@ -453,6 +480,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);

Expand All @@ -465,6 +495,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;
Expand Down
3 changes: 2 additions & 1 deletion src/hdmint/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ class CHDMintWallet
bool GenerateMint(const sigma::CoinDenomination denom, sigma::PrivateCoin& coin, CHDMint& dMint, boost::optional<MintPoolEntry> mintPoolEntry = boost::none);
bool LoadMintPoolFromDB();
bool RegenerateMint(const CHDMint& dMint, CSigmaEntry& zerocoin);
bool GetSerialForPubcoin(const std::vector<std::pair<uint256, GroupElement>>& 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<uint256,uint256> RegenerateMintPoolEntry(const uint160& mintHashSeedMaster, CKeyID& seedId, const int32_t& nCount);
void GenerateMintPool(int32_t nIndex = 0);
bool SetMintSeedSeen(std::pair<uint256,MintPoolEntry> mintPoolEntryPair, const int& nHeight, const uint256& txid, const sigma::CoinDenomination& denom);
bool SeedToZerocoin(const uint512& seedZerocoin, GroupElement& bnValue, sigma::PrivateCoin& coin);
Expand Down
5 changes: 5 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,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
Expand All @@ -1821,6 +1822,7 @@ bool AcceptToMemoryPoolWorker(
}
}
if (zwalletMain) {
LogPrintf("Updating mint state from Mempool..");
zwalletMain->GetTracker().UpdateMintStateFromMempool(zcMintPubcoinsV3);
}
}
Expand Down Expand Up @@ -3572,11 +3574,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);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listunspent", 0 },
{ "listunspent", 1 },
{ "listunspent", 2 },
{ "regeneratemintpool", 0 },
{ "listunspentmintzerocoins", 0 },
{ "listunspentmintzerocoins", 1 },
{ "listunspentmintzerocoins", 2 },
Expand Down
51 changes: 51 additions & 0 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2652,6 +2652,56 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
return result;
}

UniValue regeneratemintpool(const UniValue &params, 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<std::pair<uint256, MintPoolEntry>> listMintPool = walletdb.ListMintPool();
std::vector<std::pair<uint256, GroupElement>> serialPubcoinPairs = walletdb.ListSerialPubcoinPairs();

// <hashPubcoin, hashSerial>
std::pair<uint256,uint256> 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

Expand Down Expand Up @@ -4033,6 +4083,7 @@ static const CRPCCommand commands[] =
{ "wallet", "walletpassphrase", &walletpassphrase, true },
{ "wallet", "removeprunedfunds", &removeprunedfunds, true },
{ "wallet", "setmininput", &setmininput, false },
{ "wallet", "regeneratemintpool", &regeneratemintpool, false },
{ "wallet", "listunspentmintzerocoins", &listunspentmintzerocoins, false },
{ "wallet", "listunspentsigmamints", &listunspentsigmamints, false },
{ "wallet", "mint", &mint, false },
Expand Down
2 changes: 0 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7893,8 +7893,6 @@ bool CWallet::InitLoadWallet() {
zwalletMain = new CHDMintWallet(pwalletMain->strWalletFile);
}



RegisterValidationInterface(walletInstance);

CBlockIndex *pindexRescan = chainActive.Tip();
Expand Down
10 changes: 10 additions & 0 deletions src/wallet/walletdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::pair<uint256, GroupElement>> CWalletDB::ListSerialPubcoinPairs()
{
std::vector<std::pair<uint256, GroupElement>> listSerialPubcoin;
Expand Down Expand Up @@ -1372,6 +1377,11 @@ std::vector<std::pair<uint256, GroupElement>> CWalletDB::ListSerialPubcoinPairs(

}

bool CWalletDB::EraseMintPoolPair(const uint256& hashPubcoin)
{
return Erase(make_pair(string("mintpool"), hashPubcoin));
}

bool CWalletDB::WriteMintPoolPair(const uint256& hashPubcoin, const std::tuple<uint160, CKeyID, int32_t>& hashSeedMintPool)
{
return Write(make_pair(string("mintpool"), hashPubcoin), hashSeedMintPool);
Expand Down
2 changes: 2 additions & 0 deletions src/wallet/walletdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,9 @@ class CWalletDB : public CDB
std::list<CHDMint> ListHDMints();
bool WritePubcoin(const uint256& hashSerial, const GroupElement& hashPubcoin);
bool ReadPubcoin(const uint256& hashSerial, GroupElement& hashPubcoin);
bool ErasePubcoin(const uint256& hashSerial);
std::vector<std::pair<uint256, GroupElement>> ListSerialPubcoinPairs();
bool EraseMintPoolPair(const uint256& hashPubcoin);
bool WriteMintPoolPair(const uint256& hashPubcoin, const std::tuple<uint160, CKeyID, int32_t>& hashSeedMintPool);
bool ReadMintPoolPair(const uint256& hashPubcoin, uint160& hashSeedMaster, CKeyID& seedId, int32_t& nCount);
std::vector<std::pair<uint256, MintPoolEntry>> ListMintPool();
Expand Down