Browse Source

Move Dagger to ProofOfWork and refactor in preparation for ARPoW.

cl-refactor
Gav Wood 11 years ago
parent
commit
d74db4083c
  1. 1
      alethzero/MainWin.cpp
  2. 4
      libethcore/BlockInfo.cpp
  3. 84
      libethcore/Dagger.h
  4. 97
      libethcore/ProofOfWork.cpp
  5. 117
      libethcore/ProofOfWork.h
  6. 2
      libethcore/_libethcore.cpp
  7. 2
      libethereum/BlockChain.cpp
  8. 1
      libethereum/Client.h
  9. 3
      libethereum/State.cpp
  10. 4
      libethereum/State.h
  11. 2
      libp2p/Session.cpp
  12. 1
      libqethereum/QEthereum.cpp
  13. 1
      libqethereum/QmlEthereum.cpp
  14. 14
      test/dagger.cpp
  15. 1
      third/MainWin.cpp

1
alethzero/MainWin.cpp

@ -33,7 +33,6 @@
#include <libserpent/funcs.h>
#include <libserpent/util.h>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Dagger.h>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>
#include <libevm/VM.h>

4
libethcore/BlockInfo.cpp

@ -24,7 +24,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/RLP.h>
#include <libdevcrypto/TrieDB.h>
#include "Dagger.h"
#include "ProofOfWork.h"
#include "Exceptions.h"
#include "BlockInfo.h"
using namespace std;
@ -99,7 +99,7 @@ void BlockInfo::populateFromHeader(RLP const& _header, bool _checkNonce)
}
// check it hashes according to proof of work or that it's the genesis block.
if (_checkNonce && parentHash && !Dagger::verify(headerHashWithoutNonce(), nonce, difficulty))
if (_checkNonce && parentHash && !ProofOfWork::verify(headerHashWithoutNonce(), nonce, difficulty))
BOOST_THROW_EXCEPTION(InvalidBlockNonce(headerHashWithoutNonce(), nonce, difficulty));
if (gasUsed > gasLimit)

84
libethcore/Dagger.h

@ -1,84 +0,0 @@
/*
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 Dagger.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*
* Dagger algorithm. Or not.
*/
#pragma once
#include <libdevcrypto/SHA3.h>
#include "CommonEth.h"
#define FAKE_DAGGER 1
namespace dev
{
namespace eth
{
struct MineInfo
{
void combine(MineInfo const& _m) { requirement = std::max(requirement, _m.requirement); best = std::min(best, _m.best); hashes += _m.hashes; completed = completed || _m.completed; }
double requirement = 0;
double best = 1e99;
unsigned hashes = 0;
bool completed = false;
};
#if FAKE_DAGGER
class Dagger
{
public:
static h256 eval(h256 const& _root, h256 const& _nonce) { h256 b[2] = { _root, _nonce }; return sha3(bytesConstRef((byte const*)&b[0], 64)); }
static bool verify(h256 const& _root, h256 const& _nonce, u256 const& _difficulty) { return (bigint)(u256)eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; }
MineInfo mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false);
h256 m_last;
};
#else
/// Functions are not re-entrant. If you want to multi-thread, then use different classes for each thread.
class Dagger
{
public:
Dagger();
~Dagger();
static u256 bound(u256 const& _difficulty);
static h256 eval(h256 const& _root, u256 const& _nonce);
static bool verify(h256 const& _root, u256 const& _nonce, u256 const& _difficulty);
bool mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool const& _continue = bool(true));
private:
static h256 node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i);
h256 m_root;
u256 m_nonce;
};
#endif
}
}

97
libethcore/Dagger.cpp → libethcore/ProofOfWork.cpp

