Browse Source

Tweak Dagger API to facilitate more complex mining.

cl-refactor
Tim Hughes 11 years ago
parent
commit
0133a4450d
  1. 3
      libethereum/BlockInfo.cpp
  2. 88
      libethereum/Dagger.cpp
  3. 17
      libethereum/Dagger.h
  4. 5
      libethereum/State.cpp
  5. 2
      libethereum/State.h
  6. 15
      test/main.cpp

3
libethereum/BlockInfo.cpp

@ -91,8 +91,7 @@ void BlockInfo::populate(bytesConstRef _block)
}
// check it hashes according to proof of work.
Dagger d(headerHashWithoutNonce());
if (d.eval(nonce) >= difficulty)
if (!Dagger::verify(headerHashWithoutNonce(), nonce, difficulty))
throw InvalidNonce();
}

88
libethereum/Dagger.cpp

@ -14,7 +14,7 @@ using namespace std::chrono;
namespace eth
{
Dagger::Dagger(h256 _hash): m_hash(_hash)
Dagger::Dagger()
{
}
@ -22,30 +22,45 @@ Dagger::~Dagger()
{
}
u256 Dagger::bound(u256 _diff)
u256 Dagger::bound(u256 const& _difficulty)
{
return (u256)((bigint(1) << 256) / _diff);
return (u256)((bigint(1) << 256) / _difficulty);
}
u256 Dagger::search(uint _msTimeout, u256 _diff)
bool Dagger::verify(h256 const& _root, u256 const& _nonce, u256 const& _difficulty)
{
static mt19937_64 s_engine((std::random_device())());
u256 b = bound(_diff);
return eval(_root, _nonce) < bound(_difficulty);
}
auto start = steady_clock::now();
bool Dagger::mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, uint _msTimeout)
{
// restart search if root has changed
if (m_root != _root)
{
m_root = _root;
m_nonce = 0;
}
while (steady_clock::now() - start < milliseconds(_msTimeout))
for (uint sp = std::uniform_int_distribution<uint>()(s_engine), j = 0; j < 1000; ++j, ++sp)
if (eval(sp) < b)
return sp;
return 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); m_nonce += 1)
{
if (eval(_root, m_nonce) < b)
{
o_solution = m_nonce;
return true;
}
}
return false;
}
template <class _T, class _U>
inline void update(_T& _sha, _U const& _value)
template <class _T>
inline void update(_T& _sha, u256 const& _value)
{
int i = 0;
for (_U v = _value; v; ++i, v >>= 8) {}
for (u256 v = _value; v; ++i, v >>= 8) {}
byte buf[32];
bytesRef bufRef(buf, i);
toBigEndian(_value, bufRef);
@ -53,48 +68,57 @@ inline void update(_T& _sha, _U const& _value)
}
template <class _T>
inline u256 get(_T& _sha)
inline void update(_T& _sha, h256 const& _value)
{
byte buf[32];
_sha.TruncatedFinal(buf, 32);
return fromBigEndian<u256>(bytesConstRef(buf, 32));
int i = 0;
byte const* data = _value.data();
for (; i != 32 && data[i] == 0; ++i);
_sha.Update(data + i, 32 - i);
}
template <class _T>
inline h256 get(_T& _sha)
{
h256 ret;
_sha.TruncatedFinal(&ret[0], 32);
return ret;
}
u256 Dagger::node(uint_fast32_t _L, uint_fast32_t _i) const
h256 Dagger::node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i)
{
if (_L == _i)
return m_hash;
return _root;
u256 m = (_L == 9) ? 16 : 3;
CryptoPP::SHA3_256 bsha;
for (uint_fast32_t k = 0; k < m; ++k)
{
CryptoPP::SHA3_256 sha;
update(sha, m_hash);
update(sha, m_xn);
update(sha, _root);
update(sha, _xn);
update(sha, (u256)_L);
update(sha, (u256)_i);
update(sha, (u256)k);
uint_fast32_t pk = (uint_fast32_t)get(sha) & ((1 << ((_L - 1) * 3)) - 1);
auto u = node(_L - 1, pk);
uint_fast32_t pk = (uint_fast32_t)(u256)get(sha) & ((1 << ((_L - 1) * 3)) - 1);
auto u = node(_root, _xn, _L - 1, pk);
update(bsha, u);
}
return get(bsha);
}
u256 Dagger::eval(u256 _N)
h256 Dagger::eval(h256 const& _root, u256 const& _nonce)
{
m_xn = _N >> 26; // with xn = floor(n / 2^26) -> assuming this is with xn = floor(N / 2^26)
h256 extranonce = _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)
{
//sha256(D || xn || i || k) -> sha256(D || xn || k) - there's no 'i' here!
CryptoPP::SHA3_256 sha;
update(sha, m_hash);
update(sha, m_xn);
update(sha, _N);
update(sha, _root);
update(sha, extranonce);
update(sha, _nonce);
update(sha, (u256)k);
uint_fast32_t pk = (uint_fast32_t)get(sha) & 0x1ffffff; // mod 8^8 * 2 [ == mod 2^25 ?! ] [ == & ((1 << 25) - 1) ] [ == & 0x1ffffff ]
auto u = node(9, pk);
uint_fast32_t pk = (uint_fast32_t)(u256)get(sha) & 0x1ffffff; // mod 8^8 * 2 [ == mod 2^25 ?! ] [ == & ((1 << 25) - 1) ] [ == & 0x1ffffff ]
auto u = node(_root, extranonce, 9, pk);
update(bsha, u);
}
return get(bsha);

