23 #include <boost/detail/endian.hpp> 24 #include <boost/filesystem.hpp> 47 EthashAux::~EthashAux()
53 static std::once_flag flag;
54 std::call_once(flag, []{s_this =
new EthashAux();});
63 uint64_t EthashAux::dataSize(uint64_t _blockNumber)
68 h256 EthashAux::seedHash(
unsigned _number)
71 Guard l(
get()->x_epochs);
72 if (epoch >=
get()->m_seedHashes.size())
76 if (!
get()->m_seedHashes.empty())
78 ret =
get()->m_seedHashes.back();
79 n =
get()->m_seedHashes.
size() - 1;
81 get()->m_seedHashes.resize(epoch + 1);
83 for (; n <= epoch; ++n, ret =
sha3(ret))
85 get()->m_seedHashes[n] = ret;
89 return get()->m_seedHashes[epoch];
92 uint64_t EthashAux::number(
h256 const& _seedHash)
94 Guard l(
get()->x_epochs);
96 auto epochIter =
get()->m_epochs.find(_seedHash);
97 if (epochIter ==
get()->m_epochs.end())
100 for (
h256 h;
h != _seedHash && epoch < 2048; ++epoch,
h =
sha3(h),
get()->m_epochs[h] = epoch) {}
103 std::ostringstream
error;
104 error <<
"apparent block number for " << _seedHash <<
" is too high; max is " << (
ETHASH_EPOCH_LENGTH * 2048);
105 throw std::invalid_argument(error.str());
109 epoch = epochIter->second;
113 void EthashAux::killCache(
h256 const& _s)
122 if (
get()->m_lights.count(_seedHash))
123 return get()->m_lights.at(_seedHash);
125 return (
get()->m_lights[_seedHash] = make_shared<LightAllocation>(_seedHash));
128 EthashAux::LightAllocation::LightAllocation(
h256 const& _seedHash)
130 uint64_t blockNumber = EthashAux::number(_seedHash);
137 EthashAux::LightAllocation::~LightAllocation()
154 clog(
DAGChannel) <<
"DAG Generation Failure. Reason: " << strerror(errno);
159 EthashAux::FullAllocation::~FullAllocation()
169 static std::function<int(unsigned)> s_dagCallback;
170 static int dagCallbackShim(
unsigned _p)
173 return s_dagCallback ? s_dagCallback(_p) : 0;
179 auto l = light(_seedHash);
182 if ((ret =
get()->m_fulls[_seedHash].lock()))
184 get()->m_lastUsedFull = ret;
188 if (_createIfMissing || computeFull(_seedHash,
false) == 100)
192 ret = make_shared<FullAllocation>(l->light, dagCallbackShim);
196 get()->m_fulls[_seedHash] =
get()->m_lastUsedFull = ret;
202 unsigned EthashAux::computeFull(
h256 const& _seedHash,
bool _createIfMissing)
204 Guard l(
get()->x_fulls);
205 uint64_t blockNumber;
212 if (
FullType ret =
get()->m_fulls[_seedHash].lock())
214 get()->m_lastUsedFull = ret;
218 if (_createIfMissing && (!
get()->m_fullGenerator || !
get()->m_fullGenerator->joinable()))
220 get()->m_fullProgress = 0;
222 get()->m_fullGenerator = unique_ptr<thread>(
new thread([=](){
223 cnote <<
"Loading full DAG of seedhash: " << _seedHash;
224 get()->full(_seedHash,
true, [](
unsigned p){
get()->m_fullProgress = p;
return 0; });
225 cnote <<
"Full DAG loaded";
226 get()->m_fullProgress = 0;
227 get()->m_generatingFullNumber = NotGenerating;
231 return (
get()->m_generatingFullNumber == blockNumber) ?
get()->m_fullProgress : 0;
238 BOOST_THROW_EXCEPTION(DAGCreationFailure());
246 BOOST_THROW_EXCEPTION(DAGCreationFailure());
253 if (
FullType dag =
get()->m_fulls[_seedHash].lock())
254 return dag->compute(_headerHash, _nonce);
255 DEV_IF_THROWS(
return EthashAux::get()->light(_seedHash)->compute(_headerHash, _nonce))
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
bool error(const char *fmt, const Args &...args)
uint64_t ethash_get_datasize(uint64_t const block_number)
std::shared_ptr< FullAllocation > FullType
static EthashAux * s_this
boost::upgrade_to_unique_lock< boost::shared_mutex > UpgradeGuard
std::hash for asio::adress
ethash_light_t ethash_light_new(uint64_t block_number)
Allocate and initialize a new ethash_light handler.
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
boost::upgrade_lock< boost::shared_mutex > UpgradableGuard
void ethash_light_delete(ethash_light_t light)
Frees a previously allocated ethash_light handler.
std::shared_ptr< LightAllocation > LightType
#define ETHASH_EPOCH_LENGTH
#define DEV_GUARDED(MUTEX)
Simple block guard.
void const * ethash_full_dag(ethash_full_t full)
Get a pointer to the full DAG data.
std::lock_guard< std::mutex > Guard
void ethash_full_delete(ethash_full_t full)
Frees a previously allocated ethash_full handler.
ethash_return_value_t ethash_light_compute(ethash_light_t light, ethash_h256_t const header_hash, uint64_t nonce)
Calculate the light client data.
vector_ref< byte const > bytesConstRef
boost::unique_lock< boost::shared_mutex > WriteGuard
Type of a seedhash/blockhash e.t.c.
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 64, 64, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u64
uint8_t const size_t const size
uint64_t ethash_get_cachesize(uint64_t const block_number)
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
int(* ethash_callback_t)(unsigned)
ethash_return_value_t ethash_full_compute(ethash_full_t full, ethash_h256_t const header_hash, uint64_t nonce)
Calculate the full client data.
ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback)
Allocate and initialize a new ethash_full handler.