Browse Source

Remove abi, ethkey and rlp tools.

cl-refactor
Paweł Bylica 9 years ago
parent
commit
2b51198dd3
  1. 16
      CMakeLists.txt
  2. 19
      abi/CMakeLists.txt
  3. 769
      abi/main.cpp
  4. 33
      ethkey/CMakeLists.txt
  5. 769
      ethkey/KeyAux.h
  6. 84
      ethkey/main.cpp
  7. 19
      ethvm/CMakeLists.txt
  8. 224
      ethvm/main.cpp
  9. 21
      rlp/CMakeLists.txt
  10. 394
      rlp/main.cpp

16
CMakeLists.txt

@ -60,7 +60,6 @@ set(D_PROFILING OFF)
set(D_ROCKSDB OFF)
set(D_OLYMPIC OFF)
set(D_MINER ON)
set(D_ETHKEY ON)
if (BUNDLE STREQUAL "minimal")
set(D_SERPENT OFF)
@ -108,7 +107,6 @@ elseif (BUNDLE STREQUAL "wallet")
set(D_GUI OFF)
set(D_TOOLS OFF)
set(D_TESTS OFF)
set(D_ETHKEY ON)
set(D_MINER OFF)
set(D_ETHASHCL OFF)
set(D_FATDB OFF)
@ -121,7 +119,6 @@ elseif (BUNDLE STREQUAL "miner")
set(D_GUI OFF)
set(D_TOOLS OFF)
set(D_TESTS OFF)
set(D_ETHKEY OFF)
set(D_MINER ON)
set(D_ETHASHCL ON)
set(D_FATDB OFF)
@ -134,7 +131,6 @@ elseif (BUNDLE STREQUAL "cudaminer")
set(D_GUI OFF)
set(D_TOOLS OFF)
set(D_TESTS OFF)
set(D_ETHKEY OFF)
set(D_MINER ON)
set(D_ETHASHCL ON)
set(D_ETHASHCUDA ON)
@ -309,7 +305,6 @@ eth_format_option(GUI)
eth_format_option(TESTS)
eth_format_option(ROCKSDB)
eth_format_option(TOOLS)
eth_format_option(ETHKEY)
eth_format_option(ETHASHCL)
eth_format_option(ETHASHCUDA)
eth_format_option(JSCONSOLE)
@ -356,7 +351,6 @@ message("-- ROCKSDB Prefer rocksdb to leveldb ${ROCKSDB}
message("-- OLYMPIC Default to the Olympic network ${OLYMPIC}")
message("------------------------------------------------------------- components")
message("-- MINER Build miner ${MINER}")
message("-- ETHKEY Build wallet tools ${ETHKEY}")
message("-- TOOLS Build basic tools ${TOOLS}")
message("-- SERPENT Build Serpent language components ${SERPENT}")
message("-- GUI Build GUI components ${GUI}")
@ -467,16 +461,6 @@ if (MINER OR TOOLS)
add_subdirectory(ethminer)
endif ()
if (ETHKEY OR TOOLS)
add_subdirectory(ethkey)
endif ()
if (TOOLS)
add_subdirectory(rlp)
add_subdirectory(abi)
add_subdirectory(ethvm)
endif()
if (GUI)
add_subdirectory(libnatspec)
add_subdirectory(libjsqrc)

19
abi/CMakeLists.txt

@ -1,19 +0,0 @@
cmake_policy(SET CMP0015 NEW)
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${DB_INCLUDE_DIRS})
set(EXECUTABLE abi)
add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} ethereum)
if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

769
abi/main.cpp

