Browse Source

More on JS API types. CODECOPY & CODESIZE. Fixed && operator.

cl-refactor
Gav Wood 11 years ago
parent
commit
fc5e1e4839
  1. 12
      libethcore/CommonData.h
  2. 6
      libethereum/Instruction.cpp
  3. 2
      libethereum/Instruction.h
  4. 25
      libethereum/VM.h
  5. 81
      libqethereum/QEthereum.cpp
  6. 31
      libqethereum/QEthereum.h

12
libethcore/CommonData.h

@ -105,6 +105,18 @@ inline std::string toBigEndianString(u160 _val) { std::string ret(20, '\0'); toB
inline bytes toBigEndian(u256 _val) { bytes ret(32); toBigEndian(_val, ret); return ret; }
inline bytes toBigEndian(u160 _val) { bytes ret(20); toBigEndian(_val, ret); return ret; }
/// Convenience function for toBigEndian.
/// @returns a byte array just big enough to represent @a _val.
template <class _T>
inline bytes toCompactBigEndian(_T _val)
{
int i = 0;
for (_T v = _val; v; ++i, v >>= 8) {}
bytes ret(i, 0);
toBigEndian(_val, ret);
return ret;
}
/// Convenience function for toBigEndian.
/// @returns a string just big enough to represent @a _val.
template <class _T>

6
libethereum/Instruction.cpp

@ -57,6 +57,8 @@ const std::map<std::string, Instruction> eth::c_instructions =
{ "CALLDATALOAD", Instruction::CALLDATALOAD },
{ "CALLDATASIZE", Instruction::CALLDATASIZE },
{ "CALLDATACOPY", Instruction::CALLDATACOPY },
{ "CODESIZE", Instruction::CODESIZE },
{ "CODECOPY", Instruction::CODECOPY },
{ "GASPRICE", Instruction::GASPRICE },
{ "PREVHASH", Instruction::PREVHASH },
{ "COINBASE", Instruction::COINBASE },
@ -144,6 +146,8 @@ const std::map<Instruction, InstructionInfo> eth::c_instructionInfo =
{ Instruction::CALLDATALOAD, { "CALLDATALOAD", 0, 1, 1 } },
{ Instruction::CALLDATASIZE, { "CALLDATASIZE", 0, 0, 1 } },
{ Instruction::CALLDATACOPY, { "CALLDATACOPY", 0, 3, 0 } },
{ Instruction::CODESIZE, { "CODESIZE", 0, 0, 1 } },
{ Instruction::CODECOPY, { "CODECOPY", 0, 3, 0 } },
{ Instruction::GASPRICE, { "GASPRICE", 0, 0, 1 } },
{ Instruction::PREVHASH, { "PREVHASH", 0, 0, 1 } },
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1 } },
@ -783,6 +787,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes
{
// Check if true - predicate
appendCode(o_code, o_locs, codes[i - 1], locs[i - 1]);
o_code.push_back((byte)Instruction::NOT);
// Push the false location.
ends.push_back((unsigned)o_code.size());
@ -790,7 +795,6 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes
pushLocation(o_code, 0);
// Jump to end...
o_code.push_back((byte)Instruction::NOT);
o_code.push_back((byte)Instruction::JUMPI);
}
o_code.push_back((byte)Instruction::POP);

2
libethereum/Instruction.h

@ -61,6 +61,8 @@ enum class Instruction: uint8_t
CALLDATALOAD,
CALLDATASIZE,
CALLDATACOPY,
CODESIZE,
CODECOPY,
GASPRICE,
PREVHASH = 0x40,

25
libethereum/VM.h

