Browse Source

First basic version compiling.

cl-refactor
Gav Wood 10 years ago
parent
commit
37c82e6fd7
  1. 200
      abi/main.cpp

200
abi/main.cpp

@ -34,14 +34,19 @@ namespace js = json_spirit;
void help() void help()
{ {
cout cout
<< "Usage abi enc <signature> (<arg1>, (<arg2>, ... ))" << endl << "Usage abi enc <method_name> (<arg1>, (<arg2>, ... ))" << endl
<< " abi enc -a <abi.json> <unique_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 << " abi dec -a <abi.json> [ <signature> | <unique_method_name> ]" << endl
<< "Options:" << endl << "Options:" << endl
<< " -a,--abi-file <filename> Specify the JSON ABI file." << endl << " -a,--abi-file <filename> Specify the JSON ABI file." << endl
<< "Input options (enc mode):" << endl << " -h,--help Print this help message and exit." << endl
<< " -p,--prefix Require all arguments to be prefixed 0x (hex), . (decimal), # (binary)." << endl << " -V,--version Show the version and exit." << endl
<< "Output options (dec mode):" << endl << "Input options:" << endl
<< " -p,--prefix Require all input formats to be prefixed e.g. 0x for hex, . for decimal, @ for binary." << endl
<< " -P,--no-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 << " -i,--index <n> Output only the nth (counting from 0) return value." << endl
<< " -d,--decimal All data should be displayed as decimal." << endl << " -d,--decimal All data should be displayed as decimal." << endl
<< " -x,--hex Display all data as hex." << endl << " -x,--hex Display all data as hex." << endl
@ -49,9 +54,6 @@ void help()
<< " -p,--prefix Prefix by a base identifier." << endl << " -p,--prefix Prefix by a base identifier." << endl
<< " -z,--no-zeroes Remove any leading zeroes from the data." << endl << " -z,--no-zeroes Remove any leading zeroes from the data." << endl
<< " -n,--no-nulls Remove any trailing nulls from the data." << endl << " -n,--no-nulls Remove any trailing nulls from the data." << endl
<< "General options:" << endl
<< " -h,--help Print this help message and exit." << endl
<< " -V,--version Show the version and exit." << endl
; ;
exit(0); exit(0);
} }
@ -62,52 +64,173 @@ void version()
exit(0); exit(0);
} }
enum class Mode { enum class Mode
{
Encode, Encode,
Decode Decode
}; };
enum class Encoding { enum class Encoding
{
Auto, Auto,
Decimal, Decimal,
Hex, Hex,
Binary, Binary,
}; };
enum class Tristate
{
False = false,
True = true,
Mu
};
enum class Format
{
Binary,
Hex,
Decimal
};
struct InvalidUserString: public Exception {}; struct InvalidUserString: public Exception {};
struct InvalidFormat: public Exception {};
enum class Base
{
Unknown,
Bytes,
Address,
Int,
Uint,
Fixed
};
pair<bytes, bool> fromUser(std::string const& _arg, bool _requirePrefix) struct ABIType
{ {
if (_requirePrefix) Base base = Base::Unknown;
unsigned size = 0;
unsigned ssize = 0;
vector<int> dims;
ABIType() = default;
ABIType(std::string const& _s)
{ {
if (_arg.substr(0, 2) == "0x") if (_s.size() < 1)
return make_pair(fromHex(_arg), false); return;
if (_arg.substr(0, 1) == ".") switch (_s[0])
return make_pair(toCompactBigEndian(bigint(_arg.substr(1))), false); {
if (_arg.substr(0, 1) == "#") case 'b': base = Base::Bytes; break;
return make_pair(asBytes(_arg.substr(1)), true); case 'a': base = Base::Address; break;
throw InvalidUserString(); 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)
return;
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));
}
}
string canon() const
{
string ret;
switch (base)
{
case Base::Bytes: ret = "bytes" + 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;
}
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; } }
};
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 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 (_prefix != Tristate::True)
{
if (_arg.find_first_not_of("0123456789") == string::npos)
{
type.noteDecimalInput();
return make_tuple(toCompactBigEndian(bigint(val)), type, Format::Decimal);
}
if (_arg.find_first_not_of("0123456789abcdefABCDEF") == string::npos)
{
type.noteHexInput(val.size());
return make_tuple(fromHex(val), type, Format::Hex);
}
type.noteBinaryInput();
return make_tuple(asBytes(_arg), type, Format::Binary);
}
throw InvalidUserString();
}
void userOutput(ostream& _out, bytes const& _data, Encoding _e)
{
switch (_e)
{ {
if (_arg.substr(0, 2) == "0x") case Encoding::Binary:
return make_pair(fromHex(_arg), false); _out.write((char const*)_data.data(), _data.size());
if (_arg.find_first_not_of("0123456789")) break;
return make_pair(toCompactBigEndian(bigint(_arg)), false); default:
return make_pair(asBytes(_arg), true); _out << toHex(_data) << endl;
} }
} }
bytes aligned(bytes const& _b, bool _left, unsigned _length) bytes aligned(bytes const& _b, ABIType _t, Format _f, unsigned _length)
{ {
(void)_t;
bytes ret = _b; bytes ret = _b;
while (ret.size() < _length) while (ret.size() < _length)
if (_left) if (_f == Format::Binary)
ret.push_back(0); ret.push_back(0);
else else
ret.insert(ret.begin(), 0); ret.insert(ret.begin(), 0);
while (ret.size() > _length) while (ret.size() > _length)
if (_left) if (_f == Format::Binary)
ret.pop_back(); ret.pop_back();
else else
ret.erase(ret.begin()); ret.erase(ret.begin());
@ -120,11 +243,12 @@ int main(int argc, char** argv)
Mode mode = Mode::Encode; Mode mode = Mode::Encode;
string abiFile; string abiFile;
string method; string method;
bool prefix = false; Tristate prefix = Tristate::Mu;
Tristate typePrefix = Tristate::Mu;
bool clearZeroes = false; bool clearZeroes = false;
bool clearNulls = false; bool clearNulls = false;
int outputIndex = -1; int outputIndex = -1;
vector<pair<bytes, bool>> args; vector<tuple<bytes, ABIType, Format>> args;
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
{ {
@ -140,7 +264,13 @@ int main(int argc, char** argv)
else if ((arg == "-i" || arg == "--index") && argc > i) else if ((arg == "-i" || arg == "--index") && argc > i)
outputIndex = atoi(argv[++i]); outputIndex = atoi(argv[++i]);
else if (arg == "-p" || arg == "--prefix") else if (arg == "-p" || arg == "--prefix")
prefix = true; prefix = Tristate::True;
else if (arg == "-P" || arg == "--no-prefix")
prefix = Tristate::False;
else if (arg == "-t" || arg == "--typing")
typePrefix = Tristate::True;
else if (arg == "-T" || arg == "--no-typing")
typePrefix = Tristate::False;
else if (arg == "-z" || arg == "--no-zeroes") else if (arg == "-z" || arg == "--no-zeroes")
clearZeroes = true; clearZeroes = true;
else if (arg == "-n" || arg == "--no-nulls") else if (arg == "-n" || arg == "--no-nulls")
@ -156,7 +286,7 @@ int main(int argc, char** argv)
else if (method.empty()) else if (method.empty())
method = arg; method = arg;
else else
args.push_back(fromUser(arg, prefix)); args.push_back(fromUser(arg, prefix, typePrefix));
} }
string abi; string abi;
@ -168,22 +298,24 @@ int main(int argc, char** argv)
if (mode == Mode::Encode) if (mode == Mode::Encode)
{ {
bytes ret;
if (abi.empty()) if (abi.empty())
{ {
bytes ret;
if (!method.empty()) if (!method.empty())
ret = FixedHash<32>(sha3(method)).asBytes(); ret = FixedHash<32>(sha3(method)).asBytes();
if (method.empty()) if (method.empty())
for (pair<bytes, bool> const& arg: args) for (tuple<bytes, ABIType, Format> const& arg: args)
ret += aligned(arg.first, arg.second, 32); ret += aligned(get<0>(arg), get<1>(arg), get<2>(arg), 32);
} }
else else
{ {
// TODO: read abi. // TODO: read abi.
} }
userOutput(cout, ret, encoding);
} }
else if (mode == Mode::Decode) else if (mode == Mode::Decode)
{ {
// TODO: read abi to determine output format.
(void)encoding; (void)encoding;
(void)clearZeroes; (void)clearZeroes;
(void)clearNulls; (void)clearNulls;

Loading…
Cancel
Save