@ -1,769 +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 main.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* RLP tool.
*/
#include <fstream>
#include <iostream>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include "../test/JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libdevcore/RLP.h>
#include <libdevcore/SHA3.h>
#include <libethereum/Client.h>
using namespace std;
using namespace dev;
namespace js = json_spirit;
void help()
{
cout
<< "Usage abi enc <method_name> (<arg1>, (<arg2>, ... ))" << endl
<< " abi enc -a <abi.json> <method_name> (<arg1>, (<arg2>, ... ))" << endl
<< " abi dec -a <abi.json> [ <signature> | <unique_method_name> ]" << endl
<< "Options:" << endl
<< " -a,--abi-file <filename> Specify the JSON ABI file." << endl
<< " -h,--help Print this help message and exit." << endl
<< " -V,--version Show the version and exit." << endl
<< "Input options:" << endl
<< " -f,--format-prefix Require all input formats to be prefixed e.g. 0x for hex, + for decimal, ' for binary." << endl
<< " -F,--no-format-prefix Require no input format to be prefixed." << endl
<< " -t,--typing Require all arguments to be typed e.g. b32: (bytes32), u64: (uint64), b[]: (byte[]), i: (int256)." << endl
<< " -T,--no-typing Require no arguments to be typed." << endl
<< "Output options:" << endl
<< " -i,--index <n> Output only the nth (counting from 0) return value." << endl
<< " -d,--decimal All data should be displayed as decimal." << endl
<< " -x,--hex Display all data as hex." << endl
<< " -b,--binary Display all data as binary." << endl
<< " -p,--prefix Prefix by a base identifier." << endl
;
exit(0);
}
void version()
{
cout << "abi version " << dev::Version << endl;
exit(0);
}
enum class Mode
{
Encode,
Decode
};
enum class Encoding
{
Auto,
Decimal,
Hex,
Binary,
};
enum class Tristate
{
False = false,
True = true,
Mu
};
enum class Format
{
Binary,
Hex,
Decimal,
Open,
Close
};
struct InvalidUserString: public Exception {};
struct InvalidFormat: public Exception {};
enum class Base
{
Unknown,
Bytes,
Address,
Int,
Uint,
Fixed
};
static const map<Base, string> s_bases =
{
{ Base::Bytes, "bytes" },
{ Base::Address, "address" },
{ Base::Int, "int" },
{ Base::Uint, "uint" },
{ Base::Fixed, "fixed" }
};
struct EncodingPrefs
{
Encoding e = Encoding::Auto;
bool prefix = true;
};
struct ABIType
{
Base base = Base::Unknown;
unsigned size = 32;
unsigned ssize = 0;
vector<int> dims;
string name;
ABIType() = default;
ABIType(std::string const& _type, std::string const& _name):
name(_name)
{
string rest;
for (auto const& i: s_bases)
if (boost::algorithm::starts_with(_type, i.second))
{
base = i.first;
rest = _type.substr(i.second.size());
}
if (base == Base::Unknown)
throw InvalidFormat();
boost::regex r("(\\d*)(x(\\d+))?((\\[\\d*\\])*)");
boost::smatch res;
boost::regex_match(rest, res, r);
size = res[1].length() > 0 ? stoi(res[1]) : 0;
ssize = res[3].length() > 0 ? stoi(res[3]) : 0;
boost::regex r2("\\[(\\d*)\\](.*)");
for (rest = res[4]; boost::regex_match(rest, res, r2); rest = res[2])
dims.push_back(!res[1].length() ? -1 : stoi(res[1]));
}
ABIType(std::string const& _s)
{
if (_s.size() < 1)
return;
switch (_s[0])
{
case 'b': base = Base::Bytes; break;
case 'a': base = Base::Address; break;
case 'i': base = Base::Int; break;
case 'u': base = Base::Uint; break;
case 'f': base = Base::Fixed; break;
default: throw InvalidFormat();
}
if (_s.size() < 2)
{
if (base == Base::Fixed)
size = ssize = 16;
else if (base == Base::Address || base == Base::Bytes)
size = 0;
else
size = 32;
return;
}
strings d;
boost::algorithm::split(d, _s, boost::is_any_of("*"));
string s = d[0];
if (s.find_first_of('x') == string::npos)
size = stoi(s.substr(1));
else
{
size = stoi(s.substr(1, s.find_first_of('x') - 1));
ssize = stoi(s.substr(s.find_first_of('x') + 1));
}
for (unsigned i = 1; i < d.size(); ++i)
if (d[i].empty())
dims.push_back(-1);
else
dims.push_back(stoi(d[i]));
}
string canon() const
{
string ret;
switch (base)
{
case Base::Bytes: ret = "bytes" + (size > 0 ? toString(size) : ""); break;
case Base::Address: ret = "address"; break;
case Base::Int: ret = "int" + toString(size); break;
case Base::Uint: ret = "uint" + toString(size); break;
case Base::Fixed: ret = "fixed" + toString(size) + "x" + toString(ssize); break;
default: throw InvalidFormat();
}
for (int i: dims)
ret += "[" + ((i > -1) ? toString(i) : "") + "]";
return ret;
}
bool isBytes() const { return base == Base::Bytes && !size; }
string render(bytes const& _data, EncodingPrefs _e) const
{
if (base == Base::Uint || base == Base::Int)
{
if (_e.e == Encoding::Hex)
return (_e.prefix ? "0x" : "") + toHex(toCompactBigEndian(fromBigEndian<bigint>(bytesConstRef(&_data).cropped(32 - size / 8))));
else
{
bigint i = fromBigEndian<bigint>(bytesConstRef(&_data).cropped(32 - size / 8));
if (base == Base::Int && i > (bigint(1) << (size - 1)))
i -= (bigint(1) << size);
return toString(i);
}
}
else if (base == Base::Address)
{
Address a = Address(h256(_data), Address::AlignRight);
return _e.e == Encoding::Binary ? asString(a.asBytes()) : ((_e.prefix ? "0x" : "") + toString(a));
}
else if (isBytes())
{
return _e.e == Encoding::Binary ? asString(_data) : ((_e.prefix ? "0x" : "") + toHex(_data));
}
else if (base == Base::Bytes)
{
bytesConstRef b(&_data);
b = b.cropped(0, size);
return _e.e == Encoding::Binary ? asString(b) : ((_e.prefix ? "0x" : "") + toHex(b));
}
else
throw InvalidFormat();
}
bytes unrender(bytes const& _data, Format _f) const
{
if (isBytes())
{
auto ret = _data;
while (ret.size() % 32 != 0)
ret.push_back(0);
return ret;
}
else
return aligned(_data, _f, 32);
}
void noteHexInput(unsigned _nibbles) { if (base == Base::Unknown) { if (_nibbles == 40) base = Base::Address; else { base = Base::Bytes; size = _nibbles / 2; } } }
void noteBinaryInput() { if (base == Base::Unknown) { base = Base::Bytes; size = 32; } }
void noteDecimalInput() { if (base == Base::Unknown) { base = Base::Uint; size = 32; } }
bytes aligned(bytes const& _b, Format _f, unsigned _length) const
{
bytes ret = _b;
while (ret.size() < _length)
if (base == Base::Bytes || (base == Base::Unknown && _f == Format::Binary))
ret.push_back(0);
else
ret.insert(ret.begin(), 0);
while (ret.size() > _length)
if (base == Base::Bytes || (base == Base::Unknown && _f == Format::Binary))
ret.pop_back();
else
ret.erase(ret.begin());
return ret;
}
};
tuple<bytes, ABIType, Format> fromUser(std::string const& _arg, Tristate _prefix, Tristate _typing)
{
ABIType type;
string val;
if (_typing == Tristate::True || (_typing == Tristate::Mu && _arg.find(':') != string::npos))
{
if (_arg.find(':') == string::npos)
throw InvalidUserString();
type = ABIType(_arg.substr(0, _arg.find(':')));
val = _arg.substr(_arg.find(':') + 1);
}
else
val = _arg;
if (_prefix != Tristate::False)
{
if (val.substr(0, 2) == "0x")
{
type.noteHexInput(val.size() - 2);
return make_tuple(fromHex(val), type, Format::Hex);
}
if (val.substr(0, 1) == "+")
{
type.noteDecimalInput();
return make_tuple(toCompactBigEndian(bigint(val.substr(1))), type, Format::Decimal);
}
if (val.substr(0, 1) == "'")
{
type.noteBinaryInput();
return make_tuple(asBytes(val.substr(1)), type, Format::Binary);
}
if (val == "[")
return make_tuple(bytes(), type, Format::Open);
if (val == "]")
return make_tuple(bytes(), type, Format::Close);
}
if (_prefix != Tristate::True)
{
if (val.find_first_not_of("0123456789") == string::npos)
{
type.noteDecimalInput();
return make_tuple(toCompactBigEndian(bigint(val)), type, Format::Decimal);
}
if (val.find_first_not_of("0123456789abcdefABCDEF") == string::npos)
{
type.noteHexInput(val.size());
return make_tuple(fromHex(val), type, Format::Hex);
}
if (val == "[")
return make_tuple(bytes(), type, Format::Open);
if (val == "]")
return make_tuple(bytes(), type, Format::Close);
type.noteBinaryInput();
return make_tuple(asBytes(val), type, Format::Binary);
}
throw InvalidUserString();
}
struct ExpectedAdditionalParameter: public Exception {};
struct ExpectedOpen: public Exception {};
struct ExpectedClose: public Exception {};
struct ABIMethod
{
string name;
vector<ABIType> ins;
vector<ABIType> outs;
bool isConstant = false;
// isolation *IS* documentation.
ABIMethod() = default;
ABIMethod(js::mObject _o)
{
name = _o["name"].get_str();
isConstant = _o["constant"].get_bool();
if (_o.count("inputs"))
for (auto const& i: _o["inputs"].get_array())
{
js::mObject a = i.get_obj();
ins.push_back(ABIType(a["type"].get_str(), a["name"].get_str()));
}
if (_o.count("outputs"))
for (auto const& i: _o["outputs"].get_array())
{
js::mObject a = i.get_obj();
outs.push_back(ABIType(a["type"].get_str(), a["name"].get_str()));
}
}
ABIMethod(string const& _name, vector<ABIType> const& _args)
{
name = _name;
ins = _args;
}
string sig() const
{
string methodArgs;
for (auto const& arg: ins)
methodArgs += (methodArgs.empty() ? "" : ",") + arg.canon();
return name + "(" + methodArgs + ")";
}
FixedHash<4> id() const { return FixedHash<4>(sha3(sig())); }
std::string solidityDeclaration() const
{
ostringstream ss;
ss << "function " << name << "(";
int f = 0;
for (ABIType const& i: ins)
ss << (f++ ? ", " : "") << i.canon() << " " << i.name;
ss << ") ";
if (isConstant)
ss << "constant ";
if (!outs.empty())
{
ss << "returns(";
f = 0;
for (ABIType const& i: outs)
ss << (f++ ? ", " : "") << i.canon() << " " << i.name;
ss << ")";
}
return ss.str();
}
bytes encode(vector<pair<bytes, Format>> const& _params) const
{
bytes ret = name.empty() ? bytes() : id().asBytes();
bytes suffix;
// int int[] int
// example: 42 [ 1 2 3 ] 69
// int[2][][3]
// example: [ [ [ 1 2 3 ] [ 4 5 6 ] ] [ ] ]
unsigned pi = 0;
for (ABIType const& a: ins)
{
if (pi >= _params.size())
throw ExpectedAdditionalParameter();
auto put = [&]() {
if (a.isBytes())
ret += h256(u256(_params[pi].first.size())).asBytes();
suffix += a.unrender(_params[pi].first, _params[pi].second);
pi++;
if (pi >= _params.size())
throw ExpectedAdditionalParameter();
};
function<void(vector<int>, unsigned)> putDim = [&](vector<int> addr, unsigned q) {
if (addr.size() == a.dims.size())
put();
else
{
if (_params[pi].second != Format::Open)
throw ExpectedOpen();
++pi;
int l = a.dims[a.dims.size() - 1 - addr.size()];
if (l == -1)
{
// read ahead in params and discover the arity.
unsigned depth = 0;
l = 0;
for (unsigned pi2 = pi; depth || _params[pi2].second != Format::Close;)
{
if (_params[pi2].second == Format::Open)
++depth;
if (_params[pi2].second == Format::Close)
--depth;
if (!depth)
++l;
if (++pi2 == _params.size())
throw ExpectedClose();
}
ret += h256(u256(l)).asBytes();
}
q *= l;
for (addr.push_back(0); addr.back() < l; ++addr.back())
putDim(addr, q);
if (_params[pi].second != Format::Close)
throw ExpectedClose();
++pi;
}
};
putDim(vector<int>(), 1);
}
return ret + suffix;
}
string decode(bytes const& _data, int _index, EncodingPrefs _ep)
{
stringstream out;
unsigned di = 0;
vector<unsigned> catDims;
for (ABIType const& a: outs)
{
auto put = [&]() {
if (a.isBytes())
{
catDims.push_back(fromBigEndian<unsigned>(bytesConstRef(&_data).cropped(di, 32)));
di += 32;
}
};
function<void(vector<int>, unsigned)> putDim = [&](vector<int> addr, unsigned q) {
if (addr.size() == a.dims.size())
put();
else
{
int l = a.dims[a.dims.size() - 1 - addr.size()];
if (l == -1)
{
l = fromBigEndian<unsigned>(bytesConstRef(&_data).cropped(di, 32));
catDims.push_back(l);
di += 32;
}
q *= l;
for (addr.push_back(0); addr.back() < l; ++addr.back())
putDim(addr, q);
}
};
putDim(vector<int>(), 1);
}
unsigned d = 0;
for (ABIType const& a: outs)
{
if (_index == -1 && out.tellp() > 0)
out << ", ";
auto put = [&]() {
if (a.isBytes())
{
out << a.render(bytesConstRef(&_data).cropped(di, catDims[d]).toBytes(), _ep);
di += ((catDims[d] + 31) / 32) * 32;
d++;
}
else
{
out << a.render(bytesConstRef(&_data).cropped(di, 32).toBytes(), _ep);
di += 32;
}
};
function<void(vector<int>)> putDim = [&](vector<int> addr) {
if (addr.size() == a.dims.size())
put();
else
{
out << "[";
addr.push_back(0);
int l = a.dims[a.dims.size() - 1 - (addr.size() - 1)];
if (l == -1)
l = catDims[d++];
for (addr.back() = 0; addr.back() < l; ++addr.back())
{
if (addr.back())
out << ", ";
putDim(addr);
}
out << "]";
}
};
putDim(vector<int>());
}
return out.str();
}
};
string canonSig(string const& _name, vector<ABIType> const& _args)
{
try {
string methodArgs;
for (auto const& arg: _args)
methodArgs += (methodArgs.empty() ? "" : ",") + arg.canon();
return _name + "(" + methodArgs + ")";
}
catch (...) {
return string();
}
}
struct UnknownMethod: public Exception {};
struct OverloadedMethod: public Exception {};
class ABI
{
public:
ABI() = default;
ABI(std::string const& _json)
{
js::mValue v;
js::read_string(_json, v);
for (auto const& i: v.get_array())
{
js::mObject o = i.get_obj();
if (o["type"].get_str() != "function")
continue;
ABIMethod m(o);
m_methods[m.id()] = m;
}
}
ABIMethod method(string _nameOrSig, vector<ABIType> const& _args) const
{
auto id = FixedHash<4>(sha3(_nameOrSig));
if (!m_methods.count(id))
id = FixedHash<4>(sha3(canonSig(_nameOrSig, _args)));
if (!m_methods.count(id))
for (auto const& m: m_methods)
if (m.second.name == _nameOrSig)
{
if (m_methods.count(id))
throw OverloadedMethod();
id = m.first;
}
if (m_methods.count(id))
return m_methods.at(id);
throw UnknownMethod();
}
friend ostream& operator<<(ostream& _out, ABI const& _abi);
private:
map<FixedHash<4>, ABIMethod> m_methods;
};
ostream& operator<<(ostream& _out, ABI const& _abi)
{
_out << "contract {" << endl;
for (auto const& i: _abi.m_methods)
_out << " " << i.second.solidityDeclaration() << "; // " << i.first.abridged() << endl;
_out << "}" << endl;
return _out;
}
void userOutput(ostream& _out, bytes const& _data, Encoding _e)
{
switch (_e)
{
case Encoding::Binary:
_out.write((char const*)_data.data(), _data.size());
break;
default:
_out << toHex(_data) << endl;
}
}
template <unsigned n, class T> vector<typename std::remove_reference<decltype(get<n>(T()))>::type> retrieve(vector<T> const& _t)
{
vector<typename std::remove_reference<decltype(get<n>(T()))>::type> ret;
for (T const& i: _t)
ret.push_back(get<n>(i));
return ret;
}
int main(int argc, char** argv)
{
Encoding encoding = Encoding::Auto;
Mode mode = Mode::Encode;
string abiFile;
string method;
Tristate formatPrefix = Tristate::Mu;
Tristate typePrefix = Tristate::Mu;
EncodingPrefs prefs;
bool verbose = false;
int outputIndex = -1;
vector<pair<bytes, Format>> params;
vector<ABIType> args;
string incoming;
for (int i = 1; i < argc; ++i)
{
string arg = argv[i];
if (arg == "-h" || arg == "--help")
help();
else if (arg == "enc" && i == 1)
mode = Mode::Encode;
else if (arg == "dec" && i == 1)
mode = Mode::Decode;
else if ((arg == "-a" || arg == "--abi") && argc > i)
abiFile = argv[++i];
else if ((arg == "-i" || arg == "--index") && argc > i)
outputIndex = atoi(argv[++i]);
else if (arg == "-p" || arg == "--prefix")
prefs.prefix = true;
else if (arg == "-f" || arg == "--format-prefix")
formatPrefix = Tristate::True;
else if (arg == "-F" || arg == "--no-format-prefix")
formatPrefix = Tristate::False;
else if (arg == "-t" || arg == "--typing")
typePrefix = Tristate::True;
else if (arg == "-T" || arg == "--no-typing")
typePrefix = Tristate::False;
else if (arg == "-x" || arg == "--hex")
prefs.e = Encoding::Hex;
else if (arg == "-d" || arg == "--decimal" || arg == "--dec")
prefs.e = Encoding::Decimal;
else if (arg == "-b" || arg == "--binary" || arg == "--bin")
prefs.e = Encoding::Binary;
else if (arg == "-v" || arg == "--verbose")
verbose = true;
else if (arg == "-V" || arg == "--version")
version();
else if (method.empty())
method = arg;
else if (mode == Mode::Encode)
{
auto u = fromUser(arg, formatPrefix, typePrefix);
args.push_back(get<1>(u));
params.push_back(make_pair(get<0>(u), get<2>(u)));
}
else if (mode == Mode::Decode)
incoming += arg;
}
string abiData;
if (!abiFile.empty())
abiData = contentsString(abiFile);
if (mode == Mode::Encode)
{
ABIMethod m;
if (abiData.empty())
m = ABIMethod(method, args);
else
{
ABI abi(abiData);
if (verbose)
cerr << "ABI:" << endl << abi;
try {
m = abi.method(method, args);
}
catch (...)
{
cerr << "Unknown method in ABI." << endl;
exit(-1);
}
}
try {
userOutput(cout, m.encode(params), encoding);
}
catch (ExpectedAdditionalParameter const&)
{
cerr << "Expected additional parameter in input." << endl;
exit(-1);
}
catch (ExpectedOpen const&)
{
cerr << "Expected open-bracket '[' in input." << endl;
exit(-1);
}
catch (ExpectedClose const&)
{
cerr << "Expected close-bracket ']' in input." << endl;
exit(-1);
}
}
else if (mode == Mode::Decode)
{
if (abiData.empty())
{
cerr << "Please specify an ABI file." << endl;
exit(-1);
}
else
{
ABI abi(abiData);
ABIMethod m;
if (verbose)
cerr << "ABI:" << endl << abi;
try {
m = abi.method(method, args);
}
catch(...)
{
cerr << "Unknown method in ABI." << endl;
exit(-1);
}
string encoded;
if (incoming == "--" || incoming.empty())
for (int i = cin.get(); i != -1; i = cin.get())
encoded.push_back((char)i);
else
{
encoded = contentsString(incoming);
}
cout << m.decode(fromHex(boost::trim_copy(encoded)), outputIndex, prefs) << endl;
}
}
return 0;
}

