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;
}