@ -14,7 +14,7 @@
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 Dagger.cpp
/** @file ProofOfWork.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
@ -28,7 +28,7 @@
#include <thread>
#include <libethcore/CryptoHeaders.h>
#include <libdevcore/Common.h>
#include "Dagger.h"
#include "ProofOfWork.h"
using namespace std;
using namespace std::chrono;
@ -37,88 +37,8 @@ namespace dev
namespace eth
{
#if FAKE_DAGGER
MineInfo Dagger::mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo)
{
MineInfo ret;
static std::mt19937_64 s_eng((time(0) + (unsigned)m_last));
u256 s = (m_last = h256::random(s_eng));
bigint d = (bigint(1) << 256) / _difficulty;
ret.requirement = log2((double)d);
// 2^ 0 32 64 128 256
// [--------*-------------------------]
//
// evaluate until we run out of time
auto startTime = steady_clock::now();
if (!_turbo)
this_thread::sleep_for(chrono::milliseconds(_msTimeout * 90 / 100));
for (; (steady_clock::now() - startTime) < milliseconds(_msTimeout) && _continue; s++, ret.hashes++)
{
o_solution = (h256)s;
auto e = (bigint)(u256)eval(_root, o_solution);
ret.best = min<double>(ret.best, log2((double)e));
if (e <= d)
{
ret.completed = true;
break;
}
}
if (ret.completed)
assert(verify(_root, o_solution, _difficulty));
return ret;
}
#else
Dagger::Dagger()
{
}
Dagger::~Dagger()
{
}
u256 Dagger::bound(u256 const& _difficulty)
{
return (u256)((bigint(1) << 256) / _difficulty);
}
bool Dagger::verify(h256 const& _root, u256 const& _nonce, u256 const& _difficulty)
{
return eval(_root, _nonce) < bound(_difficulty);
}
bool Dagger::mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool const& _continue)
{
// restart search if root has changed
if (m_root != _root)
{
m_root = _root;
m_nonce = 0;
}
// compute bound
u256 const b = bound(_difficulty);
// evaluate until we run out of time
for (auto startTime = steady_clock::now(); (steady_clock::now() - startTime) < milliseconds(_msTimeout) && _continue; m_nonce += 1)
{
if (eval(_root, m_nonce) < b)
{
o_solution = m_nonce;
return true;
}
}
return false;
}
template <class _T>
inline void update(_T& _sha, u256 const& _value)
static inline void update(_T& _sha, u256 const& _value)
{
int i = 0;
for (u256 v = _value; v; ++i, v >>= 8) {}
@ -129,7 +49,7 @@ inline void update(_T& _sha, u256 const& _value)
}
template <class _T>
inline void update(_T& _sha, h256 const& _value)
static inline void update(_T& _sha, h256 const& _value)
{
int i = 0;
byte const* data = _value.data();
@ -138,14 +58,14 @@ inline void update(_T& _sha, h256 const& _value)
}
template <class _T>
inline h256 get(_T& _sha)
static inline h256 get(_T& _sha)
{
h256 ret;
_sha.TruncatedFinal(&ret[0], 32);
return ret;
}
h256 Dagger::node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i)
h256 DaggerEvaluator::node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i)
{
if (_L == _i)
return _root;
@ -166,9 +86,9 @@ h256 Dagger::node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fas
return get(bsha);
}
h256 Dagger::eval(h256 const& _root, u256 const& _nonce)
h256 DaggerEvaluator::eval(h256 const& _root, h256 const& _nonce)
{
h256 extranonce = _nonce >> 26; // with xn = floor(n / 2^26) -> assuming this is with xn = floor(N / 2^26)
h256 extranonce = (u256)_nonce >> 26; // with xn = floor(n / 2^26) -> assuming this is with xn = floor(N / 2^26)
CryptoPP::SHA3_256 bsha;
for (uint_fast32_t k = 0; k < 4; ++k)
{
@ -185,7 +105,6 @@ h256 Dagger::eval(h256 const& _root, u256 const& _nonce)
return get(bsha);
}
#endif
}
}
#endif

117
libethcore/ProofOfWork.h

@ -0,0 +1,117 @@
/*
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 ProofOfWork.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*
* ProofOfWork algorithm. Or not.
*/
#pragma once
#include <chrono>
#include <thread>
#include <cstdint>
#include <libdevcrypto/SHA3.h>
#include "CommonEth.h"
#define FAKE_DAGGER 1
namespace dev
{
namespace eth
{
struct MineInfo
{
void combine(MineInfo const& _m) { requirement = std::max(requirement, _m.requirement); best = std::min(best, _m.best); hashes += _m.hashes; completed = completed || _m.completed; }
double requirement = 0;
double best = 1e99;
unsigned hashes = 0;
bool completed = false;
};
template <class Evaluator>
class ProofOfWorkEngine: public Evaluator
{
public:
static bool verify(h256 const& _root, h256 const& _nonce, u256 const& _difficulty) { return (bigint)(u256)Evaluator::eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; }
inline MineInfo mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout = 100, bool _continue = true, bool _turbo = false);
protected:
h256 m_last;
};
class SHA3Evaluator
{
public:
static h256 eval(h256 const& _root, h256 const& _nonce) { h256 b[2] = { _root, _nonce }; return sha3(bytesConstRef((byte const*)&b[0], 64)); }
};
// TODO: class ARPoWEvaluator
class DaggerEvaluator
{
public:
static h256 eval(h256 const& _root, h256 const& _nonce);
private:
static h256 node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i);
};
using SHA3ProofOfWork = ProofOfWorkEngine<SHA3Evaluator>;
using ProofOfWork = SHA3ProofOfWork;
template <class Evaluator>
MineInfo ProofOfWorkEngine<Evaluator>::mine(h256& o_solution, h256 const& _root, u256 const& _difficulty, unsigned _msTimeout, bool _continue, bool _turbo)
{
MineInfo ret;
static std::mt19937_64 s_eng((time(0) + (unsigned)m_last));
u256 s = (m_last = h256::random(s_eng));
bigint d = (bigint(1) << 256) / _difficulty;
ret.requirement = log2((double)d);
// 2^ 0 32 64 128 256
// [--------*-------------------------]
//
// evaluate until we run out of time
auto startTime = std::chrono::steady_clock::now();
if (!_turbo)
std::this_thread::sleep_for(std::chrono::milliseconds(_msTimeout * 90 / 100));
for (; (std::chrono::steady_clock::now() - startTime) < std::chrono::milliseconds(_msTimeout) && _continue; s++, ret.hashes++)
{
o_solution = (h256)s;
auto e = (bigint)(u256)Evaluator::eval(_root, o_solution);
ret.best = std::min<double>(ret.best, log2((double)e));
if (e <= d)
{
ret.completed = true;
break;
}
}
if (ret.completed)
assert(verify(_root, o_solution, _difficulty));
return ret;
}
}
}