33
ethkey/CMakeLists.txt

@ -1,33 +0,0 @@
cmake_policy(SET CMP0015 NEW)
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
if (JSCONSOLE)
include_directories(${V8_INCLUDE_DIRS})
endif()
set(EXECUTABLE ethkey)
file(GLOB HEADERS "*.h")
add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS})
add_dependencies(${EXECUTABLE} BuildInfo.h)
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} ethcore)
if (DEFINED WIN32 AND NOT DEFINED CMAKE_COMPILER_IS_MINGW)
eth_copy_dlls("${EXECUTABLE}" MHD_DLLS)
endif()
if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

769
ethkey/KeyAux.h

@ -1,769 +0,0 @@
#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 KeyAux.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* CLI module for key management.
*/
#include <thread>
#include <chrono>
#include <fstream>
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/trim_all.hpp>
#include <libdevcore/SHA3.h>
#include <libdevcore/FileSystem.h>
#include <libethcore/KeyManager.h>
#include <libethcore/ICAP.h>
#include <libethcore/Transaction.h>
#include <libdevcrypto/WordList.h>
#include "BuildInfo.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
using namespace boost::algorithm;
#undef RETURN
class BadArgument: public Exception {};
string getAccountPassword(KeyManager& keyManager, Address const& a)
{
return getPassword("Enter password for address " + keyManager.accountName(a) + " (" + a.abridged() + "; hint:" + keyManager.passwordHint(a) + "): ");
}
string createPassword(std::string const& _prompt)
{
string ret;
while (true)
{
ret = getPassword(_prompt);
string confirm = getPassword("Please confirm the password by entering it again: ");
if (ret == confirm)
break;
cout << "Passwords were different. Try again." << endl;
}
return ret;
// cout << "Enter a hint to help you remember this password: " << flush;
// cin >> hint;
// return make_pair(ret, hint);
}
pair<string, string> createPassword(KeyManager& _keyManager, std::string const& _prompt, std::string const& _pass = std::string(), std::string const& _hint = std::string())
{
string pass = _pass;
if (pass.empty())
while (true)
{
pass = getPassword(_prompt);
string confirm = getPassword("Please confirm the password by entering it again: ");
if (pass == confirm)
break;
cout << "Passwords were different. Try again." << endl;
}
string hint = _hint;
if (hint.empty() && !pass.empty() && !_keyManager.haveHint(pass))
{
cout << "Enter a hint to help you remember this password: " << flush;
getline(cin, hint);
}
return make_pair(pass, hint);
}
class KeyCLI
{
public:
enum class OperationMode
{
None,
ListBare,
NewBare,
ImportBare,
ExportBare,
RecodeBare,
KillBare,
InspectBare,
CreateWallet,
List,
New,
Import,
ImportWithAddress,
ImportPresale,
Export,
Recode,
Kill,
NewBrain,
ImportBrain,
InspectBrain,
SignTx,
DecodeTx,
};
KeyCLI(OperationMode _mode = OperationMode::None): m_mode(_mode) {}
bool interpretOption(int& i, int argc, char** argv)
{
string arg = argv[i];
if (arg == "--wallet-path" && i + 1 < argc)
m_walletPath = argv[++i];
else if (arg == "--secrets-path" && i + 1 < argc)
m_secretsPath = argv[++i];
else if ((arg == "-m" || arg == "--master") && i + 1 < argc)
m_masterPassword = argv[++i];
else if (arg == "--unlock" && i + 1 < argc)
m_unlocks.push_back(argv[++i]);
else if (arg == "--lock" && i + 1 < argc)
m_lock = argv[++i];
else if (arg == "--kdf" && i + 1 < argc)
m_kdf = argv[++i];
else if (arg == "--kdf-param" && i + 2 < argc)
{
auto n = argv[++i];
auto v = argv[++i];
m_kdfParams[n] = v;
}
else if (arg == "--sign-tx" && i + 1 < argc)
{
m_mode = OperationMode::SignTx;
m_signKey = argv[++i];
}
else if (arg == "--tx-data" && i + 1 < argc)
try
{
m_toSign.data = fromHex(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--tx-nonce" && i + 1 < argc)
try
{
m_toSign.nonce = u256(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if ((arg == "--tx-dest" || arg == "--tx-to" || arg == "--tx-destination") && i + 1 < argc)
try
{
m_toSign.creation = false;
m_toSign.to = toAddress(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--tx-gas" && i + 1 < argc)
try
{
m_toSign.gas = u256(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--tx-gasprice" && i + 1 < argc)
try
{
m_toSign.gasPrice = u256(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--tx-value" && i + 1 < argc)
try
{
m_toSign.value = u256(argv[++i]);
}
catch (...)
{
cerr << "Invalid argument to " << arg << endl;
exit(-1);
}
else if (arg == "--decode-tx")
m_mode = OperationMode::DecodeTx;
else if (arg == "--import-bare")
m_mode = OperationMode::ImportBare;
else if (arg == "--list-bare")
m_mode = OperationMode::ListBare;
else if (arg == "--export-bare")
m_mode = OperationMode::ExportBare;
else if (arg == "--inspect-bare")
m_mode = OperationMode::InspectBare;
else if (arg == "--recode-bare")
m_mode = OperationMode::RecodeBare;
else if (arg == "--kill-bare")
m_mode = OperationMode::KillBare;
else if (arg == "--create-wallet")
m_mode = OperationMode::CreateWallet;
else if (arg == "-l" || arg == "--list")
m_mode = OperationMode::List;
else if ((arg == "-n" || arg == "--new") && i + 1 < argc)
{
m_mode = OperationMode::New;
m_name = argv[++i];
}
else if ((arg == "-i" || arg == "--import") && i + 2 < argc)
{
m_mode = OperationMode::Import;
m_inputs = strings(1, argv[++i]);
m_name = argv[++i];
}
else if (arg == "--import-presale" && i + 2 < argc)
{
m_mode = OperationMode::ImportPresale;
m_inputs = strings(1, argv[++i]);
m_name = argv[++i];
}
else if (arg == "--new-brain" && i + 1 < argc)
{
m_mode = OperationMode::NewBrain;
m_name = argv[++i];
}
else if (arg == "--import-brain" && i + 1 < argc)
{
m_mode = OperationMode::ImportBrain;
m_name = argv[++i];
}
else if (arg == "--inspect-brain")
m_mode = OperationMode::InspectBrain;
else if (arg == "--import-with-address" && i + 3 < argc)
{
m_mode = OperationMode::ImportWithAddress;
m_inputs = strings(1, argv[++i]);
m_address = Address(argv[++i]);
m_name = argv[++i];
}
else if (arg == "--export")
m_mode = OperationMode::Export;
else if (arg == "--recode")
m_mode = OperationMode::Recode;
else if (arg == "--no-icap")
m_icap = false;
else if (m_mode == OperationMode::DecodeTx || m_mode == OperationMode::SignTx || m_mode == OperationMode::ImportBare || m_mode == OperationMode::InspectBare || m_mode == OperationMode::KillBare || m_mode == OperationMode::Recode || m_mode == OperationMode::Export || m_mode == OperationMode::RecodeBare || m_mode == OperationMode::ExportBare)
m_inputs.push_back(arg);
else
return false;
return true;
}
KeyPair makeKey() const
{
KeyPair k(Secret::random());
while (m_icap && k.address()[0])
k = KeyPair(Secret(sha3(k.secret().ref())));
return k;
}
Secret getSecret(std::string const& _signKey)
{
string json = contentsString(_signKey);
if (!json.empty())
return Secret(secretStore().secret(secretStore().readKeyContent(json), [&](){ return getPassword("Enter password for key: "); }));
else
{
if (h128 u = fromUUID(_signKey))
return Secret(secretStore().secret(u, [&](){ return getPassword("Enter password for key: "); }));
if (_signKey.substr(0, 6) == "brain#" && _signKey.find(":") != string::npos)
return KeyManager::subkey(KeyManager::brain(_signKey.substr(_signKey.find(":"))), stoul(_signKey.substr(6, _signKey.find(":") - 7)));
if (_signKey.substr(0, 6) == "brain:")
return KeyManager::brain(_signKey.substr(6));
if (_signKey == "brain")
return KeyManager::brain(getPassword("Enter brain wallet phrase: "));
Address a;
DEV_IGNORE_EXCEPTIONS(a = Address(_signKey));
if (a)
return keyManager().secret(a, [&](){ return getPassword("Enter password for key (hint:" + keyManager().passwordHint(a) + "): "); });
cerr << "Bad file, UUID and address: " << _signKey << endl;
exit(-1);
}
}
void execute()
{
switch (m_mode)
{
case OperationMode::CreateWallet:
{
KeyManager wallet(m_walletPath, m_secretsPath);
if (m_masterPassword.empty())
m_masterPassword = createPassword("Please enter a MASTER password to protect your key store (make it strong!): ");
if (m_masterPassword.empty())
cerr << "Aborted (empty password not allowed)." << endl;
else
{
try
{
wallet.create(m_masterPassword);
}
catch (Exception const& _e)
{
cerr << "unable to create wallet" << endl << boost::diagnostic_information(_e);
}
}
break;
}
case OperationMode::DecodeTx:
{
bytes b = inputData(m_inputs[0]);
if (b.empty())
cerr << "Unknown file or bad hex: '" << m_inputs[0] << "'" << endl;
else
try
{
TransactionBase t(b, CheckTransaction::None);
cout << "Transaction " << t.sha3().hex() << endl;
if (t.isCreation())
{
cout << " type: creation" << endl;
cout << " code: " << toHex(t.data()) << endl;
}
else
{
cout << " type: message" << endl;
cout << " to: " << t.to().hex() << endl;
cout << " data: " << (t.data().empty() ? "none" : toHex(t.data())) << endl;
}
try
{
auto s = t.sender();
if (t.isCreation())
cout << " creates: " << toAddress(s, t.nonce()).hex() << endl;
cout << " from: " << s.hex() << endl;
}
catch (...)
{
cout << " from: <unsigned>" << endl;
}
cout << " value: " << formatBalance(t.value()) << " (" << t.value() << " wei)" << endl;
cout << " nonce: " << t.nonce() << endl;
cout << " gas: " << t.gas() << endl;
cout << " gas price: " << formatBalance(t.gasPrice()) << " (" << t.gasPrice() << " wei)" << endl;
cout << " signing hash: " << t.sha3(WithoutSignature).hex() << endl;
cout << " v: " << (int)t.signature().v << endl;
cout << " r: " << t.signature().r << endl;
cout << " s: " << t.signature().s << endl;
}
catch (Exception& ex)
{
cerr << "Invalid transaction: " << ex.what() << endl;
}
break;
}
case OperationMode::SignTx:
{
Secret s = getSecret(m_signKey);
if (m_inputs.empty())
m_inputs.push_back(string());
for (string const& i: m_inputs)
{
bool isFile = false;
try
{
TransactionBase t = i.empty() ? TransactionBase(m_toSign) : TransactionBase(inputData(i, &isFile), CheckTransaction::None);
t.sign(s);
cout << t.sha3() << ": ";
if (isFile)
{
writeFile(i + ".signed", toHex(t.rlp()));
cout << i + ".signed" << endl;
}
else
cout << toHex(t.rlp()) << endl;
}
catch (Exception& ex)
{
cerr << "Invalid transaction: " << ex.what() << endl;
}
}
break;
}
case OperationMode::NewBrain:
{
if (m_name != "--")
keyManager();
boost::random_device d;
boost::random::uniform_int_distribution<unsigned> pickWord(0, WordList.size() - 1);
string seed;
for (int i = 0; i < 13; ++i)
seed += (seed.size() ? " " : "") + WordList[pickWord(d)];
cout << "Your brain key phrase: <<" << seed << ">>" << endl;
if (m_name != "--")
{
std::string hint;
cout << "Enter a hint for the phrase if you want: " << flush;
getline(cin, hint);
Address a = keyManager().importBrain(seed, m_name, hint);
cout << a.abridged() << endl;
cout << " ICAP: " << ICAP(a).encoded() << endl;
cout << " Address: " << a.hex() << endl;
}
break;
}
case OperationMode::InspectBrain:
{
Address a = toAddress(KeyManager::brain(getPassword("Enter brain wallet key phrase: ")));
cout << a.abridged() << endl;
cout << " ICAP: " << ICAP(a).encoded() << endl;
cout << " Address: " << a.hex() << endl;
break;
}
case OperationMode::ListBare:
for (h128 const& u: std::set<h128>() + secretStore().keys())
cout << toUUID(u) << endl;
break;
case OperationMode::NewBare:
{
if (m_lock.empty())
m_lock = createPassword("Enter a password with which to secure this account: ");
auto k = makeKey();
h128 u = secretStore().importSecret(k.secret().ref(), m_lock);
cout << "Created key " << toUUID(u) << endl;
cout << " Address: " << k.address().hex() << endl;
cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
break;
}
case OperationMode::ImportBare:
for (string const& input: m_inputs)
{
h128 u;
bytesSec b;
b.writable() = fromHex(input);
if (b.size() != 32)
{
std::string s = contentsString(input);
b.writable() = fromHex(s);
if (b.size() != 32)
u = secretStore().importKey(input);
}
if (!u && b.size() == 32)
u = secretStore().importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
if (!u)
{
cerr << "Cannot import " << input << " not a file or secret." << endl;
continue;
}
cout << "Successfully imported " << input << " as " << toUUID(u);
}
break;
case OperationMode::InspectBare:
for (auto const& i: m_inputs)
if (!contents(i).empty())
{
h128 u = secretStore().readKey(i, false);
bytesSec s = secretStore().secret(u, [&](){ return getPassword("Enter password for key " + i + ": "); });
cout << "Key " << i << ":" << endl;
cout << " UUID: " << toUUID(u) << ":" << endl;
cout << " Address: " << toAddress(Secret(s)).hex() << endl;
cout << " Secret: " << toHex(s.ref().cropped(0, 8)) << "..." << endl;
}
else if (h128 u = fromUUID(i))
{
bytesSec s = secretStore().secret(u, [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); });
cout << "Key " << i << ":" << endl;
cout << " Address: " << toAddress(Secret(s)).hex() << endl;
cout << " Secret: " << toHex(s.ref().cropped(0, 8)) << "..." << endl;
}
else
cerr << "Couldn't inspect " << i << "; not found." << endl;
break;
case OperationMode::ExportBare: break;
case OperationMode::RecodeBare:
for (auto const& i: m_inputs)
if (h128 u = fromUUID(i))
if (secretStore().recode(u, lockPassword(toUUID(u)), [&](){ return getPassword("Enter password for key " + toUUID(u) + ": "); }, kdf()))
cerr << "Re-encoded " << toUUID(u) << endl;
else
cerr << "Couldn't re-encode " << toUUID(u) << "; key corrupt or incorrect password supplied." << endl;
else
cerr << "Couldn't re-encode " << i << "; not found." << endl;
break;
case OperationMode::KillBare:
for (auto const& i: m_inputs)
if (h128 u = fromUUID(i))
secretStore().kill(u);
else
cerr << "Couldn't kill " << i << "; not found." << endl;
break;
case OperationMode::New:
{
keyManager();
tie(m_lock, m_lockHint) = createPassword(keyManager(), "Enter a password with which to secure this account (or nothing to use the master password): ", m_lock, m_lockHint);
auto k = makeKey();
bool usesMaster = m_lock.empty();
h128 u = usesMaster ? keyManager().import(k.secret(), m_name) : keyManager().import(k.secret(), m_name, m_lock, m_lockHint);
cout << "Created key " << toUUID(u) << endl;
cout << " Name: " << m_name << endl;
if (usesMaster)
cout << " Uses master password." << endl;
else
cout << " Password hint: " << m_lockHint << endl;
cout << " Address: " << k.address().hex() << endl;
cout << " ICAP: " << ICAP(k.address()).encoded() << endl;
break;
}
case OperationMode::ImportWithAddress:
{
keyManager();
string const& i = m_inputs[0];
h128 u;
bytesSec b;
b.writable() = fromHex(i);
if (b.size() != 32)
{
std::string s = contentsString(i);
b.writable() = fromHex(s);
if (b.size() != 32)
u = keyManager().store().importKey(i);
}
if (!u && b.size() == 32)
u = keyManager().store().importSecret(b, lockPassword(toAddress(Secret(b)).abridged()));
if (!u)
{
cerr << "Cannot import " << i << " not a file or secret." << endl;
break;
}
keyManager().importExisting(u, m_name, m_address);
cout << "Successfully imported " << i << ":" << endl;
cout << " Name: " << m_name << endl;
cout << " Address: " << m_address << endl;
cout << " UUID: " << toUUID(u) << endl;
break;
}
case OperationMode::ImportBrain:
{
keyManager();
std::string seed = getPassword("Enter brain wallet key phrase: ");
std::string hint;
cout << "Enter a hint for the phrase if you want: " << flush;
getline(cin, hint);
Address a = keyManager().importBrain(seed, m_name, hint);
cout << a << endl;
cout << " ICAP: " << ICAP(a).encoded() << endl;
cout << " Address: " << a.hex() << endl;
break;
}
case OperationMode::ImportPresale:
{
keyManager();
std::string pw;
KeyPair k = keyManager().presaleSecret(contentsString(m_inputs[0]), [&](bool){ return (pw = getPassword("Enter the password for the presale key: ")); });
keyManager().import(k.secret(), m_name, pw, "Same password as used for presale key");
break;
}
case OperationMode::List:
{
vector<u128> bare;
AddressHash got;
for (auto const& u: keyManager().store().keys())
if (Address a = keyManager().address(u))
{
got.insert(a);
cout << toUUID(u) << " " << a.abridged();
string s = ICAP(a).encoded();
cout << " " << s << string(35 - s.size(), ' ');
cout << " " << keyManager().accountName(a) << endl;
}
else
bare.push_back(u);
for (auto const& a: keyManager().accounts())
if (!got.count(a))
{
cout << " (Brain) " << a.abridged();
cout << " " << ICAP(a).encoded() << " ";
cout << " " << keyManager().accountName(a) << endl;
}
for (auto const& u: bare)
cout << toUUID(u) << " (Bare)" << endl;
}
default: break;
}
}
std::string lockPassword(std::string const& _accountName)
{
return m_lock.empty() ? createPassword("Enter a password with which to secure account " + _accountName + ": ") : m_lock;
}
static void streamHelp(ostream& _out)
{
_out
<< "Secret-store (\"bare\") operation modes:" << endl
<< " --list-bare List all secret available in secret-store." << endl
<< " --new-bare Generate and output a key without interacting with wallet and dump the JSON." << endl
<< " --import-bare [ <file>|<secret-hex> , ... ] Import keys from given sources." << endl
<< " --recode-bare [ <uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
<< " --inspect-bare [ <uuid>|<file> , ... ] Output information on given keys." << endl
// << " --export-bare [ <uuid> , ... ] Export given keys." << endl
<< " --kill-bare [ <uuid> , ... ] Delete given keys." << endl
<< "Secret-store configuration:" << endl
<< " --secrets-path <path> Specify Web3 secret-store path (default: " << SecretStore::defaultPath() << ")" << endl
<< endl
<< "Wallet operating modes:" << endl
<< " -l,--list List all keys available in wallet." << endl
<< " -n,--new <name> Create a new key with given name and add it in the wallet." << endl
<< " -i,--import [<uuid>|<file>|<secret-hex>] <name> Import keys from given source and place in wallet." << endl
<< " --import-presale <file> <name> Import a presale wallet into a key with the given name." << endl
<< " --import-with-address [<uuid>|<file>|<secret-hex>] <address> <name> Import keys from given source with given address and place in wallet." << endl
<< " -e,--export [ <address>|<uuid> , ... ] Export given keys." << endl
<< " -r,--recode [ <address>|<uuid>|<file> , ... ] Decrypt and re-encrypt given keys." << endl
<< "Brain wallet operating modes:" << endl
<< "WARNING: Brain wallets with human-generated passphrasses are highly susceptible to attack. Don't use such a thing for" << endl
<< "anything important." << endl
<< " --new-brain [ <name>|-- ] Create a new 13-word brain wallet; argument is the name or if --, do not add to wallet."<< endl
<< " --import-brain <name> Import your own brain wallet." << endl
<< " --inspect-brain Check the address of a particular brain wallet." << endl
<< "Wallet configuration:" << endl
<< " --create-wallet Create an Ethereum master wallet." << endl
<< " --wallet-path <path> Specify Ethereum wallet path (default: " << KeyManager::defaultPath() << ")" << endl
<< " -m, --master <password> Specify wallet (master) password." << endl
<< endl
<< "Transaction operating modes:" << endl
<< " -d,--decode-tx [<hex>|<file>] Decode given transaction." << endl
<< " -s,--sign-tx [ <address>|<uuid>|<file>|brain((#<HD-index>):<brain-phrase>) ] [ <hex>|<file> , ... ] (Re-)Sign given transaction." << endl
<< endl
<< "Encryption configuration:" << endl
<< " --kdf <kdfname> Specify KDF to use when encrypting (default: sc rypt)" << endl
<< " --kdf-param <name> <value> Specify a parameter for the KDF." << endl
// << " --cipher <ciphername> Specify cipher to use when encrypting (default: aes-128-ctr)" << endl
// << " --cipher-param <name> <value> Specify a parameter for the cipher." << endl
<< " --lock <password> Specify password for when encrypting a (the) key." << endl
<< " --hint <hint> Specify hint for the --lock password." << endl
<< endl
<< "Decryption configuration:" << endl
<< " --unlock <password> Specify password for a (the) key." << endl
<< "Key generation configuration:" << endl
<< " --no-icap Don't bother to make a direct-ICAP capable key." << endl
;
}
static bytes inputData(std::string const& _input, bool* _isFile = nullptr)
{
bytes b = fromHex(_input);
if (_isFile)
*_isFile = false;
if (b.empty())
{
if (_isFile)
*_isFile = true;
std::string s = boost::trim_copy_if(contentsString(_input), is_any_of(" \t\n"));
b = fromHex(s);
if (b.empty())
b = asBytes(s);
}
return b;
}
static bool isTrue(std::string const& _m)
{
return _m == "on" || _m == "yes" || _m == "true" || _m == "1";
}
static bool isFalse(std::string const& _m)
{
return _m == "off" || _m == "no" || _m == "false" || _m == "0";
}
private:
void openWallet(KeyManager& _w)
{
while (true)
{
if (_w.load(m_masterPassword))
break;
if (!m_masterPassword.empty())
{
cout << "Password invalid. Try again." << endl;
m_masterPassword.clear();
}
m_masterPassword = getPassword("Please enter your MASTER password: ");
}
}
KDF kdf() const { return m_kdf == "pbkdf2" ? KDF::PBKDF2_SHA256 : KDF::Scrypt; }
KeyManager& keyManager()
{
if (!m_keyManager)
{
m_keyManager.reset(new KeyManager(m_walletPath, m_secretsPath));
if (m_keyManager->exists())
openWallet(*m_keyManager);
else
{
cerr << "Couldn't open wallet. Does it exist?" << endl;
exit(-1);
}
}
return *m_keyManager;
}
SecretStore& secretStore()
{
if (m_keyManager)
return m_keyManager->store();
if (!m_secretStore)
m_secretStore.reset(new SecretStore(m_secretsPath));
return *m_secretStore;
}
/// Where the keys are.
unique_ptr<SecretStore> m_secretStore;
unique_ptr<KeyManager> m_keyManager;
/// Operating mode.
OperationMode m_mode;
/// Wallet stuff
string m_secretsPath = SecretStore::defaultPath();
string m_walletPath = KeyManager::defaultPath();
/// Wallet password stuff
string m_masterPassword;
strings m_unlocks;
string m_lock;
string m_lockHint;
bool m_icap = true;
/// Creating/importing
string m_name;
Address m_address;
/// Importing
strings m_inputs;
/// Signing
string m_signKey;
TransactionSkeleton m_toSign;
string m_kdf = "scrypt";
map<string, string> m_kdfParams;
// string m_cipher;
// map<string, string> m_cipherParams;
};

84
ethkey/main.cpp

@ -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 main.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* Ethereum client.
*/
#include <thread>
#include <chrono>
#include <fstream>
#include <iostream>
#include <libdevcore/FileSystem.h>
#include <libdevcore/Log.h>
#include <libethcore/KeyManager.h>
#include "BuildInfo.h"
#include "KeyAux.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
void help()
{
cout
<< "Usage ethkey [OPTIONS]" << endl
<< "Options:" << endl << endl;
KeyCLI::streamHelp(cout);
cout
<< "General Options:" << endl
<< " -v,--verbosity <0 - 9> Set the log verbosity from 0 to 9 (default: 8)." << endl
<< " -V,--version Show the version and exit." << endl
<< " -h,--help Show this help message and exit." << endl
;
exit(0);
}
void version()
{
cout << "ethkey version " << dev::Version << endl;
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
exit(0);
}
int main(int argc, char** argv)
{
KeyCLI m(KeyCLI::OperationMode::ListBare);
g_logVerbosity = 0;
for (int i = 1; i < argc; ++i)
{
string arg = argv[i];
if (m.interpretOption(i, argc, argv)) {}
else if ((arg == "-v" || arg == "--verbosity") && i + 1 < argc)
g_logVerbosity = atoi(argv[++i]);
else if (arg == "-h" || arg == "--help")
help();
else if (arg == "-V" || arg == "--version")
version();
else
{
cerr << "Invalid argument: " << arg << endl;
exit(-1);
}
}
m.execute();
return 0;
}

19
ethvm/CMakeLists.txt

@ -1,19 +0,0 @@
cmake_policy(SET CMP0015 NEW)
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${DB_INCLUDE_DIRS})
set(EXECUTABLE ethvm)
add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} ethereum)
if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

224
ethvm/main.cpp

@ -1,224 +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 main.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* EVM Execution tool.
*/
#include <fstream>
#include <iostream>
#include <ctime>
#include <boost/algorithm/string.hpp>
#include <libdevcore/CommonIO.h>
#include <libdevcore/RLP.h>
#include <libdevcore/SHA3.h>
#include <libethereum/Block.h>
#include <libethereum/Executive.h>
#include <libevm/VM.h>
#include <libevm/VMFactory.h>
using namespace std;
using namespace dev;
using namespace eth;
void help()
{
cout
<< "Usage ethvm <options> [trace|stats|output] (<file>|--)" << endl
<< "Transaction options:" << endl
<< " --value <n> Transaction should transfer the <n> wei (default: 0)." << endl
<< " --gas <n> Transaction should be given <n> gas (default: block gas limit)." << endl
<< " --gas-price <n> Transaction's gas price' should be <n> (default: 0)." << endl
<< " --sender <a> Transaction sender should be <a> (default: 0000...0069)." << endl
<< " --origin <a> Transaction origin should be <a> (default: 0000...0069)." << endl
#if ETH_EVMJIT || !ETH_TRUE
<< endl
<< "VM options:" << endl
<< " --vm <vm-kind> Select VM. Options are: interpreter, jit, smart. (default: interpreter)" << endl
#endif
<< endl
<< "Options for trace:" << endl
<< " --flat Minimal whitespace in the JSON." << endl
<< " --mnemonics Show instruction mnemonics in the trace (non-standard)." << endl
<< endl
<< "General options:" << endl
<< " -V,--version Show the version and exit." << endl
<< " -h,--help Show this help message and exit." << endl;
exit(0);
}
void version()
{
cout << "ethvm version " << dev::Version << endl;
cout << "By Gav Wood, 2015." << endl;
cout << "Build: " << DEV_QUOTED(ETH_BUILD_PLATFORM) << "/" << DEV_QUOTED(ETH_BUILD_TYPE) << endl;
exit(0);
}
enum class Mode
{
Trace,
Statistics,
OutputOnly
};
int main(int argc, char** argv)
{
string incoming = "--";
Mode mode = Mode::Statistics;
State state;
Address sender = Address(69);
Address origin = Address(69);
u256 value = 0;
u256 gas = Block().gasLimitRemaining();
u256 gasPrice = 0;
bool styledJson = true;
StandardTrace st;
EnvInfo envInfo;
for (int i = 1; i < argc; ++i)
{
string arg = argv[i];
if (arg == "-h" || arg == "--help")
help();
else if (arg == "-V" || arg == "--version")
version();
#if ETH_EVMJIT
else if (arg == "--vm" && i + 1 < argc)
{
string vmKind = argv[++i];
if (vmKind == "interpreter")
VMFactory::setKind(VMKind::Interpreter);
else if (vmKind == "jit")
VMFactory::setKind(VMKind::JIT);
else if (vmKind == "smart")
VMFactory::setKind(VMKind::Smart);
else
{
cerr << "Unknown VM kind: " << vmKind << endl;
return -1;
}
}
#endif
else if (arg == "--mnemonics")
st.setShowMnemonics();
else if (arg == "--flat")
styledJson = false;
else if (arg == "--value" && i + 1 < argc)
value = u256(argv[++i]);
else if (arg == "--sender" && i + 1 < argc)
sender = Address(argv[++i]);
else if (arg == "--origin" && i + 1 < argc)
origin = Address(argv[++i]);
else if (arg == "--gas" && i + 1 < argc)
gas = u256(argv[++i]);
else if (arg == "--gas-price" && i + 1 < argc)
gasPrice = u256(argv[++i]);
else if (arg == "--value" && i + 1 < argc)
value = u256(argv[++i]);
else if (arg == "--value" && i + 1 < argc)
value = u256(argv[++i]);
else if (arg == "--beneficiary" && i + 1 < argc)
envInfo.setBeneficiary(Address(argv[++i]));
else if (arg == "--number" && i + 1 < argc)
envInfo.setNumber(u256(argv[++i]));
else if (arg == "--difficulty" && i + 1 < argc)
envInfo.setDifficulty(u256(argv[++i]));
else if (arg == "--timestamp" && i + 1 < argc)
envInfo.setTimestamp(u256(argv[++i]));
else if (arg == "--gas-limit" && i + 1 < argc)
envInfo.setGasLimit(u256(argv[++i]));
else if (arg == "--value" && i + 1 < argc)
value = u256(argv[++i]);
else if (arg == "stats")
mode = Mode::Statistics;
else if (arg == "output")
mode = Mode::OutputOnly;
else if (arg == "trace")
mode = Mode::Trace;
else
incoming = arg;
}
bytes code;
if (incoming == "--" || incoming.empty())
for (int i = cin.get(); i != -1; i = cin.get())
code.push_back((char)i);
else
code = contents(incoming);
bytes data = fromHex(boost::trim_copy(asString(code)));
if (data.empty())
data = code;
state.addBalance(sender, value);
Executive executive(state, envInfo);
ExecutionResult res;
executive.setResultRecipient(res);
Transaction t = eth::Transaction(value, gasPrice, gas, data, 0);
t.forceSender(sender);
unordered_map<byte, pair<unsigned, bigint>> counts;
unsigned total = 0;
bigint memTotal;
auto onOp = [&](uint64_t step, Instruction inst, bigint m, bigint gasCost, bigint gas, VM* vm, ExtVMFace const* extVM) {
if (mode == Mode::Statistics)
{
counts[(byte)inst].first++;
counts[(byte)inst].second += gasCost;
total++;
if (m > 0)
memTotal = m;
}
else if (mode == Mode::Trace)
st(step, inst, m, gasCost, gas, vm, extVM);
};
executive.initialize(t);
executive.create(sender, value, gasPrice, gas, &data, origin);
Timer timer;
executive.go(onOp);
double execTime = timer.elapsed();
executive.finalize();
bytes output = std::move(res.output);
if (mode == Mode::Statistics)
{
cout << "Gas used: " << res.gasUsed << " (+" << t.gasRequired() << " for transaction, -" << res.gasRefunded << " refunded)" << endl;
cout << "Output: " << toHex(output) << endl;
LogEntries logs = executive.logs();
cout << logs.size() << " logs" << (logs.empty() ? "." : ":") << endl;
for (LogEntry const& l: logs)
{
cout << " " << l.address.hex() << ": " << toHex(t.data()) << endl;
for (h256 const& t: l.topics)
cout << " " << t.hex() << endl;
}
cout << total << " operations in " << execTime << " seconds." << endl;
cout << "Maximum memory usage: " << memTotal * 32 << " bytes" << endl;
cout << "Expensive operations:" << endl;
for (auto const& c: {Instruction::SSTORE, Instruction::SLOAD, Instruction::CALL, Instruction::CREATE, Instruction::CALLCODE, Instruction::MSTORE8, Instruction::MSTORE, Instruction::MLOAD, Instruction::SHA3})
if (!!counts[(byte)c].first)
cout << " " << instructionInfo(c).name << " x " << counts[(byte)c].first << " (" << counts[(byte)c].second << " gas)" << endl;
}
else if (mode == Mode::Trace)
cout << st.json(styledJson);
else if (mode == Mode::OutputOnly)
cout << toHex(output);
return 0;
}

21
rlp/CMakeLists.txt

@ -1,21 +0,0 @@
cmake_policy(SET CMP0015 NEW)
set(CMAKE_AUTOMOC OFF)
aux_source_directory(. SRC_LIST)
include_directories(BEFORE ..)
include_directories(${DB_INCLUDE_DIRS})
set(EXECUTABLE rlp)
add_executable(${EXECUTABLE} ${SRC_LIST})
target_link_libraries(${EXECUTABLE} devcrypto)
target_link_libraries(${EXECUTABLE} ${DB_LIBRARIES})
if (APPLE)
install(TARGETS ${EXECUTABLE} DESTINATION bin)
else()
eth_install_executable(${EXECUTABLE})
endif()

394
rlp/main.cpp

@ -1,394 +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 main.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
* RLP tool.
*/
#include <fstream>
#include <iostream>
#include <boost/algorithm/string.hpp>
#include "../test/JsonSpiritHeaders.h"
#include <libdevcore/CommonIO.h>
#include <libdevcore/RLP.h>
#include <libdevcore/SHA3.h>
using namespace std;
using namespace dev;
namespace js = json_spirit;
void help()
{
cout
<< "Usage rlp [OPTIONS] [ <file> | -- ]" << endl
<< "Options:" << endl
<< " -r,--render Render the given RLP. Options:" << endl
<< " --indent <string> Use string as the level indentation (default ' ')." << endl
<< " --hex-ints Render integers in hex." << endl
<< " --string-ints Render integers in the same way as strings." << endl
<< " --ascii-strings Render data as C-style strings or hex depending on content being ASCII." << endl
<< " --force-string Force all data to be rendered as C-style strings." << endl
<< " --force-escape When rendering as C-style strings, force all characters to be escaped." << endl
<< " --force-hex Force all data to be rendered as raw hex." << endl
<< " -l,--list-archive List the items in the RLP list by hash and size." << endl
<< " -e,--extract-archive Extract all items in the RLP list, named by hash." << endl
<< " -c,--create Given a simplified JSON string, output the RLP." << endl
<< "General options:" << endl
<< " -L,--lenience Try not to bomb out early if possible." << endl
<< " -x,--hex,--base-16 Treat input RLP as hex encoded data." << endl
<< " -k,--keccak Output Keccak-256 hash only." << endl
<< " --64,--base-64 Treat input RLP as base-64 encoded data." << endl
<< " -b,--bin,--base-256 Treat input RLP as raw binary data." << endl
<< " -h,--help Print this help message and exit." << endl
<< " -V,--version Show the version and exit." << endl
;
exit(0);
}
void version()
{
cout << "rlp version " << dev::Version << endl;
exit(0);
}
enum class Mode {
ListArchive,
ExtractArchive,
Render,
Create
};
enum class Encoding {
Auto,
Hex,
Base64,
Binary,
Keccak,
};
bool isAscii(string const& _s)
{
// Always hex-encode anything beginning with 0x to avoid ambiguity.
if (_s.size() >= 2 && _s.substr(0, 2) == "0x")
return false;
for (char c: _s)
if (c < 32)
return false;
return true;
}
class RLPStreamer
{
public:
struct Prefs
{
string indent;
bool hexInts = false;
bool stringInts = true;
bool hexPrefix = true;
bool forceString = false;
bool escapeAll = false;
bool forceHex = true;
};
RLPStreamer(ostream& _out, Prefs _p): m_out(_out), m_prefs(_p) {}
void output(RLP const& _d, unsigned _level = 0)
{
if (_d.isNull())
m_out << "null";
else if (_d.isInt() && !m_prefs.stringInts)
if (m_prefs.hexInts)
m_out << (m_prefs.hexPrefix ? "0x" : "") << toHex(toCompactBigEndian(_d.toInt<bigint>(RLP::LaissezFaire), 1), 1);
else
m_out << _d.toInt<bigint>(RLP::LaissezFaire);
else if (_d.isData() || (_d.isInt() && m_prefs.stringInts))
if (m_prefs.forceString || (!m_prefs.forceHex && isAscii(_d.toString())))
m_out << escaped(_d.toString(), m_prefs.escapeAll);
else
m_out << "\"" << (m_prefs.hexPrefix ? "0x" : "") << toHex(_d.toBytes()) << "\"";
else if (_d.isList())
{
m_out << "[";
string newline = "\n";
for (unsigned i = 0; i < _level + 1; ++i)
newline += m_prefs.indent;
int j = 0;
for (auto i: _d)
{
m_out << (j++ ?
(m_prefs.indent.empty() ? ", " : ("," + newline)) :
(m_prefs.indent.empty() ? " " : newline));
output(i, _level + 1);
}
newline = newline.substr(0, newline.size() - m_prefs.indent.size());
m_out << (m_prefs.indent.empty() ? (j ? " ]" : "]") : (j ? newline + "]" : "]"));
}
}
private:
std::ostream& m_out;
Prefs m_prefs;
};
int main(int argc, char** argv)
{
Encoding encoding = Encoding::Auto;
Mode mode = Mode::Render;
string inputFile = "--";
bool lenience = false;
RLPStreamer::Prefs prefs;
for (int i = 1; i < argc; ++i)
{
string arg = argv[i];
if (arg == "-h" || arg == "--help")
help();
else if (arg == "-r" || arg == "--render")
mode = Mode::Render;
else if (arg == "-c" || arg == "--create")
mode = Mode::Create;
else if ((arg == "-i" || arg == "--indent") && argc > i)
prefs.indent = argv[++i];
else if (arg == "--hex-ints")
prefs.hexInts = true;
else if (arg == "--string-ints")
prefs.stringInts = true;
else if (arg == "--ascii-strings")
prefs.forceString = prefs.forceHex = false;
else if (arg == "--force-string")
prefs.forceString = true;
else if (arg == "--force-hex")
prefs.forceHex = true, prefs.forceString = false;
else if (arg == "--force-escape")
prefs.escapeAll = true;
else if (arg == "-n" || arg == "--nice")
prefs.forceString = true, prefs.stringInts = false, prefs.forceHex = false, prefs.indent = " ";
else if (arg == "-l" || arg == "--list-archive")
mode = Mode::ListArchive;
else if (arg == "-e" || arg == "--extract-archive")
mode = Mode::ExtractArchive;
else if (arg == "-L" || arg == "--lenience")
lenience = true;
else if (arg == "-V" || arg == "--version")
version();
else if (arg == "-x" || arg == "--hex" || arg == "--base-16")
encoding = Encoding::Hex;
else if (arg == "-k" || arg == "--keccak")
encoding = Encoding::Keccak;
else if (arg == "--64" || arg == "--base-64")
encoding = Encoding::Base64;
else if (arg == "-b" || arg == "--bin" || arg == "--base-256")
encoding = Encoding::Binary;
else
inputFile = arg;
}
bytes in;
if (inputFile == "--")
for (int i = cin.get(); i != -1; i = cin.get())
in.push_back((byte)i);
else
in = contents(inputFile);
bytes b;
if (mode != Mode::Create)
{
if (encoding == Encoding::Auto)
{
encoding = Encoding::Hex;
for (char b: in)
if (b != '\n' && b != ' ' && b != '\t')
{
if (encoding == Encoding::Hex && (b < '0' || b > '9' ) && (b < 'a' || b > 'f' ) && (b < 'A' || b > 'F' ))
{
cerr << "'" << b << "':" << (int)b << endl;
encoding = Encoding::Base64;
}
if (encoding == Encoding::Base64 && (b < '0' || b > '9' ) && (b < 'a' || b > 'z' ) && (b < 'A' || b > 'Z' ) && b != '+' && b != '/')
{
encoding = Encoding::Binary;
break;
}
}
}
switch (encoding)
{
case Encoding::Hex:
{
string s = asString(in);
boost::algorithm::replace_all(s, " ", "");
boost::algorithm::replace_all(s, "\n", "");
boost::algorithm::replace_all(s, "\t", "");
b = fromHex(s);
break;
}
case Encoding::Base64:
{
string s = asString(in);
boost::algorithm::replace_all(s, " ", "");
boost::algorithm::replace_all(s, "\n", "");
boost::algorithm::replace_all(s, "\t", "");
b = fromBase64(s);
break;
}
default:
swap(b, in);
break;
}
}
try
{
RLP rlp(b);
switch (mode)
{
case Mode::ListArchive:
{
if (!rlp.isList())
{
cout << "Error: Invalid format; RLP data is not a list." << endl;
exit(1);
}
cout << rlp.itemCount() << " items:" << endl;
for (auto i: rlp)
{
if (!i.isData())
{
cout << "Error: Invalid format; RLP list item is not data." << endl;
if (!lenience)
exit(1);
}
cout << " " << i.size() << " bytes: " << sha3(i.data()) << endl;
}
break;
}
case Mode::ExtractArchive:
{
if (!rlp.isList())
{
cout << "Error: Invalid format; RLP data is not a list." << endl;
exit(1);
}
cout << rlp.itemCount() << " items:" << endl;
for (auto i: rlp)
{
if (!i.isData())
{
cout << "Error: Invalid format; RLP list item is not data." << endl;
if (!lenience)
exit(1);
}
ofstream fout;
fout.open(toString(sha3(i.data())));
fout.write(reinterpret_cast<char const*>(i.data().data()), i.data().size());
}
break;
}
case Mode::Render:
{
RLPStreamer s(cout, prefs);
s.output(rlp);
cout << endl;
break;
}
case Mode::Create:
{
vector<js::mValue> v(1);
try {
js::read_string(asString(in), v[0]);
}
catch (...)
{
cerr << "Error: Invalid format; bad JSON." << endl;
exit(1);
}
RLPStream out;
while (!v.empty())
{
auto vb = v.back();
v.pop_back();
switch (vb.type())
{
case js::array_type:
{
js::mArray a = vb.get_array();
out.appendList(a.size());
for (int i = a.size() - 1; i >= 0; --i)
v.push_back(a[i]);
break;
}
case js::str_type:
{
string const& s = vb.get_str();
if (s.size() >= 2 && s.substr(0, 2) == "0x")
out << fromHex(s);
else
{
// assume it's a normal JS escaped string.
bytes ss;
ss.reserve(s.size());
for (unsigned i = 0; i < s.size(); ++i)
if (s[i] == '\\' && i + 1 < s.size())
{
if (s[++i] == 'x' && i + 2 < s.size())
ss.push_back(fromHex(s.substr(i, 2))[0]);
}
else if (s[i] != '\\')
ss.push_back((byte)s[i]);
out << ss;
}
break;
}
case js::int_type:
out << vb.get_int();
break;
default:
cerr << "ERROR: Unsupported type in JSON." << endl;
if (!lenience)
exit(1);
}
}
switch (encoding)
{
case Encoding::Hex: case Encoding::Auto:
cout << toHex(out.out()) << endl;
break;
case Encoding::Base64:
cout << toBase64(&out.out()) << endl;
break;
case Encoding::Binary:
cout.write((char const*)out.out().data(), out.out().size());
break;
case Encoding::Keccak:
cout << sha3(out.out()).hex() << endl;
break;
}
break;
}
default:;
}
}
catch (...)
{
cerr << "Error: Invalid format; bad RLP." << endl;
exit(1);
}
return 0;
}
Loading…
Cancel
Save