From e566a4f5c253d20a1fe1622e1bcd823599076f88 Mon Sep 17 00:00:00 2001 From: CJentzsch Date: Wed, 22 Apr 2015 16:53:03 +0200 Subject: [PATCH] really nice scientific gasPricer --- libethereum/Client.cpp | 42 +++-- .../bcGasPricerTestFiller.json | 153 ++++++++++++++++-- test/libethereum/gaspricer.cpp | 48 ++++-- 3 files changed, 213 insertions(+), 30 deletions(-) diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 408f8ebca..d5918bde1 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -24,6 +24,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -83,6 +87,8 @@ void BasicGasPricer::update(BlockChain const& _bc) map dist; unsigned total = 0; + + // make gasPrice versus gasUsed distribution for the last 1000 blocks while (c < 1000 && p) { BlockInfo bi = _bc.info(p); @@ -91,28 +97,44 @@ void BasicGasPricer::update(BlockChain const& _bc) auto bb = _bc.block(p); RLP r(bb); BlockReceipts brs(_bc.receipts(bi.hash())); - for (unsigned i = 0; i < r[1].size(); ++i) + size_t i = 0; + for (auto const& tr: r[1]) { + Transaction tx(tr.data(), CheckTransaction::None); auto gu = brs.receipts[i].gasUsed(); - dist[Transaction(r[1][i].data(), CheckTransaction::None).gasPrice()] += (unsigned)brs.receipts[i].gasUsed(); + dist[tx.gasPrice()] += (unsigned)gu; total += (unsigned)gu; + i++; } } p = bi.parentHash; ++c; } + + // fill m_octiles with weighted gasPrices if (total > 0) { - unsigned t = 0; - unsigned q = 1; m_octiles[0] = dist.begin()->first; + + // calc mean + u256 mean = 0; for (auto const& i: dist) - { - for (; t <= total * q / 8 && t + i.second > total * q / 8; ++q) - m_octiles[q] = i.first; - if (q > 7) - break; - } + 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; + double sd = sqrt(sdSquared.convert_to()); + double normalizedSd = 4.0 * sd / mean.convert_to(); + + // calc octiles normalized to gaussian distribution + boost::math::normal gauss(4, normalizedSd ? normalizedSd : 1); + for (int i=1; i < 8; i++) + m_octiles[i] = mean / 4000 * int(boost::math::quantile(gauss, (double)i / 8) * 1000); + m_octiles[8] = dist.rbegin()->first; } } diff --git a/test/libethereum/BlockTestsFiller/bcGasPricerTestFiller.json b/test/libethereum/BlockTestsFiller/bcGasPricerTestFiller.json index 2b0efc844..3b2e878fd 100644 --- a/test/libethereum/BlockTestsFiller/bcGasPricerTestFiller.json +++ b/test/libethereum/BlockTestsFiller/bcGasPricerTestFiller.json @@ -5,7 +5,7 @@ "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", "difficulty" : "131072", "extraData" : "0x42", - "gasLimit" : "3141592", + "gasLimit" : "31415920", "gasUsed" : "0", "mixHash" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "nonce" : "0x0102030405060708", @@ -24,7 +24,7 @@ }, "pre" : { "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "10000000000", + "balance" : "9000000000000000000000000000", "nonce" : "0", "code" : "", "storage": {} @@ -40,9 +40,9 @@ { "transactions" : [ { - "data" : "0xffffffffffffffffffffffff", - "gasLimit" : "85000", - "gasPrice" : "0", + "data" : "0xffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "10000000000000", "nonce" : "0", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", @@ -55,10 +55,145 @@ { "transactions" : [ { - "data" : "0xffffffffffff", - "gasLimit" : "85000", - "gasPrice" : "0", - "nonce" : "0", + "data" : "0xfffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "12000000000000", + "nonce" : "1", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "14000000000000", + "nonce" : "2", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xfffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "16000000000000", + "nonce" : "3", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xfffffffffffffffffffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "18000000000000", + "nonce" : "4", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xffffffffffffffffffffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "20000000000000", + "nonce" : "5", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xffffffffffffffffffffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "22000000000000", + "nonce" : "6", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xffffffffffffffffffffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "24000000000000", + "nonce" : "7", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xffffffffffffffffffffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "26000000000000", + "nonce" : "8", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xffffffffffffffffffffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "28000000000000", + "nonce" : "9", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "10" + } + ], + "uncleHeaders" : [ + ] + }, + { + "transactions" : [ + { + "data" : "0xffffffffffffffffffffffffffffffff", + "gasLimit" : "850000", + "gasPrice" : "30000000000000", + "nonce" : "10", "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", "value" : "10" diff --git a/test/libethereum/gaspricer.cpp b/test/libethereum/gaspricer.cpp index d7f72292c..6fcb6b172 100644 --- a/test/libethereum/gaspricer.cpp +++ b/test/libethereum/gaspricer.cpp @@ -33,7 +33,7 @@ using namespace dev::eth; namespace dev { namespace test { -void executeGasPricerTest(const string name, double _etherPrice, double _blockFee, const string bcTestPath, u256 _expectedAsk, u256 _expectedBid) +void executeGasPricerTest(const string name, double _etherPrice, double _blockFee, const string bcTestPath, TransactionPriority _txPrio, u256 _expectedAsk, u256 _expectedBid) { cnote << name; BasicGasPricer gp(u256(double(ether / 1000) / _etherPrice), u256(_blockFee * 1000)); @@ -44,7 +44,7 @@ void executeGasPricerTest(const string name, double _etherPrice, double _blockFe gp.update(bc); BOOST_CHECK_EQUAL(gp.ask(State()), _expectedAsk); - BOOST_CHECK_EQUAL(gp.bid(), _expectedBid); + BOOST_CHECK_EQUAL(gp.bid(_txPrio), _expectedBid); } @@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE(trivialGasPricer) std::shared_ptr gp(new TrivialGasPricer); BOOST_CHECK_EQUAL(gp->ask(State()), 10 * szabo); BOOST_CHECK_EQUAL(gp->bid(), 10 * szabo); - gp->update(BlockChain(bytes(), string(), WithExisting::Kill)); + gp->update(BlockChain(bytes(), TransientDirectory().path(), WithExisting::Kill)); BOOST_CHECK_EQUAL(gp->ask(State()), 10 * szabo); BOOST_CHECK_EQUAL(gp->bid(), 10 * szabo); } @@ -93,27 +93,53 @@ BOOST_AUTO_TEST_CASE(basicGasPricerNoUpdate) BOOST_AUTO_TEST_CASE(basicGasPricer_RPC_API_Test) { - dev::test::executeGasPricerTest("RPC_API_Test", 30.679, 15.0, "/BlockTests/bcRPC_API_Test.json", 155632494086, 155632494086); + dev::test::executeGasPricerTest("RPC_API_Test", 30.679, 15.0, "/BlockTests/bcRPC_API_Test.json", TransactionPriority::Medium, 155632494086, 155632494086); } BOOST_AUTO_TEST_CASE(basicGasPricer_bcValidBlockTest) { - dev::test::executeGasPricerTest("SimpleTx", 30.679, 15.0, "/BlockTests/bcValidBlockTest.json", 155632494086, 155632494086); + dev::test::executeGasPricerTest("SimpleTx", 30.679, 15.0, "/BlockTests/bcValidBlockTest.json", TransactionPriority::Medium, 155632494086, 155632494086); } -BOOST_AUTO_TEST_CASE(basicGasPricer_bcInvalidHeaderTest) +BOOST_AUTO_TEST_CASE(basicGasPricer_bcUncleTest) { - dev::test::executeGasPricerTest("wrongUncleHash", 30.679, 15.0, "/BlockTests/bcInvalidHeaderTest.json", 155632494086, 155632494086); + dev::test::executeGasPricerTest("twoUncle", 30.679, 15.0, "/BlockTests/bcUncleTest.json", TransactionPriority::Medium, 155632494086, 155632494086); } -BOOST_AUTO_TEST_CASE(basicGasPricer_bcUncleTest) +BOOST_AUTO_TEST_CASE(basicGasPricer_bcUncleHeaderValiditiy) { - dev::test::executeGasPricerTest("twoUncle", 30.679, 15.0, "/BlockTests/bcUncleTest.json", 155632494086, 155632494086); + dev::test::executeGasPricerTest("correct", 30.679, 15.0, "/BlockTests/bcUncleHeaderValiditiy.json", TransactionPriority::Medium, 155632494086, 155632494086); } -BOOST_AUTO_TEST_CASE(basicGasPricer_bcUncleHeaderValiditiy) +BOOST_AUTO_TEST_CASE(basicGasPricer_notxs) +{ + dev::test::executeGasPricerTest("notxs", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Medium, 155632494086, 155632494086); +} + +BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_LowestPrio) +{ + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Lowest, 15731290119, 10000000000000); +} + +BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_LowPrio) { - dev::test::executeGasPricerTest("correct", 30.679, 15.0, "/BlockTests/bcUncleHeaderValiditiy.json", 155632494086, 155632494086); + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Low, 15731290119, 15812460025839); } +BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_MediumPrio) +{ + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Medium, 15731290119, 20072941956000); +} + +BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_HighPrio) +{ + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::High, 15731290119, 24328405650672); +} + +BOOST_AUTO_TEST_CASE(basicGasPricer_highGasUsage_HighestPrio) +{ + dev::test::executeGasPricerTest("highGasUsage", 30.679, 15.0, "/BlockTests/bcGasPricerTest.json", TransactionPriority::Highest, 15731290119, 30000000000000); +} + + BOOST_AUTO_TEST_SUITE_END()