110
src/main.cpp
110
src/main.cpp
@@ -642,6 +642,102 @@ UniValue komodo_snapshot(int top)
|
||||
return(result);
|
||||
}
|
||||
|
||||
bool komodo_snapshot2(std::map <std::string, CAmount> &addressAmounts)
|
||||
{
|
||||
if ( fAddressIndex && pblocktree != 0 )
|
||||
{
|
||||
return pblocktree->Snapshot2(addressAmounts, 0);
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
int32_t lastSnapShotHeight = 0;
|
||||
std::vector <std::pair<CAmount, CTxDestination>> vAddressSnapshot;
|
||||
|
||||
bool komodo_dailysnapshot(int32_t height)
|
||||
{
|
||||
int reorglimit = 10; // CHANGE BACK TO 100 AFTER TESTING!
|
||||
uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,undo_height,extraoffset;
|
||||
if ( (extraoffset= height % KOMODO_SNAPSHOT_INTERVAL) != 0 )
|
||||
{
|
||||
// we are on chain init, and need to scan all the way back to the correct height, other wise our node will have a diffrent snapshot to online nodes.
|
||||
// use the notarizationsDB to scan back from the consesnus height to get the offset we need.
|
||||
std::string symbol; Notarisation nota;
|
||||
symbol.assign(ASSETCHAINS_SYMBOL);
|
||||
if ( ScanNotarisationsDB(height-extraoffset, symbol, 100, nota) == 0 )
|
||||
undo_height = height-extraoffset-reorglimit;
|
||||
else undo_height = nota.second.height;
|
||||
//fprintf(stderr, "height.%i-extraoffset.%i = startscanfrom.%i to get undo_height.%i\n", height, extraoffset, height-extraoffset, undo_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are at the right height in connect block to scan back to last notarized height.
|
||||
notarized_height = komodo_notarized_height(&prevMoMheight,¬arized_hash,¬arized_desttxid);
|
||||
notarized_height > height-reorglimit ? undo_height = notarized_height : undo_height = height-reorglimit;
|
||||
}
|
||||
fprintf(stderr, "doing snapshot for height.%i undo_height.%i\n", height, undo_height);
|
||||
// if we already did this height dont bother doing it again, this is just a reorg. The actual snapshot height cannot be reorged.
|
||||
if ( undo_height == lastSnapShotHeight )
|
||||
return true;
|
||||
std::map <std::string, int64_t> addressAmounts;
|
||||
if ( !komodo_snapshot2(addressAmounts) )
|
||||
return false;
|
||||
|
||||
// undo blocks in reverse order
|
||||
for (int32_t n = height; n > undo_height; n--)
|
||||
{
|
||||
//fprintf(stderr, "undoing block.%i\n",n);
|
||||
CBlockIndex *pindex; CBlock block;
|
||||
if ( (pindex= komodo_chainactive(n)) == 0 || komodo_blockload(block, pindex) != 0 )
|
||||
return false;
|
||||
// undo transactions in reverse order
|
||||
for (int32_t i = block.vtx.size() - 1; i >= 0; i--)
|
||||
{
|
||||
const CTransaction &tx = block.vtx[i];
|
||||
CTxDestination vDest;
|
||||
// loop vouts reverse order, remove value recieved.
|
||||
for (unsigned int k = tx.vout.size(); k-- > 0;)
|
||||
{
|
||||
const CTxOut &out = tx.vout[k];
|
||||
if ( ExtractDestination(out.scriptPubKey, vDest) )
|
||||
{
|
||||
addressAmounts[CBitcoinAddress(vDest).ToString()] -= out.nValue;
|
||||
if ( addressAmounts[CBitcoinAddress(vDest).ToString()] < 1 )
|
||||
addressAmounts.erase(CBitcoinAddress(vDest).ToString());
|
||||
//fprintf(stderr, "VOUT: address.%s remove_coins.%li\n",CBitcoinAddress(vDest).ToString().c_str(), out.nValue);
|
||||
}
|
||||
}
|
||||
// loop vins in reverse order, get prevout and return the sent balance.
|
||||
for (unsigned int j = tx.vin.size(); j-- > 0;)
|
||||
{
|
||||
uint256 blockhash; CTransaction txin;
|
||||
if ( !tx.IsCoinImport() && !tx.IsCoinBase() && myGetTransaction(tx.vin[j].prevout.hash,txin,blockhash) )
|
||||
{
|
||||
int vout = tx.vin[j].prevout.n;
|
||||
if ( ExtractDestination(txin.vout[vout].scriptPubKey, vDest) )
|
||||
{
|
||||
//fprintf(stderr, "VIN: address.%s add_coins.%li\n",CBitcoinAddress(vDest).ToString().c_str(), txin.vout[vout].nValue);
|
||||
addressAmounts[CBitcoinAddress(vDest).ToString()] += txin.vout[vout].nValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vAddressSnapshot.clear(); // clear existing snapshot
|
||||
// convert address string to destination for easier conversion to what ever is required, eg, scriptPubKey.
|
||||
for ( auto element : addressAmounts)
|
||||
vAddressSnapshot.push_back(make_pair(element.second, DecodeDestination(element.first)));
|
||||
// sort the vector by amount, highest at top.
|
||||
std::sort(vAddressSnapshot.rbegin(), vAddressSnapshot.rend());
|
||||
//for (int j = 0; j < 50; j++)
|
||||
// fprintf(stderr, "j.%i address.%s nValue.%li\n",j, CBitcoinAddress(vAddressSnapshot[j].second).ToString().c_str(), vAddressSnapshot[j].first );
|
||||
// include only top 5000 address.
|
||||
if ( vAddressSnapshot.size() > 3999 ) vAddressSnapshot.resize(3999);
|
||||
lastSnapShotHeight = undo_height;
|
||||
fprintf(stderr, "vAddressSnapshot.size.%li\n", vAddressSnapshot.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// mapOrphanTransactions
|
||||
@@ -3096,7 +3192,6 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||
uint160 addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr);
|
||||
// undo spending activity
|
||||
addressIndex.push_back(make_pair(CAddressIndexKey(keyType, addrHash, pindex->GetHeight(), i, hash, j, true), prevout.nValue * -1));
|
||||
|
||||
// restore unspent index
|
||||
addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(keyType, addrHash, input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight)));
|
||||
}
|
||||
@@ -3497,8 +3592,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||
fprintf(stderr,"valueout %.8f too big\n",(double)valueout/COIN);
|
||||
return state.DoS(100, error("ConnectBlock(): GetValueOut too big"),REJECT_INVALID,"tx valueout is too big");
|
||||
}
|
||||
prevsum = voutsum;
|
||||
voutsum += valueout;
|
||||
//prevsum = voutsum;
|
||||
//voutsum += valueout;
|
||||
/*if ( KOMODO_VALUETOOBIG(voutsum) != 0 )
|
||||
{
|
||||
fprintf(stderr,"voutsum %.8f too big\n",(double)voutsum/COIN);
|
||||
@@ -4163,6 +4258,13 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
|
||||
komodo_pricesupdate(pindexNew->GetHeight(),pblock);
|
||||
if ( ASSETCHAINS_SAPLING <= 0 && pindexNew->nTime > KOMODO_SAPLING_ACTIVATION - 24*3600 )
|
||||
komodo_activate_sapling(pindexNew);
|
||||
if ( ASSETCHAINS_CC != 0 && KOMODO_SNAPSHOT_INTERVAL != 0 && (pindexNew->GetHeight() % KOMODO_SNAPSHOT_INTERVAL) == 0 && pindexNew->GetHeight() > KOMODO_SNAPSHOT_INTERVAL )
|
||||
{
|
||||
uint64_t start = time(NULL);
|
||||
if ( !komodo_dailysnapshot(pindexNew->GetHeight()) )
|
||||
fprintf(stderr, "daily snapshot failed, please reindex your chain\n"); // maybe force shutdown here?
|
||||
fprintf(stderr, "snapshot completed in: %lu seconds\n", time(NULL)-start);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6102,7 +6204,7 @@ bool CVerifyDB::VerifyDB(CCoinsView *coinsview, int nCheckLevel, int nCheckDepth
|
||||
}
|
||||
|
||||
LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->GetHeight(), nGoodTransactions);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user