From d8323bbd09e3eec0a94e3ac8f1f56d2f6fd4ba34 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 25 Dec 2014 10:34:11 +0000 Subject: [PATCH] Simple ABI in/out and new Solidity-based Config/NameReg integration. --- alethzero/MainWin.cpp | 25 ++++++ libdevcore/Common.h | 3 + libdevcore/CommonData.cpp | 180 ++------------------------------------ libdevcore/CommonData.h | 3 + libdevcore/vector_ref.h | 2 +- libethereum/Client.cpp | 26 ++++++ libethereum/Client.h | 33 +++++++ libethereum/State.cpp | 9 +- 8 files changed, 102 insertions(+), 179 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 9cc651e4a..324868022 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -106,6 +106,8 @@ static QString contentsOfQResource(std::string const& res) } Address c_config = Address("661005d2720d855f1d9976f88bb10c1a3398c77f"); +Address c_newConfig = Address("d5f9d8d94886e70b06e474c3fb14fd43e2f23970"); +Address c_nameReg = Address("ddd1cea741d548f90d86fb87a3ae6492e18c03a1"); Main::Main(QWidget *parent) : QMainWindow(parent), @@ -450,6 +452,29 @@ static Public stringToPublic(QString const& _a) QString Main::pretty(dev::Address _a) const { + static std::map s_memos; + + if (!s_memos.count(_a)) + { + static Address s_newNameReg; + + if (!s_newNameReg) + s_newNameReg = abiOut
(ethereum()->call(c_newConfig, abiIn(1, (u256)1))); + + if (s_newNameReg) + { + QString s = QString::fromStdString(toString(abiOut(ethereum()->call(s_newNameReg, abiIn(2, _a))))); + if (s.size()) + { + s_memos[_a] = s; + return s; + } + } + } + else + if (s_memos[_a].size()) + return s_memos[_a]; + h256 n; if (h160 nameReg = (u160)ethereum()->stateAt(c_config, 0)) diff --git a/libdevcore/Common.h b/libdevcore/Common.h index 198119f24..11bee7aa5 100644 --- a/libdevcore/Common.h +++ b/libdevcore/Common.h @@ -74,6 +74,9 @@ using StringMap = std::map; using u256Map = std::map; using HexMap = std::map; +// Fixed-length string types. +using string32 = std::array; + // Null/Invalid values for convenience. static const u256 Invalid256 = ~(u256)0; static const bytes NullBytes; diff --git a/libdevcore/CommonData.cpp b/libdevcore/CommonData.cpp index fc3910cfe..b3abe4300 100644 --- a/libdevcore/CommonData.cpp +++ b/libdevcore/CommonData.cpp @@ -123,180 +123,10 @@ bytes dev::asNibbles(std::string const& _s) return ret; } -#if 0 - -/* Following code is copyright 2012-2014 Luke Dashjr - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the standard MIT license. See COPYING for more details. - */ - -#include -#include -#include -#include - -static const int8_t b58digits_map[] = { - -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1, - -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1, - 22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1, - -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46, - 47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1, -}; - -bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) -{ - size_t binsz = *binszp; - const unsigned char *b58u = (void*)b58; - unsigned char *binu = bin; - size_t outisz = (binsz + 3) / 4; - uint32_t outi[outisz]; - uint64_t t; - uint32_t c; - size_t i, j; - uint8_t bytesleft = binsz % 4; - uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0; - unsigned zerocount = 0; - - if (!b58sz) - b58sz = strlen(b58); - - memset(outi, 0, outisz * sizeof(*outi)); - - // Leading zeros, just count - for (i = 0; i < b58sz && !b58digits_map[b58u[i]]; ++i) - ++zerocount; - - for ( ; i < b58sz; ++i) - { - if (b58u[i] & 0x80) - // High-bit set on invalid digit - return false; - if (b58digits_map[b58u[i]] == -1) - // Invalid base58 digit - return false; - c = (unsigned)b58digits_map[b58u[i]]; - for (j = outisz; j--; ) - { - t = ((uint64_t)outi[j]) * 58 + c; - c = (t & 0x3f00000000) >> 32; - outi[j] = t & 0xffffffff; - } - if (c) - // Output number too big (carry to the next int32) - return false; - if (outi[0] & zeromask) - // Output number too big (last int32 filled too far) - return false; - } - - j = 0; - switch (bytesleft) { - case 3: - *(binu++) = (outi[0] & 0xff0000) >> 16; - case 2: - *(binu++) = (outi[0] & 0xff00) >> 8; - case 1: - *(binu++) = (outi[0] & 0xff); - ++j; - default: - break; - } - - for (; j < outisz; ++j) - { - *(binu++) = (outi[j] >> 0x18) & 0xff; - *(binu++) = (outi[j] >> 0x10) & 0xff; - *(binu++) = (outi[j] >> 8) & 0xff; - *(binu++) = (outi[j] >> 0) & 0xff; - } - - // Count canonical base58 byte count - binu = bin; - for (i = 0; i < binsz; ++i) - { - if (binu[i]) - break; - --*binszp; - } - *binszp += zerocount; - - return true; -} - -static -bool my_dblsha256(void *hash, const void *data, size_t datasz) +std::string dev::toString(string32 const& _s) { - uint8_t buf[0x20]; - return b58_sha256_impl(buf, data, datasz) && b58_sha256_impl(hash, buf, sizeof(buf)); -} - -int b58check(const void *bin, size_t binsz, const char *base58str, size_t b58sz) -{ - unsigned char buf[32]; - const uint8_t *binc = bin; - unsigned i; - if (binsz < 4) - return -4; - if (!my_dblsha256(buf, bin, binsz - 4)) - return -2; - if (memcmp(&binc[binsz - 4], buf, 4)) - return -1; - - // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) - for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) - {} // Just finding the end of zeros, nothing to do in loop - if (binc[i] == '\0' || base58str[i] == '1') - return -3; - - return binc[0]; -} - -static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - -bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) -{ - const uint8_t *bin = data; - int carry; - size_t i, j, high, zcount = 0; - size_t size; - - while (zcount < binsz && !bin[zcount]) - ++zcount; - - size = (binsz - zcount) * 138 / 100 + 1; - uint8_t buf[size]; - memset(buf, 0, size); - - for (i = zcount, high = size - 1; i < binsz; ++i, high = j) - { - for (carry = bin[i], j = size - 1; (j > high) || carry; --j) - { - carry += 256 * buf[j]; - buf[j] = carry % 58; - carry /= 58; - } - } - - for (j = 0; j < size && !buf[j]; ++j); - - if (*b58sz <= zcount + size - j) - { - *b58sz = zcount + size - j + 1; - return false; - } - - if (zcount) - memset(b58, '1', zcount); - for (i = zcount; j < size; ++i, ++j) - b58[i] = b58digits_ordered[buf[j]]; - b58[i] = '\0'; - *b58sz = i + 1; - - return true; + std::string ret; + for (unsigned i = 0; i < 32 && _s[i]; ++i) + ret.push_back(_s[i]); + return ret; } - -#endif diff --git a/libdevcore/CommonData.h b/libdevcore/CommonData.h index 87d2f5e28..6fab67452 100644 --- a/libdevcore/CommonData.h +++ b/libdevcore/CommonData.h @@ -236,4 +236,7 @@ inline std::set<_T> operator+(std::set<_T> const& _a, std::set<_T> const& _b) return ret += _b; } +/// Make normal string from fixed-length string. +std::string toString(string32 const& _s); + } diff --git a/libdevcore/vector_ref.h b/libdevcore/vector_ref.h index db46d62f6..714c53b8c 100644 --- a/libdevcore/vector_ref.h +++ b/libdevcore/vector_ref.h @@ -40,7 +40,7 @@ public: vector_ref<_T> cropped(size_t _begin, size_t _count = ~size_t(0)) const { if (m_data && _begin + std::max(size_t(0), _count) <= m_count) return vector_ref<_T>(m_data + _begin, _count == ~size_t(0) ? m_count - _begin : _count); else return vector_ref<_T>(); } void retarget(_T const* _d, size_t _s) { m_data = _d; m_count = _s; } void retarget(std::vector<_T> const& _t) { m_data = _t.data(); m_count = _t.size(); } - void copyTo(vector_ref::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); } + void copyTo(vector_ref::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); memset(_t.data() + m_count, 0, std::max(_t.size(), m_count) - m_count); } _T* begin() { return m_data; } _T* end() { return m_data + m_count; } diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp index 02ef2d3be..c7ed4500c 100644 --- a/libethereum/Client.cpp +++ b/libethereum/Client.cpp @@ -353,6 +353,32 @@ bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _dat return out; } +bytes Client::call(Address _dest, bytes const& _data, u256 _gas, u256 _value, u256 _gasPrice) +{ + bytes out; + try + { + u256 n; + State temp; + KeyPair k = KeyPair::create(); + // cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret)); + { + ReadGuard l(x_stateDB); + temp = m_postMine; + temp.addBalance(k.address(), _gas * _gasPrice + _value); + n = temp.transactionsFrom(k.address()); + } + Transaction t(_value, _gasPrice, _gas, _dest, _data, n, k.secret()); + u256 gasUsed = temp.execute(m_bc, t.rlp(), &out, false); + (void)gasUsed; // TODO: do something with gasused which it returns. + } + catch (...) + { + // TODO: Some sort of notification of failure. + } + return out; +} + Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) { startWorking(); diff --git a/libethereum/Client.h b/libethereum/Client.h index e8c460093..a68a3ecd8 100644 --- a/libethereum/Client.h +++ b/libethereum/Client.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -105,6 +107,34 @@ struct WorkChannel: public LogChannel { static const char* name() { return "-W-" #define cworkin dev::LogOutputStream() #define cworkout dev::LogOutputStream() +template struct ABISerialiser {}; +template struct ABISerialiser> { static bytes serialise(FixedHash const& _t) { return _t.asBytes(); } }; +template <> struct ABISerialiser { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } }; +template <> struct ABISerialiser { static bytes serialise(u160 const& _t) { return h160(_t).asBytes(); } }; + +inline bytes abiInAux() { return {}; } +template bytes abiInAux(T const& _t, U const& ... _u) +{ + return ABISerialiser::serialise(_t) + abiInAux(_u ...); +} + +template bytes abiIn(byte _id, T const& ... _t) +{ + return bytes(1, _id) + abiInAux(_t ...); +} + +template struct ABIDeserialiser {}; +template struct ABIDeserialiser> { static FixedHash deserialise(bytesConstRef& io_t) { FixedHash ret(io_t.cropped(0, N).toBytes()); io_t = io_t.cropped(N); return ret; } }; +template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } }; +template <> struct ABIDeserialiser { static u256 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian(io_t.cropped(0, 20)); io_t = io_t.cropped(20); return ret; } }; +template <> struct ABIDeserialiser { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).copyTo(vector_ref(ret.data(), 32)); io_t = io_t.cropped(32); return ret; } }; + +template T abiOut(bytes const& _data) +{ + bytesConstRef o(&_data); + return ABIDeserialiser::deserialise(o); +} + /** * @brief Main API hub for interfacing with Ethereum. */ @@ -135,6 +165,9 @@ public: /// Makes the given call. Nothing is recorded into the state. virtual bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo); + /// Makes the given call. Nothing is recorded into the state. This cheats by creating a null address and endowing it with a lot of ETH. + virtual bytes call(Address _dest, bytes const& _data = bytes(), u256 _gas = 125000, u256 _value = 0, u256 _gasPrice = 1 * ether); + // Informational stuff // [NEW API] diff --git a/libethereum/State.cpp b/libethereum/State.cpp index e5d31d863..ecdf2dab3 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -998,9 +998,12 @@ bool State::isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const LastHashes State::getLastHashes(BlockChain const& _bc) const { LastHashes ret; - unsigned n = (unsigned)m_previousBlock.number; - for (unsigned i = 0; i < 256; ++i) - ret[i] = _bc.numberHash(n - i); + if (c_protocolVersion > 49) + { + unsigned n = (unsigned)m_previousBlock.number; + for (unsigned i = 0; i < 256; ++i) + ret[i] = _bc.numberHash(n - i); + } return ret; }