Browse Source

Merge branch 'develop' of github.com:ethereum/cpp-ethereum into develop

Avoid redownloading blocks from all peers when only one needed.

Conflicts:
	libethcore/Ethash.cpp
	libethcore/EthashAux.cpp
	libethcore/EthashAux.h
cl-refactor
Gav Wood 10 years ago
parent
commit
93752ed1cf
  1. 6
      alethzero/MainWin.cpp
  2. 4
      eth/main.cpp
  3. 8
      ethminer/main.cpp
  4. 18
      libethcore/Ethash.cpp
  5. 6
      libethcore/Ethash.h
  6. 55
      libethcore/EthashAux.cpp
  7. 16
      libethcore/EthashAux.h
  8. 1
      libethereum/EthereumHost.cpp
  9. 11
      libethereum/EthereumPeer.cpp
  10. 4
      libethereum/EthereumPeer.h
  11. 8
      test/libethcore/dagger.cpp

6
alethzero/MainWin.cpp

@ -945,7 +945,11 @@ void Main::on_preview_triggered()
void Main::on_prepNextDAG_triggered()
{
EthashAux::computeFull(ethereum()->blockChain().number() + ETHASH_EPOCH_LENGTH);
EthashAux::computeFull(
EthashAux::seedHash(
ethereum()->blockChain().number() + ETHASH_EPOCH_LENGTH
)
);
}
void Main::refreshMining()

4
eth/main.cpp

@ -857,7 +857,7 @@ int main(int argc, char** argv)
auto boundary = bi.boundary();
m = boost::to_lower_copy(string(argv[++i]));
bi.nonce = h64(m);
auto r = EthashAux::eval((uint64_t)bi.number, powHash, bi.nonce);
auto r = EthashAux::eval(bi.seedHash(), powHash, bi.nonce);
bool valid = r.value < boundary;
cout << (valid ? "VALID :-)" : "INVALID :-(") << endl;
cout << r.value << (valid ? " < " : " >= ") << boundary << endl;
@ -866,7 +866,7 @@ int main(int argc, char** argv)
cout << " with seed as " << seedHash << endl;
if (valid)
cout << "(mixHash = " << r.mixHash << ")" << endl;
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light((uint64_t)bi.number)->data()) << endl;
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi.seedHash())->data()) << endl;
exit(0);
}
catch (...)

8
ethminer/main.cpp

@ -269,8 +269,8 @@ void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod)
cnote << " Header-hash:" << current.headerHash.hex();
cnote << " Seedhash:" << current.seedHash.hex();
cnote << " Target: " << h256(current.boundary).hex();
cnote << " Ethash: " << h256(EthashAux::eval(EthashAux::number(current.seedHash), current.headerHash, solution.nonce).value).hex();
if (EthashAux::eval(EthashAux::number(current.seedHash), current.headerHash, solution.nonce).value < current.boundary)
cnote << " Ethash: " << h256(EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value).hex();
if (EthashAux::eval(current.seedHash, current.headerHash, solution.nonce).value < current.boundary)
{
bool ok = rpc.eth_submitWork("0x" + toString(solution.nonce), "0x" + toString(current.headerHash), "0x" + toString(solution.mixHash));
if (ok)
@ -432,7 +432,7 @@ int main(int argc, char** argv)
auto boundary = bi.boundary();
m = boost::to_lower_copy(string(argv[++i]));
bi.nonce = h64(m);
auto r = EthashAux::eval((uint64_t)bi.number, powHash, bi.nonce);
auto r = EthashAux::eval(bi.seedHash(), powHash, bi.nonce);
bool valid = r.value < boundary;
cout << (valid ? "VALID :-)" : "INVALID :-(") << endl;
cout << r.value << (valid ? " < " : " >= ") << boundary << endl;
@ -441,7 +441,7 @@ int main(int argc, char** argv)
cout << " with seed as " << seedHash << endl;
if (valid)
cout << "(mixHash = " << r.mixHash << ")" << endl;
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light((uint64_t)bi.number)->data()) << endl;
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi.seedHash())->data()) << endl;
exit(0);
}
catch (...)

