Skip to content

Commit

Permalink
List from mempool fix (#496)
Browse files Browse the repository at this point in the history
* Fix issue with mint list not correct if pending during closing
  • Loading branch information
riordant authored and a-bezrukov committed Jul 9, 2019
1 parent 36a0ef2 commit 0c9b548
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 25 deletions.
99 changes: 80 additions & 19 deletions src/hdmint/tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "libzerocoin/Zerocoin.h"
#include "main.h"
#include "zerocoin_v3.h"
#include "txmempool.h"

using namespace std;
using namespace sigma;
Expand All @@ -36,7 +37,7 @@ void CHDMintTracker::Init()
{
//Load all CZerocoinEntries and CHDMints from the database
if (!fInitialized) {
ListMints(false, false);
ListMints(false, false, false, true);
fInitialized = true;
}
}
Expand Down Expand Up @@ -380,6 +381,32 @@ void CHDMintTracker::RemovePending(const uint256& txid)
mapPendingSpends.erase(hashSerial);
}

bool CHDMintTracker::IsMempoolSpendOurs(const std::set<uint256>& setMempool, const uint256& hashSerial){
// get transaction back from mempool
// if spend, get hash of serial
// if matches mint.hashSerial, mark pending spend.
for(auto& mempoolTxid : setMempool){
auto it = mempool.mapTx.find(mempoolTxid);
if (it == mempool.mapTx.end())
continue;

const CTransaction &tx = it->GetTx();
for (const CTxIn& txin : tx.vin) {
if (txin.IsSigmaSpend()) {
std::unique_ptr<sigma::CoinSpend> spend;
uint32_t pubcoinId;
std::tie(spend, pubcoinId) = sigma::ParseSigmaSpend(txin);
uint256 mempoolHashSerial = primitives::GetSerialHash(spend->getCoinSerialNumber());
if(mempoolHashSerial==hashSerial){
return true;
}
}
}
}

return false;
}

