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 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;
    }
 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 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();
     }
 }