@ -137,6 +137,10 @@ template <class Ext> eth::bytesConstRef eth::VM::go(Ext& _ext, uint64_t _steps)
require(3);
newTempSize = (unsigned)m_stack.back() + (unsigned)m_stack[m_stack.size() - 3];
break;
case Instruction::CODECOPY:
require(3);
newTempSize = (unsigned)m_stack.back() + (unsigned)m_stack[m_stack.size() - 3];
break;
case Instruction::BALANCE:
runGas = c_balanceGas;
@ -328,7 +332,26 @@ template <class Ext> eth::bytesConstRef eth::VM::go(Ext& _ext, uint64_t _steps)
m_stack.pop_back();
unsigned l = (unsigned)m_stack.back();
m_stack.pop_back();
memcpy(m_temp.data() + mf, _ext.data.data() + cf, l);
unsigned el = cf + l > _ext.data.size() ? _ext.data.size() - cf : l;
memcpy(m_temp.data() + mf, _ext.data.data() + cf, el);
memset(m_temp.data() + mf + el, 0, l - el);
break;
}
case Instruction::CODESIZE:
m_stack.push_back(_ext.code.size());
break;
case Instruction::CODECOPY:
{
require(3);
unsigned mf = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned cf = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned l = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned el = cf + l > _ext.code.size() ? _ext.code.size() - cf : l;
memcpy(m_temp.data() + mf, _ext.code.data() + cf, el);
memset(m_temp.data() + mf + el, 0, l - el);
break;
}
case Instruction::GASPRICE:

81
libqethereum/QEthereum.cpp