bool CHDMintTracker::UpdateMetaStatus(const std::set<uint256>& setMempool, CMintMeta& mint)
{
uint256 hashPubcoin = mint.GetPubCoinValueHash();
Expand All @@ -390,24 +417,18 @@ bool CHDMintTracker::UpdateMetaStatus(const std::set<uint256>& setMempool, CMint
bool isMintInChain = GetOutPoint(outPoint, pubCoin);
const uint256& txidMint = outPoint.hash;

//See if there is internal record of spending this mint (note this is memory only, would reset on restart)
//See if there is internal record of spending this mint (note this is memory only, would reset on restart - next function checks this)
bool isPendingSpend = static_cast<bool>(mapPendingSpends.count(mint.hashSerial));

// Mempool might hold pending spend
if(!isPendingSpend)
isPendingSpend = IsMempoolSpendOurs(setMempool, mint.hashSerial);

// 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);

// Double check the mempool for pending spend
if (isPendingSpend) {
uint256 txidPendingSpend = mapPendingSpends.at(mint.hashSerial);
if (!setMempool.count(txidPendingSpend) || isConfirmedSpend) {
RemovePending(txidPendingSpend);
isPendingSpend = false;
LogPrintf("%s : Pending txid %s removed because not in mempool\n", __func__, txidPendingSpend.GetHex());
}
}

bool isUsed = isPendingSpend || isConfirmedSpend;

if ((mint.nHeight==-1) || (mint.nId==-1) || !isMintInChain || isUsed != mint.isUsed) {
Expand Down Expand Up @@ -552,6 +573,43 @@ void CHDMintTracker::UpdateSpendStateFromBlock(const sigma::spend_info_container
UpdateFromBlock(mintPoolEntries, updatedMeta);
}

void CHDMintTracker::UpdateSpendStateFromMempool(const vector<Scalar>& spentSerials){
CWalletDB walletdb(strWalletFile);
std::vector<CMintMeta> updatedMeta;
std::list<std::pair<uint256, MintPoolEntry>> mintPoolEntries;
uint160 hashSeedMasterEntry;
CKeyID seedId;
int32_t nCount;
std::set<uint256> setMempool;
{
LOCK(mempool.cs);
mempool.getTransactions(setMempool);
}
for(auto& spentSerial : spentSerials){
uint256 spentSerialHash = primitives::GetSerialHash(spentSerial);
CMintMeta meta;
GroupElement pubcoin;
// Check serialHash in db
if(walletdb.ReadPubcoin(spentSerialHash, pubcoin)){
// If found in db but not in memory - this is likely a resync
if(!Get(spentSerialHash, meta)){
uint256 hashPubcoin = primitives::GetPubCoinValueHash(pubcoin);
if(!walletdb.ReadMintPoolPair(hashPubcoin, hashSeedMasterEntry, seedId, nCount)){
continue;
}
MintPoolEntry mintPoolEntry(hashSeedMasterEntry, seedId, nCount);
mintPoolEntries.push_back(std::make_pair(hashPubcoin, mintPoolEntry));
continue;
}
if(UpdateMetaStatus(setMempool, meta)){
updatedMeta.emplace_back(meta);
}
}
}

UpdateFromBlock(mintPoolEntries, updatedMeta);
}

list<CSigmaEntry> CHDMintTracker::MintsAsZerocoinEntries(bool fUnusedOnly, bool fMatureOnly){
list <CSigmaEntry> listPubcoin;
CWalletDB walletdb(strWalletFile);
Expand All @@ -565,11 +623,12 @@ list<CSigmaEntry> CHDMintTracker::MintsAsZerocoinEntries(bool fUnusedOnly, bool
return listPubcoin;
}

std::vector<CMintMeta> CHDMintTracker::ListMints(bool fUnusedOnly, bool fMatureOnly, bool fUpdateStatus, bool fWrongSeed)
std::vector<CMintMeta> CHDMintTracker::ListMints(bool fUnusedOnly, bool fMatureOnly, bool fUpdateStatus, bool fLoad, bool fWrongSeed)
{
LOCK2(cs_main, pwalletMain->cs_wallet);
std::vector<CMintMeta> setMints;
CWalletDB walletdb(strWalletFile);
if (fUpdateStatus) {
if (fLoad) {
std::list<CSigmaEntry> listMintsDB;
walletdb.ListSigmaPubCoin(listMintsDB);
for (auto& mint : listMintsDB){
Expand Down Expand Up @@ -598,12 +657,14 @@ std::vector<CMintMeta> CHDMintTracker::ListMints(bool fUnusedOnly, bool fMatureO
continue;

// Update the metadata of the mints if requested
if (fUpdateStatus && UpdateMetaStatus(setMempool, mint)) {
if (mint.isArchived)
continue;
if (fUpdateStatus){
if(UpdateMetaStatus(setMempool, mint)) {
if (mint.isArchived)
continue;

// Mint was updated, queue for overwrite
vOverWrite.emplace_back(mint);
// Mint was updated, queue for overwrite
vOverWrite.emplace_back(mint);
}
}

if (fUnusedOnly && mint.isUsed)
Expand Down
4 changes: 3 additions & 1 deletion src/hdmint/tracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class CHDMintTracker
std::string strWalletFile;
std::map<uint256, CMintMeta> mapSerialHashes;
std::map<uint256, uint256> mapPendingSpends; //serialhash, txid of spend
bool IsMempoolSpendOurs(const std::set<uint256>& setMempool, const uint256& hashSerial);
bool UpdateMetaStatus(const std::set<uint256>& setMempool, CMintMeta& mint);
public:
CHDMintTracker(std::string strWalletFile);
Expand All @@ -42,8 +43,9 @@ class CHDMintTracker
void UpdateFromBlock(const std::list<std::pair<uint256, MintPoolEntry>>& mintPoolEntries, const std::vector<CMintMeta>& updatedMeta);
void UpdateMintStateFromBlock(const std::vector<sigma::PublicCoin>& mints);
void UpdateSpendStateFromBlock(const sigma::spend_info_container& spentSerials);
void UpdateSpendStateFromMempool(const vector<Scalar>& spentSerials);
list<CSigmaEntry> MintsAsZerocoinEntries(bool fUnusedOnly = true, bool fMatureOnly = true);
std::vector<CMintMeta> ListMints(bool fUnusedOnly = true, bool fMatureOnly = true, bool fUpdateStatus = true, bool fWrongSeed = false);
std::vector<CMintMeta> ListMints(bool fUnusedOnly = true, bool fMatureOnly = true, bool fUpdateStatus = true, bool fLoad = false, bool fWrongSeed = false);
void RemovePending(const uint256& txid);
void SetPubcoinUsed(const uint256& hashPubcoin, const uint256& txid);
void SetPubcoinNotUsed(const uint256& hashPubcoin);
Expand Down
3 changes: 3 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,9 @@ void ThreadImport(std::vector <boost::filesystem::path> vImportFiles) {
if (!GetBoolArg("-disablewallet", false) && zwalletMain) {
zwalletMain->SyncWithChain();
}
if (GetBoolArg("-zapwallettxes", false)) {
pwalletMain->hdMintTracker->ListMints();
}
#endif
}

Expand Down
10 changes: 7 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1800,10 +1800,14 @@ bool AcceptToMemoryPoolWorker(

if (tx.IsZerocoinSpend() && markZcoinSpendTransactionSerial)
zcState->AddSpendToMempool(zcSpendSerials, hash);
if (tx.IsSigmaSpend() && markZcoinSpendTransactionSerial)
sigmaState->AddSpendToMempool(zcSpendSerialsV3, hash);

if (tx.IsSigmaSpend()){
if(markZcoinSpendTransactionSerial)
sigmaState->AddSpendToMempool(zcSpendSerialsV3, hash);
LogPrintf("Updating mint tracker state from Mempool..");
pwalletMain->hdMintTracker->UpdateSpendStateFromMempool(zcSpendSerialsV3);
}
SyncWithWallets(tx, NULL, NULL);

LogPrintf("AcceptToMemoryPoolWorker -> OK\n");

return true;
Expand Down
7 changes: 5 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2893,7 +2893,7 @@ void CWallet::ListAvailableCoinsMintCoins(vector <COutput> &vCoins, bool fOnlyCo

void CWallet::ListAvailableSigmaMintCoins(vector<COutput> &vCoins, bool fOnlyConfirmed) const {
vCoins.clear();
LOCK(cs_wallet);
LOCK2(cs_main, cs_wallet);
list<CSigmaEntry> listOwnCoins;
CWalletDB walletdb(pwalletMain->strWalletFile);
listOwnCoins = pwalletMain->hdMintTracker->MintsAsZerocoinEntries();
Expand Down Expand Up @@ -6946,7 +6946,7 @@ bool CWallet::CommitSigmaTransaction(CWalletTx& wtxNew, std::vector<CSigmaEntry>
throw std::runtime_error(_("Failed to write coin serial number into wallet"));
}

//Set spent mint as used
//Set spent mint as used in memory
uint256 hashPubcoin = primitives::GetPubCoinValueHash(coin.value);
pwalletMain->hdMintTracker->SetPubcoinUsed(hashPubcoin, wtxNew.GetHash());
CMintMeta metaCheck = pwalletMain->hdMintTracker->GetMetaFromPubcoin(hashPubcoin);
Expand All @@ -6955,6 +6955,9 @@ bool CWallet::CommitSigmaTransaction(CWalletTx& wtxNew, std::vector<CSigmaEntry>
LogPrintf("SpendZerocoin() : %s\n", strError.c_str());
}

//Set spent mint as used in DB
pwalletMain->hdMintTracker->UpdateState(metaCheck);

// update CSigmaEntry
coin.IsUsed = true;
coin.id = id;
Expand Down

0 comments on commit 0c9b548

Please sign in to comment.