2
libethcore/_libethcore.cpp

@ -2,6 +2,6 @@
#include "All.h"
#include "BlockInfo.cpp"
#include "CommonEth.cpp"
#include "Dagger.cpp"
#include "ProofOfWork.cpp"
#include "Exceptions.cpp"
#endif

2
libethereum/BlockChain.cpp

@ -26,7 +26,7 @@
#include <libdevcore/RLP.h>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Exceptions.h>
#include <libethcore/Dagger.h>
#include <libethcore/ProofOfWork.h>
#include <libethcore/BlockInfo.h>
#include "State.h"
#include "Defaults.h"

1
libethereum/Client.h

@ -31,7 +31,6 @@
#include <libdevcore/Guards.h>
#include <libdevcore/Worker.h>
#include <libevm/FeeStructure.h>
#include <libethcore/Dagger.h>
#include <libp2p/Common.h>
#include "BlockChain.h"
#include "TransactionQueue.h"

3
libethereum/State.cpp

@ -28,7 +28,6 @@
#include <libdevcore/CommonIO.h>
#include <libevmface/Instruction.h>
#include <libethcore/Exceptions.h>
#include <libethcore/Dagger.h>
#include <libevm/VM.h>
#include "BlockChain.h"
#include "Defaults.h"
@ -837,7 +836,7 @@ MineInfo State::mine(unsigned _msTimeout, bool _turbo)
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
// TODO: Miner class that keeps dagger between mine calls (or just non-polling mining).
auto ret = m_dagger.mine(/*out*/m_currentBlock.nonce, m_currentBlock.headerHashWithoutNonce(), m_currentBlock.difficulty, _msTimeout, true, _turbo);
auto ret = m_pow.mine(/*out*/m_currentBlock.nonce, m_currentBlock.headerHashWithoutNonce(), m_currentBlock.difficulty, _msTimeout, true, _turbo);
if (!ret.completed)
m_currentBytes.clear();

