Paweł Bylica
10 years ago
192 changed files with 5286 additions and 2573 deletions
@ -0,0 +1,497 @@ |
|||
#pragma once |
|||
|
|||
/*
|
|||
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 main.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
* Ethereum client. |
|||
*/ |
|||
|
|||
#include <thread> |
|||
#include <chrono> |
|||
#include <fstream> |
|||
#include <iostream> |
|||
#include <signal.h> |
|||
|
|||
#include <boost/algorithm/string.hpp> |
|||
#include <boost/algorithm/string/trim_all.hpp> |
|||
|
|||
#include <libdevcore/FileSystem.h> |
|||
#include <libevmcore/Instruction.h> |
|||
#include <libdevcore/StructuredLogger.h> |
|||
#include <libethcore/Exceptions.h> |
|||
#include <libdevcore/SHA3.h> |
|||
#include <libethcore/ProofOfWork.h> |
|||
#include <libethcore/EthashAux.h> |
|||
#include <libethcore/Farm.h> |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
#include <libweb3jsonrpc/WebThreeStubServer.h> |
|||
#include <jsonrpccpp/server/connectors/httpserver.h> |
|||
#include <jsonrpccpp/client/connectors/httpclient.h> |
|||
#endif |
|||
#include "BuildInfo.h" |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
#include "PhoneHome.h" |
|||
#include "Farm.h" |
|||
#endif |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
using namespace boost::algorithm; |
|||
using dev::eth::Instruction; |
|||
|
|||
#undef RETURN |
|||
|
|||
bool isTrue(std::string const& _m) |
|||
{ |
|||
return _m == "on" || _m == "yes" || _m == "true" || _m == "1"; |
|||
} |
|||
|
|||
bool isFalse(std::string const& _m) |
|||
{ |
|||
return _m == "off" || _m == "no" || _m == "false" || _m == "0"; |
|||
} |
|||
|
|||
inline std::string credits() |
|||
{ |
|||
std::ostringstream out; |
|||
out |
|||
<< "Ethereum (++) " << dev::Version << endl |
|||
<< " Code by Gav Wood et al, (c) 2013, 2014, 2015." << endl; |
|||
return out.str(); |
|||
} |
|||
|
|||
class BadArgument: public Exception {}; |
|||
|
|||
class MinerCLI |
|||
{ |
|||
public: |
|||
enum class OperationMode |
|||
{ |
|||
None, |
|||
DAGInit, |
|||
Benchmark, |
|||
Farm |
|||
}; |
|||
|
|||
MinerCLI(OperationMode _mode = OperationMode::None): mode(_mode) {} |
|||
|
|||
bool interpretOption(int& i, int argc, char** argv) |
|||
{ |
|||
string arg = argv[i]; |
|||
if ((arg == "-F" || arg == "--farm") && i + 1 < argc) |
|||
{ |
|||
mode = OperationMode::Farm; |
|||
farmURL = argv[++i]; |
|||
} |
|||
else if (arg == "--farm-recheck" && i + 1 < argc) |
|||
try { |
|||
farmRecheckPeriod = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
throw BadArgument(); |
|||
} |
|||
else if (arg == "--opencl-platform" && i + 1 < argc) |
|||
try { |
|||
openclPlatform = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
throw BadArgument(); |
|||
} |
|||
else if (arg == "--opencl-device" && i + 1 < argc) |
|||
try { |
|||
openclDevice = stol(argv[++i]); |
|||
miningThreads = 1; |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
throw BadArgument(); |
|||
} |
|||
else if (arg == "--phone-home" && i + 1 < argc) |
|||
{ |
|||
string m = argv[++i]; |
|||
if (isTrue(m)) |
|||
phoneHome = true; |
|||
else if (isFalse(m)) |
|||
phoneHome = false; |
|||
else |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << m << endl; |
|||
throw BadArgument(); |
|||
} |
|||
} |
|||
else if (arg == "--benchmark-warmup" && i + 1 < argc) |
|||
try { |
|||
benchmarkWarmup = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
throw BadArgument(); |
|||
} |
|||
else if (arg == "--benchmark-trial" && i + 1 < argc) |
|||
try { |
|||
benchmarkTrial = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
throw BadArgument(); |
|||
} |
|||
else if (arg == "--benchmark-trials" && i + 1 < argc) |
|||
try { |
|||
benchmarkTrials = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
throw BadArgument(); |
|||
} |
|||
else if (arg == "-C" || arg == "--cpu") |
|||
m_minerType = MinerType::CPU; |
|||
else if (arg == "-G" || arg == "--opencl") |
|||
{ |
|||
m_minerType = MinerType::GPU; |
|||
miningThreads = 1; |
|||
} |
|||
else if (arg == "--no-precompute") |
|||
{ |
|||
precompute = false; |
|||
} |
|||
else if ((arg == "-D" || arg == "--create-dag") && i + 1 < argc) |
|||
{ |
|||
string m = boost::to_lower_copy(string(argv[++i])); |
|||
mode = OperationMode::DAGInit; |
|||
try |
|||
{ |
|||
initDAG = stol(m); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << m << endl; |
|||
throw BadArgument(); |
|||
} |
|||
} |
|||
else if ((arg == "-w" || arg == "--check-pow") && i + 4 < argc) |
|||
{ |
|||
string m; |
|||
try |
|||
{ |
|||
BlockInfo bi; |
|||
m = boost::to_lower_copy(string(argv[++i])); |
|||
h256 powHash(m); |
|||
m = boost::to_lower_copy(string(argv[++i])); |
|||
h256 seedHash; |
|||
if (m.size() == 64 || m.size() == 66) |
|||
seedHash = h256(m); |
|||
else |
|||
seedHash = EthashAux::seedHash(stol(m)); |
|||
m = boost::to_lower_copy(string(argv[++i])); |
|||
bi.difficulty = u256(m); |
|||
auto boundary = bi.boundary(); |
|||
m = boost::to_lower_copy(string(argv[++i])); |
|||
bi.nonce = h64(m); |
|||
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; |
|||
cout << " where " << boundary << " = 2^256 / " << bi.difficulty << endl; |
|||
cout << " and " << r.value << " = ethash(" << powHash << ", " << bi.nonce << ")" << endl; |
|||
cout << " with seed as " << seedHash << endl; |
|||
if (valid) |
|||
cout << "(mixHash = " << r.mixHash << ")" << endl; |
|||
cout << "SHA3( light(seed) ) = " << sha3(EthashAux::light(bi.seedHash())->data()) << endl; |
|||
exit(0); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << m << endl; |
|||
throw BadArgument(); |
|||
} |
|||
} |
|||
else if (arg == "-M" || arg == "--benchmark") |
|||
mode = OperationMode::Benchmark; |
|||
else if ((arg == "-t" || arg == "--mining-threads") && i + 1 < argc) |
|||
{ |
|||
try { |
|||
miningThreads = stol(argv[++i]); |
|||
} |
|||
catch (...) |
|||
{ |
|||
cerr << "Bad " << arg << " option: " << argv[i] << endl; |
|||
throw BadArgument(); |
|||
} |
|||
} |
|||
else |
|||
return false; |
|||
return true; |
|||
} |
|||
|
|||
void execute() |
|||
{ |
|||
if (m_minerType == MinerType::CPU) |
|||
ProofOfWork::CPUMiner::setNumInstances(miningThreads); |
|||
else if (m_minerType == MinerType::GPU) |
|||
{ |
|||
ProofOfWork::GPUMiner::setDefaultPlatform(openclPlatform); |
|||
ProofOfWork::GPUMiner::setDefaultDevice(openclDevice); |
|||
ProofOfWork::GPUMiner::setNumInstances(miningThreads); |
|||
} |
|||
if (mode == OperationMode::DAGInit) |
|||
doInitDAG(initDAG); |
|||
else if (mode == OperationMode::Benchmark) |
|||
doBenchmark(m_minerType, phoneHome, benchmarkWarmup, benchmarkTrial, benchmarkTrials); |
|||
else if (mode == OperationMode::Farm) |
|||
doFarm(m_minerType, farmURL, farmRecheckPeriod); |
|||
} |
|||
|
|||
static void streamHelp(ostream& _out) |
|||
{ |
|||
_out |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
<< "Work farming mode:" << endl |
|||
<< " -F,--farm <url> Put into mining farm mode with the work server at URL (default: http://127.0.0.1:8545)" << endl |
|||
<< " --farm-recheck <n> Leave n ms between checks for changed work (default: 500)." << endl |
|||
<< " --no-precompute Don't precompute the next epoch's DAG." << endl |
|||
#endif |
|||
<< "Ethash verify mode:" << endl |
|||
<< " -w,--check-pow <headerHash> <seedHash> <difficulty> <nonce> Check PoW credentials for validity." << endl |
|||
<< endl |
|||
<< "Benchmarking mode:" << endl |
|||
<< " -M,--benchmark Benchmark for mining and exit; use with --cpu and --opencl." << endl |
|||
<< " --benchmark-warmup <seconds> Set the duration of warmup for the benchmark tests (default: 3)." << endl |
|||
<< " --benchmark-trial <seconds> Set the duration for each trial for the benchmark tests (default: 3)." << endl |
|||
<< " --benchmark-trials <n> Set the duration of warmup for the benchmark tests (default: 5)." << endl |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
<< " --phone-home <on/off> When benchmarking, publish results (default: on)" << endl |
|||
#endif |
|||
<< "DAG creation mode:" << endl |
|||
<< " -D,--create-dag <number> Create the DAG in preparation for mining on given block and exit." << endl |
|||
<< "Mining configuration:" << endl |
|||
<< " -C,--cpu When mining, use the CPU." << endl |
|||
<< " -G,--opencl When mining use the GPU via OpenCL." << endl |
|||
<< " --opencl-platform <n> When mining using -G/--opencl use OpenCL platform n (default: 0)." << endl |
|||
<< " --opencl-device <n> When mining using -G/--opencl use OpenCL device n (default: 0)." << endl |
|||
<< " -t, --mining-threads <n> Limit number of CPU/GPU miners to n (default: use everything available on selected platform)" << endl |
|||
; |
|||
} |
|||
|
|||
enum class MinerType |
|||
{ |
|||
CPU, |
|||
GPU |
|||
}; |
|||
|
|||
MinerType minerType() const { return m_minerType; } |
|||
|
|||
private: |
|||
void doInitDAG(unsigned _n) |
|||
{ |
|||
BlockInfo bi; |
|||
bi.number = _n; |
|||
cout << "Initializing DAG for epoch beginning #" << (bi.number / 30000 * 30000) << " (seedhash " << bi.seedHash().abridged() << "). This will take a while." << endl; |
|||
Ethash::prep(bi); |
|||
exit(0); |
|||
} |
|||
|
|||
void doBenchmark(MinerType _m, bool _phoneHome, unsigned _warmupDuration = 15, unsigned _trialDuration = 3, unsigned _trials = 5) |
|||
{ |
|||
BlockInfo genesis; |
|||
genesis.difficulty = 1 << 18; |
|||
cdebug << genesis.boundary(); |
|||
|
|||
GenericFarm<Ethash> f; |
|||
f.onSolutionFound([&](ProofOfWork::Solution) { return false; }); |
|||
|
|||
string platformInfo = _m == MinerType::CPU ? ProofOfWork::CPUMiner::platformInfo() : _m == MinerType::GPU ? ProofOfWork::GPUMiner::platformInfo() : ""; |
|||
cout << "Benchmarking on platform: " << platformInfo << endl; |
|||
|
|||
cout << "Preparing DAG..." << endl; |
|||
Ethash::prep(genesis); |
|||
|
|||
genesis.difficulty = u256(1) << 63; |
|||
genesis.noteDirty(); |
|||
f.setWork(genesis); |
|||
if (_m == MinerType::CPU) |
|||
f.startCPU(); |
|||
else if (_m == MinerType::GPU) |
|||
f.startGPU(); |
|||
|
|||
map<uint64_t, MiningProgress> results; |
|||
uint64_t mean = 0; |
|||
uint64_t innerMean = 0; |
|||
for (unsigned i = 0; i <= _trials; ++i) |
|||
{ |
|||
if (!i) |
|||
cout << "Warming up..." << endl; |
|||
else |
|||
cout << "Trial " << i << "... " << flush; |
|||
this_thread::sleep_for(chrono::seconds(i ? _trialDuration : _warmupDuration)); |
|||
|
|||
auto mp = f.miningProgress(); |
|||
f.resetMiningProgress(); |
|||
if (!i) |
|||
continue; |
|||
auto rate = mp.rate(); |
|||
|
|||
cout << rate << endl; |
|||
results[rate] = mp; |
|||
mean += rate; |
|||
} |
|||
f.stop(); |
|||
int j = -1; |
|||
for (auto const& r: results) |
|||
if (++j > 0 && j < (int)_trials - 1) |
|||
innerMean += r.second.rate(); |
|||
innerMean /= (_trials - 2); |
|||
cout << "min/mean/max: " << results.begin()->second.rate() << "/" << (mean / _trials) << "/" << results.rbegin()->second.rate() << " H/s" << endl; |
|||
cout << "inner mean: " << innerMean << " H/s" << endl; |
|||
|
|||
(void)_phoneHome; |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
if (_phoneHome) |
|||
{ |
|||
cout << "Phoning home to find world ranking..." << endl; |
|||
jsonrpc::HttpClient client("http://gav.ethdev.com:3000"); |
|||
PhoneHome rpc(client); |
|||
try |
|||
{ |
|||
unsigned ranking = rpc.report_benchmark(platformInfo, innerMean); |
|||
cout << "Ranked: " << ranking << " of all benchmarks." << endl; |
|||
} |
|||
catch (...) |
|||
{ |
|||
cout << "Error phoning home. ET is sad." << endl; |
|||
} |
|||
} |
|||
#endif |
|||
exit(0); |
|||
} |
|||
|
|||
void doFarm(MinerType _m, string const& _remote, unsigned _recheckPeriod) |
|||
{ |
|||
(void)_m; |
|||
(void)_remote; |
|||
(void)_recheckPeriod; |
|||
#if ETH_JSONRPC || !ETH_TRUE |
|||
jsonrpc::HttpClient client(_remote); |
|||
|
|||
Farm rpc(client); |
|||
GenericFarm<Ethash> f; |
|||
if (_m == MinerType::CPU) |
|||
f.startCPU(); |
|||
else if (_m == MinerType::GPU) |
|||
f.startGPU(); |
|||
|
|||
ProofOfWork::WorkPackage current; |
|||
EthashAux::FullType dag; |
|||
while (true) |
|||
try |
|||
{ |
|||
bool completed = false; |
|||
ProofOfWork::Solution solution; |
|||
f.onSolutionFound([&](ProofOfWork::Solution sol) |
|||
{ |
|||
solution = sol; |
|||
return completed = true; |
|||
}); |
|||
for (unsigned i = 0; !completed; ++i) |
|||
{ |
|||
if (current) |
|||
cnote << "Mining on PoWhash" << current.headerHash << ": " << f.miningProgress(); |
|||
else |
|||
cnote << "Getting work package..."; |
|||
Json::Value v = rpc.eth_getWork(); |
|||
h256 hh(v[0].asString()); |
|||
h256 newSeedHash(v[1].asString()); |
|||
if (current.seedHash != newSeedHash) |
|||
cnote << "Grabbing DAG for" << newSeedHash; |
|||
if (!(dag = EthashAux::full(newSeedHash, true, [&](unsigned _pc){ cout << "\rCreating DAG. " << _pc << "% done..." << flush; return 0; }))) |
|||
BOOST_THROW_EXCEPTION(DAGCreationFailure()); |
|||
if (precompute) |
|||
EthashAux::computeFull(sha3(newSeedHash), true); |
|||
if (hh != current.headerHash) |
|||
{ |
|||
current.headerHash = hh; |
|||
current.seedHash = newSeedHash; |
|||
current.boundary = h256(fromHex(v[2].asString()), h256::AlignRight); |
|||
cnote << "Got work package:"; |
|||
cnote << " Header-hash:" << current.headerHash.hex(); |
|||
cnote << " Seedhash:" << current.seedHash.hex(); |
|||
cnote << " Target: " << h256(current.boundary).hex(); |
|||
f.setWork(current); |
|||
} |
|||
this_thread::sleep_for(chrono::milliseconds(_recheckPeriod)); |
|||
} |
|||
cnote << "Solution found; Submitting to" << _remote << "..."; |
|||
cnote << " Nonce:" << solution.nonce.hex(); |
|||
cnote << " Mixhash:" << solution.mixHash.hex(); |
|||
cnote << " Header-hash:" << current.headerHash.hex(); |
|||
cnote << " Seedhash:" << current.seedHash.hex(); |
|||
cnote << " Target: " << h256(current.boundary).hex(); |
|||
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) |
|||
cnote << "B-) Submitted and accepted."; |
|||
else |
|||
cwarn << ":-( Not accepted."; |
|||
} |
|||
else |
|||
cwarn << "FAILURE: GPU gave incorrect result!"; |
|||
current.reset(); |
|||
} |
|||
catch (jsonrpc::JsonRpcException&) |
|||
{ |
|||
for (auto i = 3; --i; this_thread::sleep_for(chrono::seconds(1))) |
|||
cerr << "JSON-RPC problem. Probably couldn't connect. Retrying in " << i << "... \r"; |
|||
cerr << endl; |
|||
} |
|||
#endif |
|||
exit(0); |
|||
} |
|||
|
|||
/// Operating mode.
|
|||
OperationMode mode; |
|||
|
|||
/// Mining options
|
|||
MinerType m_minerType = MinerType::CPU; |
|||
unsigned openclPlatform = 0; |
|||
unsigned openclDevice = 0; |
|||
unsigned miningThreads = UINT_MAX; |
|||
|
|||
/// DAG initialisation param.
|
|||
unsigned initDAG = 0; |
|||
|
|||
/// Benchmarking params
|
|||
bool phoneHome = true; |
|||
unsigned benchmarkWarmup = 3; |
|||
unsigned benchmarkTrial = 3; |
|||
unsigned benchmarkTrials = 5; |
|||
|
|||
/// Farm params
|
|||
string farmURL = "http://127.0.0.1:8545"; |
|||
unsigned farmRecheckPeriod = 500; |
|||
bool precompute = true; |
|||
}; |
@ -0,0 +1,440 @@ |
|||
/*
|
|||
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 Hash.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "Hash.h" |
|||
#include <cstdio> |
|||
#include <cstdlib> |
|||
#include <cstring> |
|||
#include "picosha2.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
|
|||
namespace dev |
|||
{ |
|||
|
|||
h256 sha256(bytesConstRef _input) |
|||
{ |
|||
h256 ret; |
|||
picosha2::hash256(_input.begin(), _input.end(), ret.data(), ret.data() + 32); |
|||
return ret; |
|||
} |
|||
|
|||
namespace rmd160 |
|||
{ |
|||
|
|||
/********************************************************************\
|
|||
* |
|||
* FILE: rmd160.h |
|||
* FILE: rmd160.c |
|||
* |
|||
* CONTENTS: Header file for a sample C-implementation of the |
|||
* RIPEMD-160 hash-function. |
|||
* TARGET: any computer with an ANSI C compiler |
|||
* |
|||
* AUTHOR: Antoon Bosselaers, ESAT-COSIC |
|||
* DATE: 1 March 1996 |
|||
* VERSION: 1.0 |
|||
* |
|||
* Copyright (c) Katholieke Universiteit Leuven |
|||
* 1996, All Rights Reserved |
|||
* |
|||
\********************************************************************/ |
|||
|
|||
// Adapted into "header-only" format by Gav Wood.
|
|||
|
|||
/* macro definitions */ |
|||
|
|||
#define RMDsize 160 |
|||
|
|||
/* collect four bytes into one word: */ |
|||
#define BYTES_TO_DWORD(strptr) \ |
|||
(((uint32_t) *((strptr)+3) << 24) | \ |
|||
((uint32_t) *((strptr)+2) << 16) | \ |
|||
((uint32_t) *((strptr)+1) << 8) | \ |
|||
((uint32_t) *(strptr))) |
|||
|
|||
/* ROL(x, n) cyclically rotates x over n bits to the left */ |
|||
/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ |
|||
#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) |
|||
|
|||
/* the five basic functions F(), G() and H() */ |
|||
#define F(x, y, z) ((x) ^ (y) ^ (z)) |
|||
#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) |
|||
#define H(x, y, z) (((x) | ~(y)) ^ (z)) |
|||
#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) |
|||
#define J(x, y, z) ((x) ^ ((y) | ~(z))) |
|||
|
|||
/* the ten basic operations FF() through III() */ |
|||
#define FF(a, b, c, d, e, x, s) {\ |
|||
(a) += F((b), (c), (d)) + (x);\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define GG(a, b, c, d, e, x, s) {\ |
|||
(a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define HH(a, b, c, d, e, x, s) {\ |
|||
(a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define II(a, b, c, d, e, x, s) {\ |
|||
(a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define JJ(a, b, c, d, e, x, s) {\ |
|||
(a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define FFF(a, b, c, d, e, x, s) {\ |
|||
(a) += F((b), (c), (d)) + (x);\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define GGG(a, b, c, d, e, x, s) {\ |
|||
(a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define HHH(a, b, c, d, e, x, s) {\ |
|||
(a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define III(a, b, c, d, e, x, s) {\ |
|||
(a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
#define JJJ(a, b, c, d, e, x, s) {\ |
|||
(a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ |
|||
(a) = ROL((a), (s)) + (e);\ |
|||
(c) = ROL((c), 10);\ |
|||
} |
|||
|
|||
void MDinit(uint32_t *MDbuf) |
|||
{ |
|||
MDbuf[0] = 0x67452301UL; |
|||
MDbuf[1] = 0xefcdab89UL; |
|||
MDbuf[2] = 0x98badcfeUL; |
|||
MDbuf[3] = 0x10325476UL; |
|||
MDbuf[4] = 0xc3d2e1f0UL; |
|||
|
|||
return; |
|||
} |
|||
|
|||
/********************************************************************/ |
|||
|
|||
void MDcompress(uint32_t *MDbuf, uint32_t *X) |
|||
{ |
|||
uint32_t aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], |
|||
dd = MDbuf[3], ee = MDbuf[4]; |
|||
uint32_t aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], |
|||
ddd = MDbuf[3], eee = MDbuf[4]; |
|||
|
|||
/* round 1 */ |
|||
FF(aa, bb, cc, dd, ee, X[ 0], 11); |
|||
FF(ee, aa, bb, cc, dd, X[ 1], 14); |
|||
FF(dd, ee, aa, bb, cc, X[ 2], 15); |
|||
FF(cc, dd, ee, aa, bb, X[ 3], 12); |
|||
FF(bb, cc, dd, ee, aa, X[ 4], 5); |
|||
FF(aa, bb, cc, dd, ee, X[ 5], 8); |
|||
FF(ee, aa, bb, cc, dd, X[ 6], 7); |
|||
FF(dd, ee, aa, bb, cc, X[ 7], 9); |
|||
FF(cc, dd, ee, aa, bb, X[ 8], 11); |
|||
FF(bb, cc, dd, ee, aa, X[ 9], 13); |
|||
FF(aa, bb, cc, dd, ee, X[10], 14); |
|||
FF(ee, aa, bb, cc, dd, X[11], 15); |
|||
FF(dd, ee, aa, bb, cc, X[12], 6); |
|||
FF(cc, dd, ee, aa, bb, X[13], 7); |
|||
FF(bb, cc, dd, ee, aa, X[14], 9); |
|||
FF(aa, bb, cc, dd, ee, X[15], 8); |
|||
|
|||
/* round 2 */ |
|||
GG(ee, aa, bb, cc, dd, X[ 7], 7); |
|||
GG(dd, ee, aa, bb, cc, X[ 4], 6); |
|||
GG(cc, dd, ee, aa, bb, X[13], 8); |
|||
GG(bb, cc, dd, ee, aa, X[ 1], 13); |
|||
GG(aa, bb, cc, dd, ee, X[10], 11); |
|||
GG(ee, aa, bb, cc, dd, X[ 6], 9); |
|||
GG(dd, ee, aa, bb, cc, X[15], 7); |
|||
GG(cc, dd, ee, aa, bb, X[ 3], 15); |
|||
GG(bb, cc, dd, ee, aa, X[12], 7); |
|||
GG(aa, bb, cc, dd, ee, X[ 0], 12); |
|||
GG(ee, aa, bb, cc, dd, X[ 9], 15); |
|||
GG(dd, ee, aa, bb, cc, X[ 5], 9); |
|||
GG(cc, dd, ee, aa, bb, X[ 2], 11); |
|||
GG(bb, cc, dd, ee, aa, X[14], 7); |
|||
GG(aa, bb, cc, dd, ee, X[11], 13); |
|||
GG(ee, aa, bb, cc, dd, X[ 8], 12); |
|||
|
|||
/* round 3 */ |
|||
HH(dd, ee, aa, bb, cc, X[ 3], 11); |
|||
HH(cc, dd, ee, aa, bb, X[10], 13); |
|||
HH(bb, cc, dd, ee, aa, X[14], 6); |
|||
HH(aa, bb, cc, dd, ee, X[ 4], 7); |
|||
HH(ee, aa, bb, cc, dd, X[ 9], 14); |
|||
HH(dd, ee, aa, bb, cc, X[15], 9); |
|||
HH(cc, dd, ee, aa, bb, X[ 8], 13); |
|||
HH(bb, cc, dd, ee, aa, X[ 1], 15); |
|||
HH(aa, bb, cc, dd, ee, X[ 2], 14); |
|||
HH(ee, aa, bb, cc, dd, X[ 7], 8); |
|||
HH(dd, ee, aa, bb, cc, X[ 0], 13); |
|||
HH(cc, dd, ee, aa, bb, X[ 6], 6); |
|||
HH(bb, cc, dd, ee, aa, X[13], 5); |
|||
HH(aa, bb, cc, dd, ee, X[11], 12); |
|||
HH(ee, aa, bb, cc, dd, X[ 5], 7); |
|||
HH(dd, ee, aa, bb, cc, X[12], 5); |
|||
|
|||
/* round 4 */ |
|||
II(cc, dd, ee, aa, bb, X[ 1], 11); |
|||
II(bb, cc, dd, ee, aa, X[ 9], 12); |
|||
II(aa, bb, cc, dd, ee, X[11], 14); |
|||
II(ee, aa, bb, cc, dd, X[10], 15); |
|||
II(dd, ee, aa, bb, cc, X[ 0], 14); |
|||
II(cc, dd, ee, aa, bb, X[ 8], 15); |
|||
II(bb, cc, dd, ee, aa, X[12], 9); |
|||
II(aa, bb, cc, dd, ee, X[ 4], 8); |
|||
II(ee, aa, bb, cc, dd, X[13], 9); |
|||
II(dd, ee, aa, bb, cc, X[ 3], 14); |
|||
II(cc, dd, ee, aa, bb, X[ 7], 5); |
|||
II(bb, cc, dd, ee, aa, X[15], 6); |
|||
II(aa, bb, cc, dd, ee, X[14], 8); |
|||
II(ee, aa, bb, cc, dd, X[ 5], 6); |
|||
II(dd, ee, aa, bb, cc, X[ 6], 5); |
|||
II(cc, dd, ee, aa, bb, X[ 2], 12); |
|||
|
|||
/* round 5 */ |
|||
JJ(bb, cc, dd, ee, aa, X[ 4], 9); |
|||
JJ(aa, bb, cc, dd, ee, X[ 0], 15); |
|||
JJ(ee, aa, bb, cc, dd, X[ 5], 5); |
|||
JJ(dd, ee, aa, bb, cc, X[ 9], 11); |
|||
JJ(cc, dd, ee, aa, bb, X[ 7], 6); |
|||
JJ(bb, cc, dd, ee, aa, X[12], 8); |
|||
JJ(aa, bb, cc, dd, ee, X[ 2], 13); |
|||
JJ(ee, aa, bb, cc, dd, X[10], 12); |
|||
JJ(dd, ee, aa, bb, cc, X[14], 5); |
|||
JJ(cc, dd, ee, aa, bb, X[ 1], 12); |
|||
JJ(bb, cc, dd, ee, aa, X[ 3], 13); |
|||
JJ(aa, bb, cc, dd, ee, X[ 8], 14); |
|||
JJ(ee, aa, bb, cc, dd, X[11], 11); |
|||
JJ(dd, ee, aa, bb, cc, X[ 6], 8); |
|||
JJ(cc, dd, ee, aa, bb, X[15], 5); |
|||
JJ(bb, cc, dd, ee, aa, X[13], 6); |
|||
|
|||
/* parallel round 1 */ |
|||
JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); |
|||
JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); |
|||
JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); |
|||
JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); |
|||
JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); |
|||
JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); |
|||
JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); |
|||
JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); |
|||
JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); |
|||
JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); |
|||
JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); |
|||
JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); |
|||
JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); |
|||
JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); |
|||
JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); |
|||
JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); |
|||
|
|||
/* parallel round 2 */ |
|||
III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); |
|||
III(ddd, eee, aaa, bbb, ccc, X[11], 13); |
|||
III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); |
|||
III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); |
|||
III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); |
|||
III(eee, aaa, bbb, ccc, ddd, X[13], 8); |
|||
III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); |
|||
III(ccc, ddd, eee, aaa, bbb, X[10], 11); |
|||
III(bbb, ccc, ddd, eee, aaa, X[14], 7); |
|||
III(aaa, bbb, ccc, ddd, eee, X[15], 7); |
|||
III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); |
|||
III(ddd, eee, aaa, bbb, ccc, X[12], 7); |
|||
III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); |
|||
III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); |
|||
III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); |
|||
III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); |
|||
|
|||
/* parallel round 3 */ |
|||
HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); |
|||
HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); |
|||
HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); |
|||
HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); |
|||
HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); |
|||
HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); |
|||
HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); |
|||
HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); |
|||
HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); |
|||
HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); |
|||
HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); |
|||
HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); |
|||
HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); |
|||
HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); |
|||
HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); |
|||
HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); |
|||
|
|||
/* parallel round 4 */ |
|||
GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); |
|||
GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); |
|||
GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); |
|||
GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); |
|||
GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); |
|||
GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); |
|||
GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); |
|||
GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); |
|||
GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); |
|||
GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); |
|||
GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); |
|||
GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); |
|||
GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); |
|||
GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); |
|||
GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); |
|||
GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); |
|||
|
|||
/* parallel round 5 */ |
|||
FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); |
|||
FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); |
|||
FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); |
|||
FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); |
|||
FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); |
|||
FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); |
|||
FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); |
|||
FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); |
|||
FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); |
|||
FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); |
|||
FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); |
|||
FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); |
|||
FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); |
|||
FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); |
|||
FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); |
|||
FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); |
|||
|
|||
/* combine results */ |
|||
ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ |
|||
MDbuf[1] = MDbuf[2] + dd + eee; |
|||
MDbuf[2] = MDbuf[3] + ee + aaa; |
|||
MDbuf[3] = MDbuf[4] + aa + bbb; |
|||
MDbuf[4] = MDbuf[0] + bb + ccc; |
|||
MDbuf[0] = ddd; |
|||
|
|||
return; |
|||
} |
|||
|
|||
void MDfinish(uint32_t *MDbuf, byte const *strptr, uint32_t lswlen, uint32_t mswlen) |
|||
{ |
|||
unsigned int i; /* counter */ |
|||
uint32_t X[16]; /* message words */ |
|||
|
|||
memset(X, 0, 16*sizeof(uint32_t)); |
|||
|
|||
/* put bytes from strptr into X */ |
|||
for (i=0; i<(lswlen&63); i++) { |
|||
/* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ |
|||
X[i>>2] ^= (uint32_t) *strptr++ << (8 * (i&3)); |
|||
} |
|||
|
|||
/* append the bit m_n == 1 */ |
|||
X[(lswlen>>2)&15] ^= (uint32_t)1 << (8*(lswlen&3) + 7); |
|||
|
|||
if ((lswlen & 63) > 55) { |
|||
/* length goes to next block */ |
|||
MDcompress(MDbuf, X); |
|||
memset(X, 0, 16*sizeof(uint32_t)); |
|||
} |
|||
|
|||
/* append length in bits*/ |
|||
X[14] = lswlen << 3; |
|||
X[15] = (lswlen >> 29) | (mswlen << 3); |
|||
MDcompress(MDbuf, X); |
|||
|
|||
return; |
|||
} |
|||
|
|||
#undef ROL |
|||
#undef F |
|||
#undef G |
|||
#undef H |
|||
#undef I |
|||
#undef J |
|||
#undef FF |
|||
#undef GG |
|||
#undef HH |
|||
#undef II |
|||
#undef JJ |
|||
#undef FFF |
|||
#undef GGG |
|||
#undef HHH |
|||
#undef III |
|||
#undef JJJ |
|||
|
|||
} |
|||
|
|||
/*
|
|||
* @returns RMD(_input) |
|||
*/ |
|||
h160 ripemd160(bytesConstRef _input) |
|||
{ |
|||
h160 hashcode; |
|||
uint32_t buffer[RMDsize / 32]; // contains (A, B, C, D(, E))
|
|||
uint32_t current[16]; // current 16-word chunk
|
|||
|
|||
// initialize
|
|||
rmd160::MDinit(buffer); |
|||
byte const* message = _input.data(); |
|||
uint32_t remaining = _input.size(); // # of bytes not yet processed
|
|||
|
|||
// process message in 16x 4-byte chunks
|
|||
for (; remaining >= 64; remaining -= 64) |
|||
{ |
|||
for (unsigned i = 0; i < 16; i++) |
|||
{ |
|||
current[i] = BYTES_TO_DWORD(message); |
|||
message += 4; |
|||
} |
|||
rmd160::MDcompress(buffer, current); |
|||
} |
|||
// length mod 64 bytes left
|
|||
|
|||
// finish:
|
|||
rmd160::MDfinish(buffer, message, _input.size(), 0); |
|||
|
|||
for (unsigned i = 0; i < RMDsize / 8; i += 4) |
|||
{ |
|||
hashcode[i] = buffer[i >> 2]; // implicit cast to byte
|
|||
hashcode[i + 1] = (buffer[i >> 2] >> 8); //extracts the 8 least
|
|||
hashcode[i + 2] = (buffer[i >> 2] >> 16); // significant bits.
|
|||
hashcode[i + 3] = (buffer[i >> 2] >> 24); |
|||
} |
|||
|
|||
return hashcode; |
|||
} |
|||
|
|||
#undef BYTES_TO_DWORD |
|||
#undef RMDsize |
|||
|
|||
} |
@ -0,0 +1,223 @@ |
|||
/*
|
|||
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 SHA3.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "SHA3.h" |
|||
#include <cstdint> |
|||
#include <cstdio> |
|||
#include <cstdlib> |
|||
#include <cstring> |
|||
#include <libdevcore/RLP.h> |
|||
#include "picosha2.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
|
|||
namespace dev |
|||
{ |
|||
|
|||
h256 EmptySHA3 = sha3(bytesConstRef()); |
|||
h256 EmptyListSHA3 = sha3(rlpList()); |
|||
|
|||
namespace keccak |
|||
{ |
|||
|
|||
/** libkeccak-tiny
|
|||
* |
|||
* A single-file implementation of SHA-3 and SHAKE. |
|||
* |
|||
* Implementor: David Leon Gil |
|||
* License: CC0, attribution kindly requested. Blame taken too, |
|||
* but not liability. |
|||
*/ |
|||
|
|||
#define decshake(bits) \ |
|||
int shake##bits(uint8_t*, size_t, const uint8_t*, size_t); |
|||
|
|||
#define decsha3(bits) \ |
|||
int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t); |
|||
|
|||
decshake(128) |
|||
decshake(256) |
|||
decsha3(224) |
|||
decsha3(256) |
|||
decsha3(384) |
|||
decsha3(512) |
|||
|
|||
/******** The Keccak-f[1600] permutation ********/ |
|||
|
|||
/*** Constants. ***/ |
|||
static const uint8_t rho[24] = \ |
|||
{ 1, 3, 6, 10, 15, 21, |
|||
28, 36, 45, 55, 2, 14, |
|||
27, 41, 56, 8, 25, 43, |
|||
62, 18, 39, 61, 20, 44}; |
|||
static const uint8_t pi[24] = \ |
|||
{10, 7, 11, 17, 18, 3, |
|||
5, 16, 8, 21, 24, 4, |
|||
15, 23, 19, 13, 12, 2, |
|||
20, 14, 22, 9, 6, 1}; |
|||
static const uint64_t RC[24] = \ |
|||
{1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, |
|||
0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, |
|||
0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, |
|||
0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, |
|||
0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, |
|||
0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; |
|||
|
|||
/*** Helper macros to unroll the permutation. ***/ |
|||
#define rol(x, s) (((x) << s) | ((x) >> (64 - s))) |
|||
#define REPEAT6(e) e e e e e e |
|||
#define REPEAT24(e) REPEAT6(e e e e) |
|||
#define REPEAT5(e) e e e e e |
|||
#define FOR5(v, s, e) \ |
|||
v = 0; \ |
|||
REPEAT5(e; v += s;) |
|||
|
|||
/*** Keccak-f[1600] ***/ |
|||
static inline void keccakf(void* state) { |
|||
uint64_t* a = (uint64_t*)state; |
|||
uint64_t b[5] = {0}; |
|||
uint64_t t = 0; |
|||
uint8_t x, y; |
|||
|
|||
for (int i = 0; i < 24; i++) { |
|||
// Theta
|
|||
FOR5(x, 1, |
|||
b[x] = 0; |
|||
FOR5(y, 5, |
|||
b[x] ^= a[x + y]; )) |
|||
FOR5(x, 1, |
|||
FOR5(y, 5, |
|||
a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) |
|||
// Rho and pi
|
|||
t = a[1]; |
|||
x = 0; |
|||
REPEAT24(b[0] = a[pi[x]]; |
|||
a[pi[x]] = rol(t, rho[x]); |
|||
t = b[0]; |
|||
x++; ) |
|||
// Chi
|
|||
FOR5(y, |
|||
5, |
|||
FOR5(x, 1, |
|||
b[x] = a[y + x];) |
|||
FOR5(x, 1, |
|||
a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) |
|||
// Iota
|
|||
a[0] ^= RC[i]; |
|||
} |
|||
} |
|||
|
|||
/******** The FIPS202-defined functions. ********/ |
|||
|
|||
/*** Some helper macros. ***/ |
|||
|
|||
#define _(S) do { S } while (0) |
|||
#define FOR(i, ST, L, S) \ |
|||
_(for (size_t i = 0; i < L; i += ST) { S; }) |
|||
#define mkapply_ds(NAME, S) \ |
|||
static inline void NAME(uint8_t* dst, \ |
|||
const uint8_t* src, \ |
|||
size_t len) { \ |
|||
FOR(i, 1, len, S); \ |
|||
} |
|||
#define mkapply_sd(NAME, S) \ |
|||
static inline void NAME(const uint8_t* src, \ |
|||
uint8_t* dst, \ |
|||
size_t len) { \ |
|||
FOR(i, 1, len, S); \ |
|||
} |
|||
|
|||
mkapply_ds(xorin, dst[i] ^= src[i]) // xorin
|
|||
mkapply_sd(setout, dst[i] = src[i]) // setout
|
|||
|
|||
#define P keccakf |
|||
#define Plen 200 |
|||
|
|||
// Fold P*F over the full blocks of an input.
|
|||
#define foldP(I, L, F) \ |
|||
while (L >= rate) { \ |
|||
F(a, I, rate); \ |
|||
P(a); \ |
|||
I += rate; \ |
|||
L -= rate; \ |
|||
} |
|||
|
|||
/** The sponge-based hash construction. **/ |
|||
static inline int hash(uint8_t* out, size_t outlen, |
|||
const uint8_t* in, size_t inlen, |
|||
size_t rate, uint8_t delim) { |
|||
if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { |
|||
return -1; |
|||
} |
|||
uint8_t a[Plen] = {0}; |
|||
// Absorb input.
|
|||
foldP(in, inlen, xorin); |
|||
// Xor in the DS and pad frame.
|
|||
a[inlen] ^= delim; |
|||
a[rate - 1] ^= 0x80; |
|||
// Xor in the last block.
|
|||
xorin(a, in, inlen); |
|||
// Apply P
|
|||
P(a); |
|||
// Squeeze output.
|
|||
foldP(out, outlen, setout); |
|||
setout(a, out, outlen); |
|||
memset(a, 0, 200); |
|||
return 0; |
|||
} |
|||
|
|||
/*** Helper macros to define SHA3 and SHAKE instances. ***/ |
|||
#define defshake(bits) \ |
|||
int shake##bits(uint8_t* out, size_t outlen, \ |
|||
const uint8_t* in, size_t inlen) { \ |
|||
return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \ |
|||
} |
|||
#define defsha3(bits) \ |
|||
int sha3_##bits(uint8_t* out, size_t outlen, \ |
|||
const uint8_t* in, size_t inlen) { \ |
|||
if (outlen > (bits/8)) { \ |
|||
return -1; \ |
|||
} \ |
|||
return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ |
|||
} |
|||
|
|||
/*** FIPS202 SHAKE VOFs ***/ |
|||
defshake(128) |
|||
defshake(256) |
|||
|
|||
/*** FIPS202 SHA3 FOFs ***/ |
|||
defsha3(224) |
|||
defsha3(256) |
|||
defsha3(384) |
|||
defsha3(512) |
|||
|
|||
} |
|||
|
|||
h256 sha3(bytesConstRef _input) |
|||
{ |
|||
// FIXME: What with unaligned memory?
|
|||
h256 ret; |
|||
keccak::sha3_256(ret.data(), 32, _input.data(), _input.size()); |
|||
// keccak::keccak(ret.data(), 32, (uint64_t const*)_input.data(), _input.size());
|
|||
return ret; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,46 @@ |
|||
/*
|
|||
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 TrieHash.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/FixedHash.h> |
|||
|
|||
namespace dev |
|||
{ |
|||
|
|||
bytes rlp256(BytesMap const& _s); |
|||
h256 hash256(BytesMap const& _s); |
|||
|
|||
h256 orderedTrieRoot(std::vector<bytes> const& _data); |
|||
|
|||
template <class T, class U> inline h256 trieRootOver(unsigned _itemCount, T const& _getKey, U const& _getValue) |
|||
{ |
|||
BytesMap m; |
|||
for (unsigned i = 0; i < _itemCount; ++i) |
|||
m[_getKey(i)] = _getValue(i); |
|||
return hash256(m); |
|||
} |
|||
|
|||
h256 orderedTrieRoot(std::vector<bytesConstRef> const& _data); |
|||
h256 orderedTrieRoot(std::vector<bytes> const& _data); |
|||
|
|||
} |
@ -0,0 +1,360 @@ |
|||
/*
|
|||
The MIT License (MIT) |
|||
|
|||
Copyright (C) 2014 okdshin |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
THE SOFTWARE. |
|||
*/ |
|||
#ifndef PICOSHA2_H |
|||
#define PICOSHA2_H |
|||
//picosha2:20140213
|
|||
#include <cstdint> |
|||
#include <iostream> |
|||
#include <vector> |
|||
#include <iterator> |
|||
#include <cassert> |
|||
#include <sstream> |
|||
#include <algorithm> |
|||
|
|||
namespace picosha2 |
|||
{ |
|||
|
|||
namespace detail |
|||
{ |
|||
|
|||
inline uint8_t mask_8bit(uint8_t x){ |
|||
return x&0xff; |
|||
} |
|||
|
|||
inline uint32_t mask_32bit(uint32_t x){ |
|||
return x&0xffffffff; |
|||
} |
|||
|
|||
static const uint32_t add_constant[64] = { |
|||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, |
|||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, |
|||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, |
|||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, |
|||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, |
|||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, |
|||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, |
|||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, |
|||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, |
|||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, |
|||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, |
|||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
|||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, |
|||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, |
|||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, |
|||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 |
|||
}; |
|||
|
|||
static const uint32_t initial_message_digest[8] = { |
|||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, |
|||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 |
|||
}; |
|||
|
|||
inline uint32_t ch(uint32_t x, uint32_t y, uint32_t z){ |
|||
return (x&y)^((~x)&z); |
|||
} |
|||
|
|||
inline uint32_t maj(uint32_t x, uint32_t y, uint32_t z){ |
|||
return (x&y)^(x&z)^(y&z); |
|||
} |
|||
|
|||
inline uint32_t rotr(uint32_t x, std::size_t n){ |
|||
assert(n < 32); |
|||
return mask_32bit((x>>n)|(x<<(32-n))); |
|||
} |
|||
|
|||
inline uint32_t bsig0(uint32_t x){ |
|||
return rotr(x, 2)^rotr(x, 13)^rotr(x, 22); |
|||
} |
|||
|
|||
inline uint32_t bsig1(uint32_t x){ |
|||
return rotr(x, 6)^rotr(x, 11)^rotr(x, 25); |
|||
} |
|||
|
|||
inline uint32_t shr(uint32_t x, std::size_t n){ |
|||
assert(n < 32); |
|||
return x >> n; |
|||
} |
|||
|
|||
inline uint32_t ssig0(uint32_t x){ |
|||
return rotr(x, 7)^rotr(x, 18)^shr(x, 3); |
|||
} |
|||
|
|||
inline uint32_t ssig1(uint32_t x){ |
|||
return rotr(x, 17)^rotr(x, 19)^shr(x, 10); |
|||
} |
|||
|
|||
template<typename RaIter1, typename RaIter2> |
|||
void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last){ |
|||
(void)last; // FIXME: check this is valid
|
|||
uint32_t w[64]; |
|||
std::fill(w, w+64, 0); |
|||
for(std::size_t i = 0; i < 16; ++i){ |
|||
w[i] = (static_cast<uint32_t>(mask_8bit(*(first+i*4)))<<24) |
|||
|(static_cast<uint32_t>(mask_8bit(*(first+i*4+1)))<<16) |
|||
|(static_cast<uint32_t>(mask_8bit(*(first+i*4+2)))<<8) |
|||
|(static_cast<uint32_t>(mask_8bit(*(first+i*4+3)))); |
|||
} |
|||
for(std::size_t i = 16; i < 64; ++i){ |
|||
w[i] = mask_32bit(ssig1(w[i-2])+w[i-7]+ssig0(w[i-15])+w[i-16]); |
|||
} |
|||
|
|||
uint32_t a = *message_digest; |
|||
uint32_t b = *(message_digest+1); |
|||
uint32_t c = *(message_digest+2); |
|||
uint32_t d = *(message_digest+3); |
|||
uint32_t e = *(message_digest+4); |
|||
uint32_t f = *(message_digest+5); |
|||
uint32_t g = *(message_digest+6); |
|||
uint32_t h = *(message_digest+7); |
|||
|
|||
for(std::size_t i = 0; i < 64; ++i){ |
|||
uint32_t temp1 = h+bsig1(e)+ch(e,f,g)+add_constant[i]+w[i]; |
|||
uint32_t temp2 = bsig0(a)+maj(a,b,c); |
|||
h = g; |
|||
g = f; |
|||
f = e; |
|||
e = mask_32bit(d+temp1); |
|||
d = c; |
|||
c = b; |
|||
b = a; |
|||
a = mask_32bit(temp1+temp2); |
|||
} |
|||
*message_digest += a; |
|||
*(message_digest+1) += b; |
|||
*(message_digest+2) += c; |
|||
*(message_digest+3) += d; |
|||
*(message_digest+4) += e; |
|||
*(message_digest+5) += f; |
|||
*(message_digest+6) += g; |
|||
*(message_digest+7) += h; |
|||
for(std::size_t i = 0; i < 8; ++i){ |
|||
*(message_digest+i) = mask_32bit(*(message_digest+i)); |
|||
} |
|||
} |
|||
|
|||
}//namespace detail
|
|||
|
|||
template<typename InIter> |
|||
void output_hex(InIter first, InIter last, std::ostream& os){ |
|||
os.setf(std::ios::hex, std::ios::basefield); |
|||
while(first != last){ |
|||
os.width(2); |
|||
os.fill('0'); |
|||
os << static_cast<unsigned int>(*first); |
|||
++first; |
|||
} |
|||
os.setf(std::ios::dec, std::ios::basefield); |
|||
} |
|||
|
|||
template<typename InIter> |
|||
void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str){ |
|||
std::ostringstream oss; |
|||
output_hex(first, last, oss); |
|||
hex_str.assign(oss.str()); |
|||
} |
|||
|
|||
template<typename InContainer> |
|||
void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str){ |
|||
bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str); |
|||
} |
|||
|
|||
template<typename InIter> |
|||
std::string bytes_to_hex_string(InIter first, InIter last){ |
|||
std::string hex_str; |
|||
bytes_to_hex_string(first, last, hex_str); |
|||
return hex_str; |
|||
} |
|||
|
|||
template<typename InContainer> |
|||
std::string bytes_to_hex_string(const InContainer& bytes){ |
|||
std::string hex_str; |
|||
bytes_to_hex_string(bytes, hex_str); |
|||
return hex_str; |
|||
} |
|||
|
|||
class hash256_one_by_one { |
|||
public: |
|||
hash256_one_by_one(){ |
|||
init(); |
|||
} |
|||
|
|||
void init(){ |
|||
buffer_.clear(); |
|||
std::fill(data_length_digits_, data_length_digits_+4, 0); |
|||
std::copy(detail::initial_message_digest, detail::initial_message_digest+8, h_); |
|||
} |
|||
|
|||
template<typename RaIter> |
|||
void process(RaIter first, RaIter last){ |
|||
add_to_data_length(std::distance(first, last)); |
|||
std::copy(first, last, std::back_inserter(buffer_)); |
|||
std::size_t i = 0; |
|||
for(;i+64 <= buffer_.size(); i+=64){ |
|||
detail::hash256_block(h_, buffer_.begin()+i, buffer_.begin()+i+64); |
|||
} |
|||
buffer_.erase(buffer_.begin(), buffer_.begin()+i); |
|||
} |
|||
|
|||
void finish(){ |
|||
uint8_t temp[64]; |
|||
std::fill(temp, temp+64, 0); |
|||
std::size_t remains = buffer_.size(); |
|||
std::copy(buffer_.begin(), buffer_.end(), temp); |
|||
temp[remains] = 0x80; |
|||
|
|||
if(remains > 55){ |
|||
std::fill(temp+remains+1, temp+64, 0); |
|||
detail::hash256_block(h_, temp, temp+64); |
|||
std::fill(temp, temp+64-4, 0); |
|||
} |
|||
else { |
|||
std::fill(temp+remains+1, temp+64-4, 0); |
|||
} |
|||
|
|||
write_data_bit_length(&(temp[56])); |
|||
detail::hash256_block(h_, temp, temp+64); |
|||
} |
|||
|
|||
template<typename OutIter> |
|||
void get_hash_bytes(OutIter first, OutIter last)const{ |
|||
for(const uint32_t* iter = h_; iter != h_+8; ++iter){ |
|||
for(std::size_t i = 0; i < 4 && first != last; ++i){ |
|||
*(first++) = detail::mask_8bit(static_cast<uint8_t>((*iter >> (24-8*i)))); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private: |
|||
void add_to_data_length(uint32_t n) { |
|||
uint32_t carry = 0; |
|||
data_length_digits_[0] += n; |
|||
for(std::size_t i = 0; i < 4; ++i) { |
|||
data_length_digits_[i] += carry; |
|||
if(data_length_digits_[i] >= 65536u) { |
|||
data_length_digits_[i] -= 65536u; |
|||
carry = 1; |
|||
} |
|||
else { |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
void write_data_bit_length(uint8_t* begin) { |
|||
uint32_t data_bit_length_digits[4]; |
|||
std::copy( |
|||
data_length_digits_, data_length_digits_+4, |
|||
data_bit_length_digits |
|||
); |
|||
|
|||
// convert byte length to bit length (multiply 8 or shift 3 times left)
|
|||
uint32_t carry = 0; |
|||
for(std::size_t i = 0; i < 4; ++i) { |
|||
uint32_t before_val = data_bit_length_digits[i]; |
|||
data_bit_length_digits[i] <<= 3; |
|||
data_bit_length_digits[i] |= carry; |
|||
data_bit_length_digits[i] &= 65535u; |
|||
carry = (before_val >> (16-3)) & 65535u; |
|||
} |
|||
|
|||
// write data_bit_length
|
|||
for(int i = 3; i >= 0; --i) { |
|||
(*begin++) = static_cast<uint8_t>(data_bit_length_digits[i] >> 8); |
|||
(*begin++) = static_cast<uint8_t>(data_bit_length_digits[i]); |
|||
} |
|||
} |
|||
std::vector<uint8_t> buffer_; |
|||
uint32_t data_length_digits_[4]; //as 64bit integer (16bit x 4 integer)
|
|||
uint32_t h_[8]; |
|||
}; |
|||
|
|||
inline void get_hash_hex_string(const hash256_one_by_one& hasher, std::string& hex_str){ |
|||
uint8_t hash[32]; |
|||
hasher.get_hash_bytes(hash, hash+32); |
|||
return bytes_to_hex_string(hash, hash+32, hex_str); |
|||
} |
|||
|
|||
inline std::string get_hash_hex_string(const hash256_one_by_one& hasher){ |
|||
std::string hex_str; |
|||
get_hash_hex_string(hasher, hex_str); |
|||
return hex_str; |
|||
} |
|||
|
|||
template<typename RaIter, typename OutIter> |
|||
void hash256(RaIter first, RaIter last, OutIter first2, OutIter last2){ |
|||
hash256_one_by_one hasher; |
|||
//hasher.init();
|
|||
hasher.process(first, last); |
|||
hasher.finish(); |
|||
hasher.get_hash_bytes(first2, last2); |
|||
} |
|||
|
|||
template<typename RaIter, typename OutContainer> |
|||
void hash256(RaIter first, RaIter last, OutContainer& dst){ |
|||
hash256(first, last, dst.begin(), dst.end()); |
|||
} |
|||
|
|||
template<typename RaContainer, typename OutIter> |
|||
void hash256(const RaContainer& src, OutIter first, OutIter last){ |
|||
hash256(src.begin(), src.end(), first, last); |
|||
} |
|||
|
|||
template<typename RaContainer, typename OutContainer> |
|||
void hash256(const RaContainer& src, OutContainer& dst){ |
|||
hash256(src.begin(), src.end(), dst.begin(), dst.end()); |
|||
} |
|||
|
|||
|
|||
template<typename RaIter> |
|||
void hash256_hex_string(RaIter first, RaIter last, std::string& hex_str){ |
|||
uint8_t hashed[32]; |
|||
hash256(first, last, hashed, hashed+32); |
|||
std::ostringstream oss; |
|||
output_hex(hashed, hashed+32, oss); |
|||
hex_str.assign(oss.str()); |
|||
} |
|||
|
|||
template<typename RaIter> |
|||
std::string hash256_hex_string(RaIter first, RaIter last){ |
|||
std::string hex_str; |
|||
hash256_hex_string(first, last, hex_str); |
|||
return hex_str; |
|||
} |
|||
|
|||
inline void hash256_hex_string(const std::string& src, std::string& hex_str){ |
|||
hash256_hex_string(src.begin(), src.end(), hex_str); |
|||
} |
|||
|
|||
template<typename RaContainer> |
|||
void hash256_hex_string(const RaContainer& src, std::string& hex_str){ |
|||
hash256_hex_string(src.begin(), src.end(), hex_str); |
|||
} |
|||
|
|||
template<typename RaContainer> |
|||
std::string hash256_hex_string(const RaContainer& src){ |
|||
return hash256_hex_string(src.begin(), src.end()); |
|||
} |
|||
|
|||
}//namespace picosha2
|
|||
|
|||
#endif //PICOSHA2_H
|
@ -1,129 +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 SHA3.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "SHA3.h" |
|||
|
|||
#include <libdevcore/RLP.h> |
|||
#include "CryptoPP.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
|
|||
namespace dev |
|||
{ |
|||
|
|||
h256 EmptySHA3 = sha3(bytesConstRef()); |
|||
h256 EmptyListSHA3 = sha3(rlpList()); |
|||
|
|||
std::string sha3(std::string const& _input, bool _hex) |
|||
{ |
|||
if (!_hex) |
|||
{ |
|||
string ret(32, '\0'); |
|||
sha3(bytesConstRef((byte const*)_input.data(), _input.size()), bytesRef((byte*)ret.data(), 32)); |
|||
return ret; |
|||
} |
|||
|
|||
uint8_t buf[32]; |
|||
sha3(bytesConstRef((byte const*)_input.data(), _input.size()), bytesRef((byte*)&(buf[0]), 32)); |
|||
std::string ret(64, '\0'); |
|||
for (unsigned int i = 0; i < 32; i++) |
|||
sprintf((char*)(ret.data())+i*2, "%02x", buf[i]); |
|||
return ret; |
|||
} |
|||
|
|||
void sha3(bytesConstRef _input, bytesRef _output) |
|||
{ |
|||
CryptoPP::SHA3_256 ctx; |
|||
ctx.Update((byte*)_input.data(), _input.size()); |
|||
assert(_output.size() >= 32); |
|||
ctx.Final(_output.data()); |
|||
} |
|||
|
|||
void ripemd160(bytesConstRef _input, bytesRef _output) |
|||
{ |
|||
CryptoPP::RIPEMD160 ctx; |
|||
ctx.Update((byte*)_input.data(), _input.size()); |
|||
assert(_output.size() >= 32); |
|||
ctx.Final(_output.data()); |
|||
} |
|||
|
|||
void sha256(bytesConstRef _input, bytesRef _output) |
|||
{ |
|||
CryptoPP::SHA256 ctx; |
|||
ctx.Update((byte*)_input.data(), _input.size()); |
|||
assert(_output.size() >= 32); |
|||
ctx.Final(_output.data()); |
|||
} |
|||
|
|||
bytes sha3Bytes(bytesConstRef _input) |
|||
{ |
|||
bytes ret(32); |
|||
sha3(_input, &ret); |
|||
return ret; |
|||
} |
|||
|
|||
h256 sha3(bytesConstRef _input) |
|||
{ |
|||
h256 ret; |
|||
sha3(_input, bytesRef(&ret[0], 32)); |
|||
return ret; |
|||
} |
|||
|
|||
void sha3mac(bytesConstRef _secret, bytesConstRef _plain, bytesRef _output) |
|||
{ |
|||
CryptoPP::SHA3_256 ctx; |
|||
assert(_secret.size() > 0); |
|||
ctx.Update((byte*)_secret.data(), _secret.size()); |
|||
ctx.Update((byte*)_plain.data(), _plain.size()); |
|||
assert(_output.size() >= 32); |
|||
ctx.Final(_output.data()); |
|||
} |
|||
|
|||
bytes aesDecrypt(bytesConstRef _ivCipher, std::string const& _password, unsigned _rounds, bytesConstRef _salt) |
|||
{ |
|||
bytes pw = asBytes(_password); |
|||
|
|||
if (!_salt.size()) |
|||
_salt = &pw; |
|||
|
|||
bytes target(64); |
|||
CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA256>().DeriveKey(target.data(), target.size(), 0, pw.data(), pw.size(), _salt.data(), _salt.size(), _rounds); |
|||
|
|||
try |
|||
{ |
|||
CryptoPP::AES::Decryption aesDecryption(target.data(), 16); |
|||
auto cipher = _ivCipher.cropped(16); |
|||
auto iv = _ivCipher.cropped(0, 16); |
|||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data()); |
|||
std::string decrypted; |
|||
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decrypted)); |
|||
stfDecryptor.Put(cipher.data(), cipher.size()); |
|||
stfDecryptor.MessageEnd(); |
|||
return asBytes(decrypted); |
|||
} |
|||
catch (exception const& e) |
|||
{ |
|||
cerr << e.what() << endl; |
|||
return bytes(); |
|||
} |
|||
} |
|||
|
|||
} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue