Example #1
0
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
    }
}
    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";
        }
    }
bool shamap::compare (shamap::ref othermap, delta& differences, int maxcount)
{
    // compare two hash trees, add up to maxcount differences to the difference table
    // return value: true=complete table of differences given, false=too many differences
    // throws on corrupt tables or missing nodes
    // caution: othermap is not locked and must be immutable

    assert (isvalid () && othermap && othermap->isvalid ());

    using stackentry = std::pair <shamaptreenode*, shamaptreenode*>;
    std::stack <stackentry, std::vector<stackentry>> nodestack; // track nodes we've pushed

    if (gethash () == othermap->gethash ())
        return true;

    nodestack.push ({root.get(), othermap->root.get()});
    while (!nodestack.empty ())
    {
        shamaptreenode* ournode = nodestack.top().first;
        shamaptreenode* othernode = nodestack.top().second;
        nodestack.pop ();

        if (!ournode || !othernode)
        {
            assert (false);
            throw shamapmissingnode (mtype, uint256 ());
        }

        if (ournode->isleaf () && othernode->isleaf ())
        {
            // two leaves
            if (ournode->gettag () == othernode->gettag ())
            {
                if (ournode->peekdata () != othernode->peekdata ())
                {
                    differences.insert (std::make_pair (ournode->gettag (),
                                                 deltaref (ournode->peekitem (),
                                                 othernode->peekitem ())));
                    if (--maxcount <= 0)
                        return false;
                }
            }
            else
            {
                differences.insert (std::make_pair(ournode->gettag (),
                                                   deltaref(ournode->peekitem(),
                                                   shamapitem::pointer ())));
                if (--maxcount <= 0)
                    return false;

                differences.insert(std::make_pair(othernode->gettag (),
                                                  deltaref(shamapitem::pointer(),
                                                  othernode->peekitem ())));
                if (--maxcount <= 0)
                    return false;
            }
        }
        else if (ournode->isinner () && othernode->isleaf ())
        {
            if (!walkbranch (ournode, othernode->peekitem (),
                    true, differences, maxcount))
                return false;
        }
        else if (ournode->isleaf () && othernode->isinner ())
        {
            if (!othermap->walkbranch (othernode, ournode->peekitem (),
                                       false, differences, maxcount))
                return false;
        }
        else if (ournode->isinner () && othernode->isinner ())
        {
            for (int i = 0; i < 16; ++i)
                if (ournode->getchildhash (i) != othernode->getchildhash (i))
                {
                    if (othernode->isemptybranch (i))
                    {
                        // we have a branch, the other tree does not
                        shamaptreenode* inode = descendthrow (ournode, i);
                        if (!walkbranch (inode,
                                         shamapitem::pointer (), true,
                                         differences, maxcount))
                            return false;
                    }
                    else if (ournode->isemptybranch (i))
                    {
                        // the other tree has a branch, we do not
                        shamaptreenode* inode =
                            othermap->descendthrow(othernode, i);
                        if (!othermap->walkbranch (inode,
                                                   shamapitem::pointer(),
                                                   false, differences, maxcount))
                            return false;
                    }
                    else // the two trees have different non-empty branches
                        nodestack.push ({descendthrow (ournode, i),
                                        othermap->descendthrow (othernode, i)});
                }
        }
        else
            assert (false);
    }

    return true;
}
Example #4
0
void
FeeVoteImpl::doVoting (Ledger::ref lastClosedLedger,
    SHAMap::ref 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)
    {
        SerializedValidation 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;

        SerializedTransaction trans (ttFEE);
        trans.setFieldAccount (sfAccount, Account ());
        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, true);

        SHAMapItem::pointer tItem = std::make_shared<SHAMapItem> (
            txID, s.peekData ());

        if (!initialPosition->addGiveItem (tItem, true, false))
        {
            if (journal_.warning) journal_.warning <<
                "Ledger already had fee change";
        }
    }
}