17
libethereum/Dagger.h

@ -9,18 +9,21 @@ namespace eth
class Dagger
{
public:
Dagger(h256 _hash);
Dagger();
~Dagger();
u256 node(uint_fast32_t _L, uint_fast32_t _i) const;
u256 eval(u256 _N);
u256 search(uint _msTimeout, u256 _diff);
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);
static u256 bound(u256 _diff);
bool mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, uint _msTimeout = 100);
private:
u256 m_hash;
u256 m_xn;
static h256 node(h256 const& _root, h256 const& _xn, uint_fast32_t _L, uint_fast32_t _i);
h256 m_root;
u256 m_nonce;
};
}

5
libethereum/State.cpp

@ -250,10 +250,7 @@ bool State::mine(uint _msTimeout)
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
// TODO: Miner class that keeps dagger between mine calls (or just non-polling mining).
Dagger d(m_currentBlock.headerHashWithoutNonce());
m_currentBlock.nonce = d.search(_msTimeout, m_currentBlock.difficulty);
if (m_currentBlock.nonce)
if (m_dagger.mine(/*out*/m_currentBlock.nonce, m_currentBlock.headerHashWithoutNonce(), m_currentBlock.difficulty, _msTimeout))
{
// Got it! Compile block:
RLPStream ret;

2
libethereum/State.h

@ -176,6 +176,8 @@ private:
Address m_ourAddress; ///< Our address (i.e. the address to which fees go).
Dagger m_dagger;
/// The fee structure. Values yet to be agreed on...
static const u256 c_stepFee;
static const u256 c_dataFee;

15
test/main.cpp

@ -39,22 +39,23 @@ int main()
/*
// Test dagger
{
Dagger d((h256)0);
Dagger d;
auto s = steady_clock::now();
cout << hex << d.eval(0);
cout << hex << d.eval((h256)1, 0);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
cout << hex << d.eval(1);
cout << hex << d.eval((h256)1, 1);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
}
{
Dagger d((h256)1);
Dagger d;
auto s = steady_clock::now();
cout << hex << d.eval(0);
cout << hex << d.eval((h256)1, 0);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
cout << hex << d.eval(1);
cout << hex << d.eval((h256)1, 1);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;
}
*/
//*/
/*
// Test transaction.
bytes tx = fromUserHex("88005401010101010101010101010101010101010101011f0de0b6b3a76400001ce8d4a5100080181c373130a009ba1f10285d4e659568bfcfec85067855c5a3c150100815dad4ef98fd37cf0593828c89db94bd6c64e210a32ef8956eaa81ea9307194996a3b879441f5d");

Loading…
Cancel
Save