@ -189,12 +189,8 @@ eth::bytes toBytes(QString const& _s)
// Hex
return eth::fromHex(_s.mid(2).toStdString());
else if (!_s.contains(QRegExp("[^0-9]")))
{
// Decimal
eth::bytes ret;
eth::toBigEndian(eth::bigint(_s.toStdString()), ret);
return ret;
}
return eth::toCompactBigEndian(eth::bigint(_s.toStdString()));
else
// Binary
return eth::asBytes(_s.toStdString());
@ -207,8 +203,24 @@ QString padded(QString const& _s, unsigned _l, unsigned _r)
b.insert(b.begin(), 0);
while (b.size() < _r)
b.push_back(0);
b.resize(_r);
return QString::fromStdString(eth::asString(b));
return QString::fromStdString(eth::asString(b).substr(b.size() - max(_l, _r)));
}
QString padded(QString const& _s, unsigned _l)
{
if (_s.startsWith("0x") || !_s.contains(QRegExp("[^0-9]")))
// Numeric: pad to right
return padded(_s, _l, _l);
else
// Text: pad to the left
return padded(_s, 0, _l);
}
QString unpadded(QString _s)
{
while (_s.size() && _s.endsWith(QChar(0)))
_s.chop(1);
return _s;
}
QEthereum::QEthereum(QObject* _p, Client* _c, QList<eth::KeyPair> _accounts): QObject(_p), m_client(_c), m_accounts(_accounts)
@ -225,9 +237,9 @@ void QEthereum::setup(QWebFrame* _e)
// disconnect
disconnect(SIGNAL(changed()));
_e->addToJavaScriptWindowObject("eth", this, QWebFrame::ScriptOwnership);
_e->addToJavaScriptWindowObject("u256", new U256Helper, QWebFrame::ScriptOwnership);
/* _e->addToJavaScriptWindowObject("u256", new U256Helper, QWebFrame::ScriptOwnership);
_e->addToJavaScriptWindowObject("key", new KeyHelper, QWebFrame::ScriptOwnership);
_e->addToJavaScriptWindowObject("bytes", new BytesHelper, QWebFrame::ScriptOwnership);
_e->addToJavaScriptWindowObject("bytes", new BytesHelper, QWebFrame::ScriptOwnership);*/
_e->evaluateJavaScript("eth.newBlock = function(f) { eth.changed.connect(f) }");
_e->evaluateJavaScript("eth.watch = function(a, s, f) { eth.changed.connect(f ? f : s) }");
_e->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { eth.doCreate(s, v, c, g, p); if (f) f() }");
@ -235,6 +247,7 @@ void QEthereum::setup(QWebFrame* _e)
_e->evaluateJavaScript("String.prototype.pad = function(l, r) { return eth.pad(this, l, r) }");
_e->evaluateJavaScript("String.prototype.bin = function(l) { return eth.toBinary(this) }");
_e->evaluateJavaScript("String.prototype.unbin = function(l) { return eth.fromBinary(this) }");
_e->evaluateJavaScript("String.prototype.unpad = function(l) { return eth.unpad(this) }");
}
void QEthereum::teardown(QWebFrame*)
@ -246,58 +259,58 @@ Client* QEthereum::client() const
return m_client;
}
QVariant QEthereum::coinbase() const
QString QEthereum::coinbase() const
{
return toQJS(client()->address());
}
QVariant QEthereum::account() const
QString QEthereum::account() const
{
if (m_accounts.empty())
return toQJS(Address());
return toQJS(m_accounts[0].address());
}
QList<QVariant> QEthereum::accounts() const
QStringList QEthereum::accounts() const
{
QList<QVariant> ret;
QStringList ret;
for (auto i: m_accounts)
ret.push_back(toQJS(i.address()));
return ret;
}
QVariant QEthereum::key() const
QString QEthereum::key() const
{
if (m_accounts.empty())
return toQJS(KeyPair());
return toQJS(m_accounts[0]);
return toQJS(KeyPair().sec());
return toQJS(m_accounts[0].sec());
}
QList<QVariant> QEthereum::keys() const
QStringList QEthereum::keys() const
{
QList<QVariant> ret;
QStringList ret;
for (auto i: m_accounts)
ret.push_back(toQJS(i));
ret.push_back(toQJS(i.sec()));
return ret;
}
void QEthereum::setCoinbase(QVariant _a)
void QEthereum::setCoinbase(QString _a)
{
if (client()->address() != to<Address>(_a))
if (client()->address() != toAddress(_a))
{
client()->setAddress(to<Address>(_a));
client()->setAddress(toAddress(_a));
changed();
}
}
QVariant QEthereum::balanceAt(QVariant _a) const
QString QEthereum::balanceAt(QString _a) const
{
return toQJS(client()->postState().balance(to<Address>(_a)));
return toQJS(client()->postState().balance(toAddress(_a)));
}
QVariant QEthereum::storageAt(QVariant _a, QVariant _p) const
QString QEthereum::storageAt(QString _a, QString _p) const
{
return toQJS(client()->postState().storage(to<Address>(_a), to<u256>(_p)));
return toQJS(client()->postState().storage(toAddress(_a), toU256(_p)));
}
u256 QEthereum::balanceAt(Address _a) const
@ -305,9 +318,9 @@ u256 QEthereum::balanceAt(Address _a) const
return client()->postState().balance(_a);
}
bool QEthereum::isContractAt(QVariant _a) const
bool QEthereum::isContractAt(QString _a) const
{
return client()->postState().addressHasCode(to<Address>(_a));
return client()->postState().addressHasCode(toAddress(_a));
}
bool QEthereum::isContractAt(Address _a) const
@ -341,9 +354,9 @@ void QEthereum::setListening(bool _l)
client()->stopNetwork();
}
double QEthereum::txCountAt(QVariant _a) const
double QEthereum::txCountAt(QString _a) const
{
return (double)client()->postState().transactionsFrom(to<Address>(_a));
return (double)client()->postState().transactionsFrom(toAddress(_a));
}
double QEthereum::txCountAt(Address _a) const
@ -356,14 +369,14 @@ unsigned QEthereum::peerCount() const
return (unsigned)client()->peerCount();
}
QVariant QEthereum::doCreate(QVariant _secret, QVariant _amount, QByteArray _init, QVariant _gas, QVariant _gasPrice)
QString QEthereum::doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice)
{
return toQJS(client()->transact(to<Secret>(_secret), to<u256>(_amount), bytes(_init.data(), _init.data() + _init.size()), to<u256>(_gas), to<u256>(_gasPrice)));
return toQJS(client()->transact(toSecret(_secret), toU256(_amount), toBytes(_init), toU256(_gas), toU256(_gasPrice)));
}
void QEthereum::doTransact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice)
void QEthereum::doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice)
{
client()->transact(to<Secret>(_secret), to<u256>(_amount), to<Address>(_dest), bytes(_data.data(), _data.data() + _data.size()), to<u256>(_gas), to<u256>(_gasPrice));
client()->transact(toSecret(_secret), toU256(_amount), toAddress(_dest), toBytes(_data), toU256(_gas), toU256(_gasPrice));
}
// extra bits needed to link on VS

31
libqethereum/QEthereum.h

