123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- /*
- This file is part of cpp-ethereum.
- cpp-ethereum is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- cpp-ethereum is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
- */
- /** @file BasicGasPricer.cpp
- * @author Gav Wood <i@gavwood.com>
- * @date 2015
- */
- #pragma warning(push)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #include <boost/math/distributions/normal.hpp>
- #pragma warning(pop)
- #pragma GCC diagnostic pop
- #include "BasicGasPricer.h"
- #include "BlockChain.h"
- using namespace std;
- using namespace dev;
- using namespace dev::eth;
- void BasicGasPricer::update(BlockChain const& _bc)
- {
- unsigned c = 0;
- h256 p = _bc.currentHash();
- m_gasPerBlock = _bc.info(p).gasLimit();
- map<u256, u256> dist;
- u256 total = 0;
- // make gasPrice versus gasUsed distribution for the last 1000 blocks
- while (c < 1000 && p)
- {
- BlockHeader bi = _bc.info(p);
- if (bi.transactionsRoot() != EmptyTrie)
- {
- auto bb = _bc.block(p);
- RLP r(bb);
- BlockReceipts brs(_bc.receipts(bi.hash()));
- size_t i = 0;
- for (auto const& tr: r[1])
- {
- Transaction tx(tr.data(), CheckTransaction::None);
- u256 gu = brs.receipts[i].gasUsed();
- dist[tx.gasPrice()] += gu;
- total += gu;
- i++;
- }
- }
- p = bi.parentHash();
- ++c;
- }
- // fill m_octiles with weighted gasPrices
- if (total > 0)
- {
- m_octiles[0] = dist.begin()->first;
- // calc mean
- u256 mean = 0;
- for (auto const& i: dist)
- mean += i.first * i.second;
- mean /= total;
- // calc standard deviation
- u256 sdSquared = 0;
- for (auto const& i: dist)
- sdSquared += i.second * (i.first - mean) * (i.first - mean);
- sdSquared /= total;
- if (sdSquared)
- {
- long double sd = sqrt(sdSquared.convert_to<long double>());
- long double normalizedSd = sd / mean.convert_to<long double>();
- // calc octiles normalized to gaussian distribution
- boost::math::normal gauss(1.0, (normalizedSd > 0.01) ? normalizedSd : 0.01);
- for (size_t i = 1; i < 8; i++)
- m_octiles[i] = u256(mean.convert_to<long double>() * boost::math::quantile(gauss, i / 8.0));
- m_octiles[8] = dist.rbegin()->first;
- }
- else
- {
- for (size_t i = 0; i < 9; i++)
- m_octiles[i] = (i + 1) * mean / 5;
- }
- }
- }
|