18
libethcore/Ethash.cpp

@ -77,7 +77,7 @@ Ethash::WorkPackage Ethash::package(BlockInfo const& _bi)
void Ethash::prep(BlockInfo const& _header, std::function<int(unsigned)> const& _f)
{
EthashAux::full((unsigned)_header.number, _f);
EthashAux::full(_header.seedHash(), true, _f);
}
bool Ethash::preVerify(BlockInfo const& _header)
@ -134,7 +134,7 @@ void Ethash::CPUMiner::workLoop()
WorkPackage w = work();
auto dag = EthashAux::full(EthashAux::number(w.seedHash));
auto dag = EthashAux::full(w.seedHash);
h256 boundary = w.boundary;
unsigned hashCount = 1;
for (; !shouldStop(); tryNonce++, hashCount++)
@ -283,7 +283,7 @@ Ethash::GPUMiner::~GPUMiner()
bool Ethash::GPUMiner::report(uint64_t _nonce)
{
Nonce n = (Nonce)(u64)_nonce;
Result r = EthashAux::eval(EthashAux::number(work().seedHash), work().headerHash, n);
Result r = EthashAux::eval(work().seedHash, work().headerHash, n);
if (r.value < work().boundary)
return submitProof(Solution{n, r.mixHash});
return false;
@ -310,14 +310,16 @@ void Ethash::GPUMiner::workLoop()
unsigned device = instances() > 1 ? index() : s_deviceId;
while (EthashAux::computeFull(EthashAux::number(w.seedHash)) != 100 && !shouldStop())
EthashAux::FullType dag;
while (true)
{
cnote << "Awaiting DAG" << EthashAux::computeFull(EthashAux::number(w.seedHash));
if ((dag = EthashAux::full(w.seedHash, false)))
break;
if (shouldStop())
return;
cnote << "Awaiting DAG";
this_thread::sleep_for(chrono::milliseconds(500));
}
if (shouldStop())
return;
EthashAux::FullType dag = EthashAux::full(EthashAux::number(w.seedHash)); // todo , , false
bytesConstRef dagData = dag->data();
m_miner->init(dagData.data(), dagData.size(), 32, s_platformId, device);
}

6
libethcore/Ethash.h

@ -66,7 +66,7 @@ public:
h256 boundary;
h256 headerHash; ///< When h256() means "pause until notified a new work package is available".
h256 seedHash; /// LTODO: IS this needed now that we use the block number instead?
h256 seedHash;
};
static const WorkPackage NullWorkPackage;
@ -78,7 +78,7 @@ public:
static bool preVerify(BlockInfo const& _header);
static WorkPackage package(BlockInfo const& _header);
static void assignResult(Solution const& _r, BlockInfo& _header) { _header.nonce = _r.nonce; _header.mixHash = _r.mixHash; }
class CPUMiner: public Miner, Worker
{
@ -119,7 +119,7 @@ public:
static void setDefaultPlatform(unsigned _id) { s_platformId = _id; }
static void setDefaultDevice(unsigned _id) { s_deviceId = _id; }
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, getNumDevices()); }
protected:
void kickOff() override;
void pause() override;

55
libethcore/EthashAux.cpp