@ -159,6 +159,7 @@ private:
Q_PROPERTY(bool mining READ isMining WRITE setMining)
};
#if 0
template <class T> T to(QVariant const& _s) { if (_s.type() != QVariant::String) return T(); auto s = _s.toString().toLatin1(); assert(s.size() == sizeof(T)); return *(T*)s.data(); }
template <class T> QVariant toQJS(T const& _s) { QLatin1String ret((char*)&_s, sizeof(T)); assert(QVariant(QString(ret)).toString().toLatin1().size() == sizeof(T)); assert(*(T*)(QVariant(QString(ret)).toString().toLatin1().data()) == _s); return QVariant(QString(ret)); }
@ -282,33 +283,43 @@ public:
return toQJS<eth::u256>(ret);
}
};
#endif
eth::bytes toBytes(QString const& _s);
QString padded(QString const& _s, unsigned _l, unsigned _r);
QString padded(QString const& _s, unsigned _l);
QString unpadded(QString _s);
template <class H> H toFixed(QString const& _s)
template <unsigned N> eth::FixedHash<N> toFixed(QString const& _s)
{
if (_s.startsWith("0x"))
// Hex
return H(_s.mid(2));
return eth::FixedHash<N>(_s.mid(2).toStdString());
else if (!_s.contains(QRegExp("[^0-9]")))
// Decimal
return (typename H::Arith)(_s);
return (typename eth::FixedHash<N>::Arith)(_s.toStdString());
else
// Binary
return H(toBytes(_s));
return eth::FixedHash<N>(eth::asBytes(padded(_s, N).toStdString()));
}
template <class I> I toInt(QString const& _s)
template <unsigned N> boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N, N, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>> toInt(QString const& _s)
{
if (_s.startsWith("0x") || !_s.contains(QRegExp("[^0-9]")))
// Hex or Decimal
return (I)eth::bigint(_s);
return boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N, N, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>(_s.toStdString());
else
// Binary
return eth::fromBigEndian<I>(toBytes(_s));
return eth::fromBigEndian<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N, N, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>>(eth::asBytes(padded(_s, N).toStdString()));
}
inline eth::Address toAddress(QString const& _s) { return toFixed<20>(_s); }
inline eth::Secret toSecret(QString const& _s) { return toFixed<32>(_s); }
inline eth::u256 toU256(QString const& _s) { return toInt<32>(_s); }
template <unsigned S> QString toQJS(eth::FixedHash<S> const& _h) { return QString::fromStdString("0x" + toHex(_h.ref())); }
template <unsigned N> QString toQJS(boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N, N, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>> const& _n) { return QString::fromStdString("0x" + eth::toHex(eth::toCompactBigEndian(_n))); }
inline QString toBinary(QString const& _s)
{
return QString::fromStdString(eth::asString(toBytes(_s)));
@ -335,7 +346,9 @@ public:
Q_INVOKABLE QString ethTest() const { return "Hello world!"; }
Q_INVOKABLE QEthereum* self() { return this; }
Q_INVOKABLE QString pad(QString _s, unsigned _l) const { return padded(_s, _l); }
Q_INVOKABLE QString pad(QString _s, unsigned _l, unsigned _r) const { return padded(_s, _l, _r); }
Q_INVOKABLE QString unpad(QString _s) const { return unpadded(_s); }
Q_INVOKABLE QString toBinary(QString _s) const { return ::toBinary(_s); }
Q_INVOKABLE QString fromBinary(QString _s) const { return ::fromBinary(_s); }
@ -351,7 +364,7 @@ public:
bool isMining() const;
QString/*eth::Address*/ coinbase() const;
QString/*eth::u256*/ gasPrice() const { return toString(10 * eth::szabo); }
QString/*eth::u256*/ gasPrice() const { return toQJS(10 * eth::szabo); }
eth::u256 balanceAt(eth::Address _a) const;
double txCountAt(eth::Address _a) const;
@ -380,7 +393,7 @@ private:
Q_PROPERTY(bool mining READ isMining WRITE setMining)
Q_PROPERTY(QString gasPrice READ gasPrice NOTIFY changed)
Q_PROPERTY(QString key READ key NOTIFY changed)
Q_PROPERTY(QString keys READ keys NOTIFY changed)
Q_PROPERTY(QStringList keys READ keys NOTIFY changed)
Q_PROPERTY(unsigned peerCount READ peerCount)
eth::Client* m_client;

Loading…
Cancel
Save