Browse Source

Simple ABI in/out and new Solidity-based Config/NameReg integration.

cl-refactor
Gav Wood 10 years ago
parent
commit
d8323bbd09
  1. 25
      alethzero/MainWin.cpp
  2. 3
      libdevcore/Common.h
  3. 180
      libdevcore/CommonData.cpp
  4. 3
      libdevcore/CommonData.h
  5. 2
      libdevcore/vector_ref.h
  6. 26
      libethereum/Client.cpp
  7. 33
      libethereum/Client.h
  8. 9
      libethereum/State.cpp

25
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<Address, QString> s_memos;
if (!s_memos.count(_a))
{
static Address s_newNameReg;
if (!s_newNameReg)
s_newNameReg = abiOut<Address>(ethereum()->call(c_newConfig, abiIn(1, (u256)1)));
if (s_newNameReg)
{
QString s = QString::fromStdString(toString(abiOut<string32>(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))

3
libdevcore/Common.h

@ -74,6 +74,9 @@ using StringMap = std::map<std::string, std::string>;
using u256Map = std::map<u256, u256>;
using HexMap = std::map<bytes, std::string>;
// Fixed-length string types.
using string32 = std::array<char, 32>;
// Null/Invalid values for convenience.
static const u256 Invalid256 = ~(u256)0;
static const bytes NullBytes;

180
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 <cstdbool>
#include <cstddef>
#include <cstdint>
#include <cstring>
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

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

2
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<typename std::remove_const<_T>::type> _t) const { memcpy(_t.data(), m_data, std::min(_t.size(), m_count) * sizeof(_T)); }
void copyTo(vector_ref<typename std::remove_const<_T>::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; }

26
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();

33
libethereum/Client.h

@ -25,6 +25,8 @@
#include <mutex>
#include <list>
#include <atomic>
#include <string>
#include <array>
#include <boost/utility.hpp>
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
@ -105,6 +107,34 @@ struct WorkChannel: public LogChannel { static const char* name() { return "-W-"
#define cworkin dev::LogOutputStream<dev::eth::WorkInChannel, true>()
#define cworkout dev::LogOutputStream<dev::eth::WorkOutChannel, true>()
template <class T> struct ABISerialiser {};
template <unsigned N> struct ABISerialiser<FixedHash<N>> { static bytes serialise(FixedHash<N> const& _t) { return _t.asBytes(); } };
template <> struct ABISerialiser<u256> { static bytes serialise(u256 const& _t) { return h256(_t).asBytes(); } };
template <> struct ABISerialiser<u160> { static bytes serialise(u160 const& _t) { return h160(_t).asBytes(); } };
inline bytes abiInAux() { return {}; }
template <class T, class ... U> bytes abiInAux(T const& _t, U const& ... _u)
{
return ABISerialiser<T>::serialise(_t) + abiInAux(_u ...);
}
template <class ... T> bytes abiIn(byte _id, T const& ... _t)
{
return bytes(1, _id) + abiInAux(_t ...);
}
template <class T> struct ABIDeserialiser {};
template <unsigned N> struct ABIDeserialiser<FixedHash<N>> { static FixedHash<N> deserialise(bytesConstRef& io_t) { FixedHash<N> ret(io_t.cropped(0, N).toBytes()); io_t = io_t.cropped(N); return ret; } };
template <> struct ABIDeserialiser<u256> { static u256 deserialise(bytesConstRef& io_t) { u256 ret = fromBigEndian<u256>(io_t.cropped(0, 32)); io_t = io_t.cropped(32); return ret; } };
template <> struct ABIDeserialiser<u160> { static u256 deserialise(bytesConstRef& io_t) { u160 ret = fromBigEndian<u160>(io_t.cropped(0, 20)); io_t = io_t.cropped(20); return ret; } };
template <> struct ABIDeserialiser<string32> { static string32 deserialise(bytesConstRef& io_t) { string32 ret; io_t.cropped(0, 32).copyTo(vector_ref<char>(ret.data(), 32)); io_t = io_t.cropped(32); return ret; } };
template <class T> T abiOut(bytes const& _data)
{
bytesConstRef o(&_data);
return ABIDeserialiser<T>::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]

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

Loading…
Cancel
Save