void FeeVoteImpl::doValidation (Ledger::ref lastClosedLedger, STObject& baseValidation) { if (lastClosedLedger->getBaseFee () != target_.reference_fee) { if (journal_.info) journal_.info << "Voting for base fee of " << target_.reference_fee; baseValidation.setFieldU64 (sfBaseFee, target_.reference_fee); } if (lastClosedLedger->getReserve (0) != target_.account_reserve) { if (journal_.info) journal_.info << "Voting for base resrve of " << target_.account_reserve; baseValidation.setFieldU32(sfReserveBase, target_.account_reserve); } if (lastClosedLedger->getReserveInc () != target_.owner_reserve) { if (journal_.info) journal_.info << "Voting for reserve increment of " << target_.owner_reserve; baseValidation.setFieldU32 (sfReserveIncrement, target_.owner_reserve); } }
void LedgerHistory::validatedLedger (Ledger::ref ledger) { LedgerIndex index = ledger->getLedgerSeq(); LedgerHash hash = ledger->getHash(); assert (!hash.isZero()); ConsensusValidated::ScopedLockType sl ( m_consensus_validated.peekMutex()); std::shared_ptr< std::pair< LedgerHash, LedgerHash > > entry = std::make_shared<std::pair< LedgerHash, LedgerHash >>(); m_consensus_validated.canonicalize(index, entry, false); if (entry->second != hash) { bool mismatch (false); if (entry->second.isNonZero() && (entry->second != hash)) { WriteLog (lsERROR, LedgerMaster) << "MISMATCH: seq=" << index << " validated:" << entry->second << " then:" << hash; mismatch = true; } if (entry->first.isNonZero() && (entry->first != hash)) { WriteLog (lsERROR, LedgerMaster) << "MISMATCH: seq=" << index << " built:" << entry->first << " validated:" << hash; mismatch = true; } if (mismatch) handleMismatch (entry->second, hash); entry->second = hash; } }
void AmendmentTableImpl::doVoting (Ledger::ref lastClosedLedger, SHAMap::ref initialPosition) { // LCL must be flag ledger assert((lastClosedLedger->getLedgerSeq () % 256) == 0); AmendmentSet amendmentSet (lastClosedLedger->getParentCloseTimeNC ()); // get validations for ledger before flag ledger ValidationSet valSet = getApp().getValidations ().getValidations (lastClosedLedger->getParentHash ()); for (auto const& entry : valSet) { auto const& val = *entry.second; if (val.isTrusted ()) { amendmentSet.addVoter (); if (val.isFieldPresent (sfAmendments)) { for (auto const& amendment : val.getFieldV256 (sfAmendments)) { amendmentSet.addVote (amendment); } } } } reportValidations (amendmentSet); amendmentList_t lAmendments = getToEnable (lastClosedLedger->getCloseTimeNC ()); for (auto const& uAmendment : lAmendments) { if (m_journal.warning) m_journal.warning << "Voting for amendment: " << uAmendment; // Create the transaction to enable the amendment STTx trans (ttAMENDMENT); trans.setFieldAccount (sfAccount, Account ()); trans.setFieldH256 (sfAmendment, uAmendment); uint256 txID = trans.getTransactionID (); if (m_journal.warning) m_journal.warning << "Vote ID: " << txID; // Inject the transaction into our initial proposal Serializer s; trans.add (s, true); #if RIPPLE_PROPOSE_AMENDMENTS SHAMapItem::pointer tItem = std::make_shared<SHAMapItem> (txID, s.peekData ()); if (!initialPosition->addGiveItem (tItem, true, false)) { if (m_journal.warning) m_journal.warning << "Ledger already had amendment transaction"; } #endif } }
AcceptedLedger::AcceptedLedger (Ledger::ref ledger) : mLedger (ledger) { SHAMap& txSet = *ledger->peekTransactionMap (); for (SHAMapItem::pointer item = txSet.peekFirstItem (); !!item; item = txSet.peekNextItem (item->getTag ())) { SerializerIterator sit (item->peekSerializer ()); insert (boost::make_shared<AcceptedLedgerTx> (ledger->getLedgerSeq (), boost::ref (sit))); } }
AcceptedLedger::pointer AcceptedLedger::makeAcceptedLedger (Ledger::ref ledger) { AcceptedLedger::pointer ret = s_cache.fetch (ledger->getHash ()); if (ret) return ret; ret = AcceptedLedger::pointer (new AcceptedLedger (ledger)); s_cache.canonicalize (ledger->getHash (), ret); return ret; }
void AccountItems::fillItems (const uint160& accountID, Ledger::ref ledger) { uint256 const rootIndex = Ledger::getOwnerDirIndex (accountID); uint256 currentIndex = rootIndex; // VFALCO TODO Rewrite all infinite loops to have clear terminating // conditions defined in one location. // while (1) { SLE::pointer ownerDir = ledger->getDirNode (currentIndex); // VFALCO TODO Rewrite to not return from the middle of the function if (!ownerDir) return; BOOST_FOREACH (uint256 const & uNode, ownerDir->getFieldV256 (sfIndexes).peekValue ()) { // VFALCO TODO rename getSLEi() to something legible. SLE::pointer sleCur = ledger->getSLEi (uNode); if (!sleCur) { // item in directory not in ledger } else { AccountItem::pointer item = mOfType->makeItem (accountID, sleCur); // VFALCO NOTE Under what conditions would makeItem() return nullptr? // DJS NOTE If the item wasn't one this particular AccountItems was interested in // (For example, if the owner is only interested in ripple lines and this is an offer) if (item) { mItems.push_back (item); } } } std::uint64_t uNodeNext = ownerDir->getFieldU64 (sfIndexNext); // VFALCO TODO Rewrite to not return from the middle of the function if (!uNodeNext) return; currentIndex = Ledger::getDirNodeIndex (rootIndex, uNodeNext); } }
void OrderBookDB::setup (Ledger::ref ledger) { { ScopedLockType sl (mLock); auto seq = ledger->getLedgerSeq (); // Do a full update every 256 ledgers if (mSeq != 0) { if (seq == mSeq) return; if ((seq > mSeq) && ((seq - mSeq) < 256)) return; if ((seq < mSeq) && ((mSeq - seq) < 16)) return; } WriteLog (lsDEBUG, OrderBookDB) << "Advancing from " << mSeq << " to " << seq; mSeq = seq; } if (getConfig().RUN_STANDALONE) update(ledger); else getApp().getJobQueue().addJob(jtUPDATE_PF, "OrderBookDB::update", std::bind(&OrderBookDB::update, this, ledger)); }
void LedgerMaster::switchLedgers(Ledger::ref lastClosed, Ledger::ref current) { assert(lastClosed && current); { boost::recursive_mutex::scoped_lock ml(mLock); mFinalizedLedger = lastClosed; mFinalizedLedger->setClosed(); mFinalizedLedger->setAccepted(); mCurrentLedger = current; } assert(!mCurrentLedger->isClosed()); mEngine.setLedger(mCurrentLedger); checkAccept(lastClosed->getHash(), lastClosed->getLedgerSeq()); }
void doapplyvalidation(ledger::ref lastclosedledger, stobject& basevalidation) override { dividendmaster::pointer dividendmaster = getapp().getops().getdividendmaster(); if (dividendmaster->trylock()) { if (dividendmaster->isready()) { uint32_t dividendledger = lastclosedledger->getdividendbaseledger(); if (dividendledger == dividendmaster->getledgerseq()) { basevalidation.setfieldu32 (sfdividendledger, dividendledger); basevalidation.setfieldh256 (sfdividendresulthash, dividendmaster->getresulthash()); if (m_journal.info) m_journal.info << "voting for a dividend apply based " << dividendledger << " with hash "<< dividendmaster->getresulthash() << " in " << lastclosedledger->gethash(); } else { if (m_journal.warning) m_journal.warning << "wrong base ledger " << dividendmaster->getledgerseq() << " want "<< dividendledger; } } dividendmaster->unlock(); } }
void OrderBookDB::setup (Ledger::ref ledger) { { ScopedLockType sl (mLock, __FILE__, __LINE__); // Do a full update every 256 ledgers if (mSeq != 0) { if (ledger->getLedgerSeq () == mSeq) return; if ((ledger->getLedgerSeq () > mSeq) && ((ledger->getLedgerSeq () - mSeq) < 256)) return; if ((ledger->getLedgerSeq () < mSeq) && ((mSeq - ledger->getLedgerSeq ()) < 16)) return; } WriteLog (lsDEBUG, OrderBookDB) << "Advancing from " << mSeq << " to " << ledger->getLedgerSeq(); mSeq = ledger->getLedgerSeq (); } if (getConfig().RUN_STANDALONE) update(ledger); else getApp().getJobQueue().addJob(jtUPDATE_PF, "OrderBookDB::update", BIND_TYPE(&OrderBookDB::update, this, ledger)); }
void AccountItems::fillItems (Account const& accountID, Ledger::ref ledger) { uint256 const rootIndex = Ledger::getOwnerDirIndex (accountID); uint256 currentIndex = rootIndex; // VFALCO TODO Rewrite all infinite loops to have clear terminating // conditions defined in one location. // while (1) { SLE::pointer ownerDir = ledger->getDirNode (currentIndex); // VFALCO TODO Rewrite to not return from the middle of the function if (!ownerDir) return; for (auto const& uNode: ownerDir->getFieldV256 (sfIndexes).peekValue ()) { // VFALCO TODO rename getSLEi() to something legible. SLE::pointer sleCur = ledger->getSLEi (uNode); if (sleCur) { // The item in the directory is in ledger auto item = mOfType->makeItem (accountID, sleCur); // makeItem() returns nullptr if the item wasn't one this // particular AccountItems was interested in - for example, if // the owner is only interested in ripple lines and this is an // offer. if (item) mItems.push_back (item); } } std::uint64_t uNodeNext = ownerDir->getFieldU64 (sfIndexNext); if (!uNodeNext) return; currentIndex = Ledger::getDirNodeIndex (rootIndex, uNodeNext); } }
bool LedgerMaster::acquireMissingLedger(Ledger::ref origLedger, const uint256& ledgerHash, uint32 ledgerSeq) { // return: false = already gave up recently if (mTooFast) return true; Ledger::pointer ledger = mLedgerHistory.getLedgerBySeq(ledgerSeq); if (ledger && (Ledger::getHashByIndex(ledgerSeq) == ledgerHash)) { cLog(lsTRACE) << "Ledger hash found in database"; mTooFast = true; theApp->getJobQueue().addJob(jtPUBOLDLEDGER, boost::bind(&LedgerMaster::asyncAccept, this, ledger)); return true; } if (theApp->getMasterLedgerAcquire().isFailure(ledgerHash)) return false; mMissingLedger = theApp->getMasterLedgerAcquire().findCreate(ledgerHash); if (mMissingLedger->isComplete()) { Ledger::pointer lgr = mMissingLedger->getLedger(); if (lgr && (lgr->getLedgerSeq() == ledgerSeq)) missingAcquireComplete(mMissingLedger); mMissingLedger.reset(); return true; } else if (mMissingLedger->isDone()) { mMissingLedger.reset(); return false; } mMissingSeq = ledgerSeq; if (mMissingLedger->setAccept()) { if (!mMissingLedger->addOnComplete(boost::bind(&LedgerMaster::missingAcquireComplete, this, _1))) theApp->getIOService().post(boost::bind(&LedgerMaster::missingAcquireComplete, this, mMissingLedger)); } int fetch = theConfig.getSize(siLedgerFetch); if (theApp->getMasterLedgerAcquire().getFetchCount() < fetch) { int count = 0; typedef std::pair<uint32, uint256> u_pair; std::vector<u_pair> vec = origLedger->getLedgerHashes(); BOOST_REVERSE_FOREACH(const u_pair& it, vec) { if ((count < fetch) && (it.first < ledgerSeq) && !mCompleteLedgers.hasValue(it.first) && !theApp->getMasterLedgerAcquire().find(it.second)) { ++count; theApp->getMasterLedgerAcquire().findCreate(it.second); } } }
void LedgerMaster::pushLedger(Ledger::ref newLCL, Ledger::ref newOL, bool fromConsensus) { assert(newLCL->isClosed() && newLCL->isAccepted()); assert(!newOL->isClosed() && !newOL->isAccepted()); if (newLCL->isAccepted()) { assert(newLCL->isClosed()); assert(newLCL->isImmutable()); mLedgerHistory.addAcceptedLedger(newLCL, fromConsensus); cLog(lsINFO) << "StashAccepted: " << newLCL->getHash(); } { boost::recursive_mutex::scoped_lock ml(mLock); mFinalizedLedger = newLCL; mCurrentLedger = newOL; mEngine.setLedger(newOL); } checkAccept(newLCL->getHash(), newLCL->getLedgerSeq()); }
bool isstartledger(ledger::ref ledger) override { return ((ledger->getledgerseq() > 2) && (ledger->gettotalcoins() < vrp_increase_max || ledger->gettotalcoinsvbc() < vbc_increase_max) && (ledger->getclosetime().time_of_day().hours() == 1) && ((ledger->getclosetimenc() - ledger->getdividendtimenc()) > 3600) ); }
void LedgerHistory::validatedLedger (Ledger::ref ledger) { LedgerIndex index = ledger->getLedgerSeq(); LedgerHash hash = ledger->getHash(); assert (!hash.isZero()); TaggedCache::ScopedLockType sl(mConsensusValidated.peekMutex(), __FILE__, __LINE__); boost::shared_ptr< std::pair< LedgerHash, LedgerHash > > entry = boost::make_shared<std::pair< LedgerHash, LedgerHash >>(); mConsensusValidated.canonicalize(index, entry, false); if (entry->second != hash) { if (entry->second.isNonZero() && (entry->second != hash)) { WriteLog (lsERROR, LedgerMaster) << "MISMATCH: seq=" << index << " validated:" << entry->second << " then:" << hash; } if (entry->first.isNonZero() && (entry->first != hash)) { WriteLog (lsERROR, LedgerMaster) << "MISMATCH: seq=" << index << " built:" << entry->first << " validated:" << hash; } entry->second = hash; } }
AcceptedLedgerTx::AcceptedLedgerTx (Ledger::ref ledger, SerialIter& sit) : mLedger (ledger) { // VFALCO This is making a needless copy auto const vl = sit.getVL(); SerialIter txnIt (make_Slice(vl)); mTxn = std::make_shared<STTx> (std::ref (txnIt)); mRawMeta = sit.getVL (); mMeta = std::make_shared<TransactionMetaSet> (mTxn->getTransactionID (), ledger->getLedgerSeq (), mRawMeta); mAffected = mMeta->getAffectedAccounts (); mResult = mMeta->getResultTER (); buildJson (); }
void LedgerMaster::pushLedger(Ledger::ref newLedger) { // Caller should already have properly assembled this ledger into "ready-to-close" form -- // all candidate transactions must already be applied cLog(lsINFO) << "PushLedger: " << newLedger->getHash(); boost::recursive_mutex::scoped_lock ml(mLock); if (!!mFinalizedLedger) { mFinalizedLedger->setClosed(); cLog(lsTRACE) << "Finalizes: " << mFinalizedLedger->getHash(); } mFinalizedLedger = mCurrentLedger; mCurrentLedger = newLedger; mEngine.setLedger(newLedger); }
void FeeVoteImpl::doVoting (Ledger::ref lastClosedLedger, std::shared_ptr<SHAMap> const& initialPosition) { // LCL must be flag ledger assert ((lastClosedLedger->getLedgerSeq () % 256) == 0); detail::VotableInteger<std::uint64_t> baseFeeVote ( lastClosedLedger->getBaseFee (), target_.reference_fee); detail::VotableInteger<std::uint32_t> baseReserveVote ( lastClosedLedger->getReserve (0), target_.account_reserve); detail::VotableInteger<std::uint32_t> incReserveVote ( lastClosedLedger->getReserveInc (), target_.owner_reserve); // get validations for ledger before flag ValidationSet const set = getApp().getValidations ().getValidations ( lastClosedLedger->getParentHash ()); for (auto const& e : set) { STValidation const& val = *e.second; if (val.isTrusted ()) { if (val.isFieldPresent (sfBaseFee)) { baseFeeVote.addVote (val.getFieldU64 (sfBaseFee)); } else { baseFeeVote.noVote (); } if (val.isFieldPresent (sfReserveBase)) { baseReserveVote.addVote (val.getFieldU32 (sfReserveBase)); } else { baseReserveVote.noVote (); } if (val.isFieldPresent (sfReserveIncrement)) { incReserveVote.addVote (val.getFieldU32 (sfReserveIncrement)); } else { incReserveVote.noVote (); } } } // choose our positions std::uint64_t const baseFee = baseFeeVote.getVotes (); std::uint32_t const baseReserve = baseReserveVote.getVotes (); std::uint32_t const incReserve = incReserveVote.getVotes (); // add transactions to our position if ((baseFee != lastClosedLedger->getBaseFee ()) || (baseReserve != lastClosedLedger->getReserve (0)) || (incReserve != lastClosedLedger->getReserveInc ())) { if (journal_.warning) journal_.warning << "We are voting for a fee change: " << baseFee << "/" << baseReserve << "/" << incReserve; STTx trans (ttFEE); trans.setFieldAccount (sfAccount, AccountID ()); trans.setFieldU64 (sfBaseFee, baseFee); trans.setFieldU32 (sfReferenceFeeUnits, 10); trans.setFieldU32 (sfReserveBase, baseReserve); trans.setFieldU32 (sfReserveIncrement, incReserve); uint256 txID = trans.getTransactionID (); if (journal_.warning) journal_.warning << "Vote: " << txID; Serializer s; trans.add (s); auto tItem = std::make_shared<SHAMapItem> (txID, s.peekData ()); if (!initialPosition->addGiveItem (tItem, true, false)) { if (journal_.warning) journal_.warning << "Ledger already had fee change"; } } }
bool doapplyvoting(ledger::ref lastclosedledger, shamap::ref initialposition) override { uint32_t dividendledger = lastclosedledger->getdividendbaseledger(); int weight = 0; std::map<uint256, int> votes; // get validations for validation ledger validationset const set = getapp().getvalidations ().getvalidations (lastclosedledger->gethash ()); for (auto const& e : set) { stvalidation const& val = *e.second; if (val.istrusted ()) { if (val.isfieldpresent (sfdividendledger) && val.isfieldpresent (sfdividendresulthash)) { uint32_t ledgerseq = val.getfieldu32 (sfdividendledger); if (ledgerseq != dividendledger) continue; const uint256 & dividendhash = val.getfieldh256 (sfdividendresulthash); ++votes[dividendhash]; // if (ledgerseq != dividendledger || dividendhash != dividendresulthash) { if (m_journal.debug) m_journal.debug << "recv dividend apply vote based " << ledgerseq << " hash " << dividendhash << " from validator " << val.getnodeid() << " in " << lastclosedledger->gethash(); // continue; // } // ++weight; } } } uint256 dividendresulthash; for (auto const& v : votes) { if (v.second > weight) { dividendresulthash = v.first; weight = v.second; } } dividendmaster::pointer dividendmaster = getapp().getops().getdividendmaster(); if (!dividendmaster->trylock()) { if (weight >=getapp().getledgermaster().getminvalidations()) return false; else return true; } if (!dividendmaster->isready() || dividendledger != dividendmaster->getledgerseq() || dividendresulthash != dividendmaster->getresulthash()) { if (dividendmaster->isready()) m_journal.warning << "we got mismatch dividend apply based " << dividendledger << " hash " << dividendresulthash << " ours " << dividendmaster->getresulthash() << " based " << dividendmaster->getledgerseq() << " in " << lastclosedledger->gethash(); dividendmaster->unlock(); if (weight >=getapp().getledgermaster().getminvalidations()) return false; else return true; } if (weight >= getapp().getledgermaster().getminvalidations()) { m_journal.warning << "we are voting for a dividend apply based " << dividendledger << " hash " << dividendresulthash << " with " << weight << " same votes in " << lastclosedledger->gethash(); dividendmaster->filldivresult(initialposition); dividendmaster->filldivready(initialposition); dividendmaster->setready(false); } else { m_journal.warning << "we are cancelling a dividend apply with only " << weight << " same votes in " << lastclosedledger->gethash(); dividendmaster->settotaldividend(0); dividendmaster->settotaldividendvbc(0); dividendmaster->setsumvrank(0); dividendmaster->setsumvspd(0); dividendmaster->setresulthash(uint256()); dividendmaster->filldivready(initialposition); dividendmaster->setready(false); } dividendmaster->unlock(); return true; }
bool isapplyledger(ledger::ref ledger) override { return (ledger->isdividendstarted() && ((ledger->getclosetimenc() - ledger->getdividendtimenc()) >= 120) ); }
void dostartvalidation(ledger::ref lastclosedledger, stobject& basevalidation) override { // lcl must be validation ledger assert (isstartledger(lastclosedledger)); std::uint32_t dividendledger = lastclosedledger->getledgerseq(); std::uint64_t dividendcoins = vrp_increase_rate * lastclosedledger->gettotalcoinsvbc() / vrp_increase_rate_parts; if (dividendcoins + lastclosedledger->gettotalcoins() > vrp_increase_max) { dividendcoins = 0; } std::uint64_t dividendcoinsvbc = 0; if (lastclosedledger->gettotalcoinsvbc() < vbc_increase_max) { if (lastclosedledger->getclosetimenc() < vbc_dividend_period_1) { dividendcoinsvbc = vbc_increase_rate_1 * lastclosedledger->gettotalcoinsvbc() / vbc_increase_rate_1_parts; } else if (lastclosedledger->getclosetimenc() < vbc_dividend_period_2) { dividendcoinsvbc = vbc_increase_rate_2 * lastclosedledger->gettotalcoinsvbc() / vbc_increase_rate_2_parts; } else if (lastclosedledger->getclosetimenc() < vbc_dividend_period_3) { dividendcoinsvbc = vbc_increase_rate_3 * lastclosedledger->gettotalcoinsvbc() / vbc_increase_rate_3_parts; } else { dividendcoinsvbc = vbc_increase_rate_4 * lastclosedledger->gettotalcoinsvbc() / vbc_increase_rate_4_parts; } if (dividendcoinsvbc + lastclosedledger->gettotalcoinsvbc() > vbc_increase_max) dividendcoinsvbc = 0; } if (dividendcoins==0 && dividendcoinsvbc==0) { if (m_journal.warning) m_journal.warning << "not voting for a dividend start because both vrp and vbc will exceed max."; return; } basevalidation.setfieldu32 (sfdividendledger, dividendledger); basevalidation.setfieldu64 (sfdividendcoins, dividendcoins); basevalidation.setfieldu64 (sfdividendcoinsvbc, dividendcoinsvbc); if (m_journal.info) m_journal.info << "voting for a dividend start based " << dividendledger << " with vrp "<< dividendcoins << " vbc " << dividendcoinsvbc << " in " << lastclosedledger->gethash(); }
void dostartvoting(ledger::ref lastclosedledger, shamap::ref initialposition) override { // lcl must be validation ledger assert (isstartledger(lastclosedledger)); std::uint32_t dividendledger = lastclosedledger->getledgerseq(); std::map<std::pair<uint64_t, uint64_t>, int> votemap; // get validations for validation ledger validationset const set = getapp().getvalidations ().getvalidations (lastclosedledger->gethash ()); for (auto const& e : set) { stvalidation const& val = *e.second; if (val.istrusted ()) { if (val.isfieldpresent (sfdividendledger) && val.isfieldpresent (sfdividendcoins) && val.isfieldpresent (sfdividendcoinsvbc)) { uint32_t ledgerseq = val.getfieldu32 (sfdividendledger); if (ledgerseq != dividendledger) { m_journal.warning << "mismatch ledger seq " << ledgerseq << " from validator " << val.getnodeid() << " ours: " << dividendledger << " in " << lastclosedledger->gethash(); continue; } ++votemap[std::make_pair(val.getfieldu64 (sfdividendcoins), val.getfieldu64 (sfdividendcoinsvbc))]; } } } std::pair<uint64_t, uint64_t> ourvote = std::make_pair(0, 0); int weight = 0; for (auto const& e : votemap) { // take most voted value if (e.second > weight) { ourvote = e.first; weight = e.second; } } if (weight < getapp().getledgermaster().getminvalidations()) { m_journal.warning << weight << " votes are not enough to start dividend for " << dividendledger; return; } if (ourvote.first==0 && ourvote.second==0) { if (m_journal.warning) m_journal.warning << "not voting for a dividend start because both vrp and vbc voted are 0"; return; } if (ourvote.first + lastclosedledger->gettotalcoins() > vrp_increase_max && ourvote.second + lastclosedledger->gettotalcoinsvbc() > vbc_increase_max) { if (m_journal.error) m_journal.error << "not voting for a dividend start because both vrp and vbc will exceed max."; return; } if (m_journal.warning) m_journal.warning << "we are voting for a dividend start based " << dividendledger << " with vrp " << ourvote.first << " vbc " << ourvote.second << " with " << weight << " same votes in " << lastclosedledger->gethash(); sttx trans(ttdividend); trans.setfieldu8(sfdividendtype, dividendmaster::divtype_start); trans.setfieldaccount(sfaccount, account()); trans.setfieldu32(sfdividendledger, dividendledger); trans.setfieldu64(sfdividendcoins, ourvote.first); trans.setfieldu64(sfdividendcoinsvbc, ourvote.second); uint256 txid = trans.gettransactionid(); if (m_journal.warning) m_journal.warning << "vote: " << txid; serializer s; trans.add (s, true); shamapitem::pointer titem = std::make_shared<shamapitem> (txid, s.peekdata ()); if (!initialposition->addgiveitem (titem, true, false)) { if (m_journal.warning) m_journal.warning << "ledger already had dividend start"; } }
void LedgerMaster::storeLedger(Ledger::ref ledger) { mLedgerHistory.addLedger(ledger); if (ledger->isAccepted()) mLedgerHistory.addAcceptedLedger(ledger, false); }