4
libethereum/State.h

@ -29,7 +29,7 @@
#include <libdevcrypto/TrieDB.h>
#include <libethcore/Exceptions.h>
#include <libethcore/BlockInfo.h>
#include <libethcore/Dagger.h>
#include <libethcore/ProofOfWork.h>
#include <libevm/FeeStructure.h>
#include <libevm/ExtVMFace.h>
#include "TransactionQueue.h"
@ -322,7 +322,7 @@ private:
Address m_ourAddress; ///< Our address (i.e. the address to which fees go).
Dagger m_dagger;
ProofOfWork m_pow;
u256 m_blockReward;

2
libp2p/Session.cpp

@ -234,6 +234,8 @@ bool Session::interpret(RLP const& _r)
}
m_node = m_server->noteNode(id, bi::tcp::endpoint(m_socket.remote_endpoint().address(), listenPort), Origin::Self, false, !m_node || m_node->id == id ? NodeId() : m_node->id);
if (m_node->isOffline())
m_node->lastConnected = chrono::system_clock::now();
m_knownNodes.extendAll(m_node->index);
m_knownNodes.unionWith(m_node->index);

1
libqethereum/QEthereum.cpp

@ -1,7 +1,6 @@
#include <QtCore/QtCore>
#include <QtWebKitWidgets/QWebFrame>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Dagger.h>
#include <libevmface/Instruction.h>
#include <liblll/Compiler.h>
#include <libethereum/Client.h>

1
libqethereum/QmlEthereum.cpp

@ -4,7 +4,6 @@
#include <QtCore/QtCore>
#include <QtWebKitWidgets/QWebFrame>
#include <libdevcrypto/FileSystem.h>
#include <libethcore/Dagger.h>
#include <libevmface/Instruction.h>
#include <liblll/Compiler.h>
#include <libethereum/Client.h>

14
test/dagger.cpp

@ -17,12 +17,12 @@
/** @file dagger.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Dagger test functions.
* ProofOfWork test functions.
*/
#include <chrono>
#include <libdevcore/Log.h>
#include <libethcore/Dagger.h>
#include <libethcore/ProofOfWork.h>
using namespace std;
using namespace std::chrono;
using namespace dev;
@ -30,20 +30,20 @@ using namespace dev::eth;
int daggerTest()
{
cnote << "Testing Dagger...";
cnote << "Testing ProofOfWork...";
// Test dagger
{
auto s = steady_clock::now();
cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)0);
cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)0);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)1);
cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)1);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
}
{
auto s = steady_clock::now();
cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)0);
cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)0);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
cout << hex << Dagger().eval((h256)(u256)1, (h256)(u256)1);
cout << hex << ProofOfWork().eval((h256)(u256)1, (h256)(u256)1);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
}
return 0;

1
third/MainWin.cpp

@ -30,7 +30,6 @@
#include <boost/algorithm/string.hpp>
#include <libserpent/funcs.h>
#include <libserpent/util.h>
#include <libethcore/Dagger.h>
#include <libdevcrypto/FileSystem.h>
#include <liblll/Compiler.h>
#include <liblll/CodeFragment.h>

Loading…
Cancel
Save