@ -105,23 +105,18 @@ void EthashAux::killCache(h256 const& _s)
m_lights.erase(_s);
}
EthashAux::LightType EthashAux::light(BlockInfo const& _header)
{
return light((uint64_t)_header.number);
}
EthashAux::LightType EthashAux::light(uint64_t _blockNumber)
EthashAux::LightType EthashAux::light(h256 const& _seedHash)
{
RecursiveGuard l(get()->x_lights);
h256 seedHash = EthashAux::seedHash(_blockNumber);
LightType ret = get()->m_lights[seedHash];
return ret ? ret : (get()->m_lights[seedHash] = make_shared<LightAllocation>(_blockNumber));
LightType ret = get()->m_lights[_seedHash];
return ret ? ret : (get()->m_lights[_seedHash] = make_shared<LightAllocation>(_seedHash));
}
EthashAux::LightAllocation::LightAllocation(uint64_t _blockNumber)
EthashAux::LightAllocation::LightAllocation(h256 const& _seedHash)
{
light = ethash_light_new(_blockNumber);
size = ethash_get_cachesize(_blockNumber);
uint64_t blockNumber = EthashAux::number(_seedHash);
light = ethash_light_new(blockNumber);
size = ethash_get_cachesize(blockNumber);
}
EthashAux::LightAllocation::~LightAllocation()
@ -156,22 +151,19 @@ static int dagCallbackShim(unsigned _p)
return s_dagCallback ? s_dagCallback(_p) : 0;
}
EthashAux::FullType EthashAux::full(uint64_t _blockNumber, function<int(unsigned)> const& _f, bool _createIfMissing)
EthashAux::FullType EthashAux::full(h256 const& _seedHash, bool _createIfMissing, function<int(unsigned)> const& _f)
{
(void)_createIfMissing;
// TODO: implement
auto l = light(_blockNumber);
h256 seedHash = EthashAux::seedHash(_blockNumber);
FullType ret;
auto l = light(_seedHash);
DEV_GUARDED(get()->x_fulls)
if ((ret = get()->m_fulls[seedHash].lock()))
if ((ret = get()->m_fulls[_seedHash].lock()))
{
get()->m_lastUsedFull = ret;
return ret;
}
if (_createIfMissing || computeFull(_blockNumber) == 100)
if (_createIfMissing || computeFull(_seedHash) == 100)
{
s_dagCallback = _f;
cnote << "Loading from libethash...";
@ -179,17 +171,17 @@ EthashAux::FullType EthashAux::full(uint64_t _blockNumber, function<int(unsigned
cnote << "Done loading.";
DEV_GUARDED(get()->x_fulls)
get()->m_fulls[seedHash] = get()->m_lastUsedFull = ret;
get()->m_fulls[_seedHash] = get()->m_lastUsedFull = ret;
}
return ret;
}
unsigned EthashAux::computeFull(uint64_t _blockNumber)
unsigned EthashAux::computeFull(h256 const& _seedHash)
{
Guard l(get()->x_fulls);
h256 seedHash = EthashAux::seedHash(_blockNumber);
if (FullType ret = get()->m_fulls[seedHash].lock())
uint64_t blockNumber = EthashAux::number(_seedHash);
if (FullType ret = get()->m_fulls[_seedHash].lock())
{
get()->m_lastUsedFull = ret;
return 100;
@ -198,17 +190,17 @@ unsigned EthashAux::computeFull(uint64_t _blockNumber)
if (!get()->m_fullGenerator || !get()->m_fullGenerator->joinable())
{
get()->m_fullProgress = 0;
get()->m_generatingFullNumber = _blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH;
get()->m_generatingFullNumber = blockNumber / ETHASH_EPOCH_LENGTH * ETHASH_EPOCH_LENGTH;
get()->m_fullGenerator = unique_ptr<thread>(new thread([=](){
cnote << "Loading full DAG of" << _blockNumber;
get()->full(_blockNumber, [](unsigned p){ get()->m_fullProgress = p; return 0; }, true);
cnote << "Loading full DAG of seedhash: " << _seedHash;
get()->full(_seedHash, true, [](unsigned p){ get()->m_fullProgress = p; return 0; });
cnote << "Full DAG loaded";
get()->m_fullProgress = 0;
get()->m_generatingFullNumber = NotGenerating;
}));
}
return (get()->m_generatingFullNumber == _blockNumber) ? get()->m_fullProgress : 0;
return (get()->m_generatingFullNumber == blockNumber) ? get()->m_fullProgress : 0;
}
Ethash::Result EthashAux::FullAllocation::compute(h256 const& _headerHash, Nonce const& _nonce) const
@ -229,13 +221,12 @@ Ethash::Result EthashAux::LightAllocation::compute(h256 const& _headerHash, Nonc
Ethash::Result EthashAux::eval(BlockInfo const& _header, Nonce const& _nonce)
{
return eval((uint64_t)_header.number, _header.headerHash(WithoutNonce), _nonce);
return eval(_header.seedHash(), _header.headerHash(WithoutNonce), _nonce);
}
Ethash::Result EthashAux::eval(uint64_t _blockNumber, h256 const& _headerHash, Nonce const& _nonce)
Ethash::Result EthashAux::eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce)
{
h256 seedHash = EthashAux::seedHash(_blockNumber);
if (FullType dag = get()->m_fulls[seedHash].lock())
if (FullType dag = get()->m_fulls[_seedHash].lock())
return dag->compute(_headerHash, _nonce);
return EthashAux::get()->light(_blockNumber)->compute(_headerHash, _nonce);
return EthashAux::get()->light(_seedHash)->compute(_headerHash, _nonce);
}

16
libethcore/EthashAux.h

@ -40,7 +40,7 @@ public:
struct LightAllocation
{
LightAllocation(uint64_t _blockNumber);
LightAllocation(h256 const& _seedHash);
~LightAllocation();
bytesConstRef data() const;
Ethash::Result compute(h256 const& _headerHash, Nonce const& _nonce) const;
@ -65,21 +65,19 @@ public:
static uint64_t number(h256 const& _seedHash);
static uint64_t cacheSize(BlockInfo const& _header);
static LightType light(BlockInfo const& _header);
static LightType light(uint64_t _blockNumber);
static LightType light(h256 const& _seedHash);
static const uint64_t NotGenerating = (uint64_t)-1;
/// Kicks off generation of DAG for @a _blocknumber and @returns false or @returns true if ready.
static unsigned computeFull(uint64_t _blockNumber);
/// Kicks off generation of DAG for @a _seedHash and @returns false or @returns true if ready.
static unsigned computeFull(h256 const& _seedHash);
/// Information on the generation progress.
static std::pair<uint64_t, unsigned> fullGeneratingProgress() { return std::make_pair(get()->m_generatingFullNumber, get()->m_fullProgress); }
/// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result or empty pointer if not existing.
static FullType full(uint64_t _blockNumber, std::function<int(unsigned)> const& _f = std::function<int(unsigned)>(), bool _createIfMissing = false);
/// Kicks off generation of DAG for @a _blocknumber and blocks until ready; @returns result or empty pointer if not existing and _createIfMissing is false.
static FullType full(h256 const& _seedHash, bool _createIfMissing = false, std::function<int(unsigned)> const& _f = std::function<int(unsigned)>());
static Ethash::Result eval(BlockInfo const& _header) { return eval(_header, _header.nonce); }
static Ethash::Result eval(BlockInfo const& _header, Nonce const& _nonce);
static Ethash::Result eval(uint64_t _blockNumber, h256 const& _headerHash, Nonce const& _nonce);
static Ethash::Result eval(h256 const& _seedHash, h256 const& _headerHash, Nonce const& _nonce);
private:
EthashAux() {}

1
libethereum/EthereumHost.cpp

@ -96,6 +96,7 @@ void EthereumHost::changeSyncer(EthereumPeer* _syncer, bool _needHelp)
if (_needHelp && _syncer->m_asking == Asking::Blocks)
for (auto j: peerSessions())
{
clog(NetNote) << "Getting help with downloading blocks";
auto e = j.first->cap<EthereumPeer>().get();
if (e != _syncer && e->m_asking == Asking::Nothing)
e->transition(Asking::Blocks);

11
libethereum/EthereumPeer.cpp

@ -74,7 +74,7 @@ string toString(Asking _a)
return "?";
}
void EthereumPeer::transition(Asking _a, bool _force)
void EthereumPeer::transition(Asking _a, bool _force, bool _needHelp)
{
clog(NetMessageSummary) << "Transition!" << ::toString(_a) << "from" << ::toString(m_asking) << ", " << (isSyncing() ? "syncing" : "holding") << (needsSyncing() ? "& needed" : "");
@ -151,7 +151,7 @@ void EthereumPeer::transition(Asking _a, bool _force)
if (m_asking == Asking::Nothing || m_asking == Asking::Hashes || m_asking == Asking::Blocks)
{
// Looks like it's the best yet for total difficulty. Set to download.
setAsking(Asking::Blocks, isSyncing()); // will kick off other peers to help if available.
setAsking(Asking::Blocks, isSyncing(), _needHelp); // will kick off other peers to help if available.
auto blocks = m_sub.nextFetch(c_maxBlocksAsk);
if (blocks.size())
{
@ -200,13 +200,13 @@ void EthereumPeer::transition(Asking _a, bool _force)
clog(NetWarn) << "Invalid state transition:" << ::toString(_a) << "from" << ::toString(m_asking) << ", " << (isSyncing() ? "syncing" : "holding") << (needsSyncing() ? "& needed" : "");
}
void EthereumPeer::setAsking(Asking _a, bool _isSyncing)
void EthereumPeer::setAsking(Asking _a, bool _isSyncing, bool _needHelp)
{
bool changedAsking = (m_asking != _a);
m_asking = _a;
if (_isSyncing != (host()->m_syncer == this) || (_isSyncing && changedAsking))
host()->changeSyncer(_isSyncing ? this : nullptr);
host()->changeSyncer(_isSyncing ? this : nullptr, _needHelp);
if (!_isSyncing)
{
@ -599,9 +599,10 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
clog(NetMessageSummary) << knowns << "knowns," << unknowns << "unknowns";
if (unknowns > 0)
{
clog(NetNote) << "Not syncing and new block hash discovered: syncing without help.";
host()->m_man.resetToChain(m_syncingNeededBlocks);
host()->changeSyncer(this, false);
transition(Asking::Blocks);
transition(Asking::Blocks, false, false); // TODO: transaction(Asking::NewBlocks, false)
}
return true;
}

4
libethereum/EthereumPeer.h

@ -77,7 +77,7 @@ private:
virtual bool interpret(unsigned _id, RLP const& _r);
/// Transition state in a particular direction.
void transition(Asking _wantState, bool _force = false);
void transition(Asking _wantState, bool _force = false, bool _needHelp = true);
/// Attempt to begin syncing with this peer; first check the peer has a more difficlult chain to download, then start asking for hashes, then move to blocks.
void attemptSync();
@ -89,7 +89,7 @@ private:
void clearKnownTransactions() { std::lock_guard<std::mutex> l(x_knownTransactions); m_knownTransactions.clear(); }
/// Update our asking state.
void setAsking(Asking _g, bool _isSyncing);
void setAsking(Asking _g, bool _isSyncing, bool _needHelp = true);
/// Update our syncing requirements state.
void setNeedsSyncing(h256 _latestHash, u256 _td);

8
test/libethcore/dagger.cpp

@ -63,14 +63,14 @@ BOOST_AUTO_TEST_CASE(basic_test)
unsigned cacheSize(o["cache_size"].get_int());
h256 cacheHash(o["cache_hash"].get_str());
BOOST_REQUIRE_EQUAL(EthashAux::get()->light(header)->size, cacheSize);
BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->light(header)->data()), cacheHash);
BOOST_REQUIRE_EQUAL(EthashAux::get()->light(header.seedHash())->size, cacheSize);
BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->light(header.seedHash())->data()), cacheHash);
#if TEST_FULL
unsigned fullSize(o["full_size"].get_int());
h256 fullHash(o["full_hash"].get_str());
BOOST_REQUIRE_EQUAL(EthashAux::get()->full(header)->size(), fullSize);
BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->full(header)->data()), fullHash);
BOOST_REQUIRE_EQUAL(EthashAux::get()->full(header.seedHash())->size(), fullSize);
BOOST_REQUIRE_EQUAL(sha3(EthashAux::get()->full(header.seedHash())->data()), fullHash);
#endif
h256 result(o["result"].get_str());

Loading…
Cancel
Save