Browse Source

Nicer transactions in JS API.

Added call() in Client & JS API.
cl-refactor
Gav Wood 11 years ago
parent
commit
b7a96fbbff
  1. 22
      libethereum/Client.cpp
  2. 10
      libethereum/Client.h
  3. 79
      libqethereum/QEthereum.cpp
  4. 12
      libqethereum/QEthereum.h

22
libethereum/Client.cpp

@ -333,6 +333,28 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _
m_tq.attemptImport(t.rlp()); m_tq.attemptImport(t.rlp());
} }
bytes Client::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice)
{
State temp;
Transaction t;
// cdebug << "Nonce at " << toAddress(_secret) << " pre:" << m_preMine.transactionsFrom(toAddress(_secret)) << " post:" << m_postMine.transactionsFrom(toAddress(_secret));
{
ReadGuard l(x_stateDB);
temp = m_postMine;
t.nonce = temp.transactionsFrom(toAddress(_secret));
}
t.value = _value;
t.gasPrice = _gasPrice;
t.gas = _gas;
t.receiveAddress = _dest;
t.data = _data;
t.sign(_secret);
bytes out;
u256 gasUsed = temp.execute(t.data, &out, false);
(void)gasUsed; // TODO: do something with gasused which it returns.
return out;
}
Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice)
{ {
ensureWorking(); ensureWorking();

10
libethereum/Client.h

@ -180,14 +180,14 @@ public:
/// @returns the new contract's address (assuming it all goes through). /// @returns the new contract's address (assuming it all goes through).
Address transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo); Address transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
/// Blocks until all pending transactions have been processed.
void flushTransactions();
/// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly. /// Injects the RLP-encoded transaction given by the _rlp into the transaction queue directly.
void inject(bytesConstRef _rlp); void inject(bytesConstRef _rlp);
/// Makes the given call. Nothing is recorded into the state. TODO /// Blocks until all pending transactions have been processed.
// bytes call(Secret _secret, u256 _amount, u256 _gasPrice, Address _dest, u256 _gas, bytes _data = bytes()); void flushTransactions();
/// Makes the given call. Nothing is recorded into the state.
bytes call(Secret _secret, u256 _value, Address _dest, bytes const& _data = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
// Informational stuff // Informational stuff

79
libqethereum/QEthereum.cpp

@ -131,6 +131,11 @@ QString QEthereum::sha3(QString _s) const
return toQJS(eth::sha3(asBytes(_s))); return toQJS(eth::sha3(asBytes(_s)));
} }
QString QEthereum::offset(QString _s, int _i) const
{
return toQJS(toU256(_s) + _i);
}
QString QEthereum::coinbase() const QString QEthereum::coinbase() const
{ {
return m_client ? toQJS(client()->address()) : ""; return m_client ? toQJS(client()->address()) : "";
@ -277,6 +282,45 @@ static eth::MessageFilter toMessageFilter(QString _json)
return filter; return filter;
} }
struct TransactionSkeleton
{
Secret from;
Address to;
u256 value;
bytes data;
u256 gas;
u256 gasPrice;
};
static TransactionSkeleton toTransaction(QString _json)
{
TransactionSkeleton ret;
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
if (f.contains("from"))
ret.from = toSecret(f["from"].toString());
if (f.contains("to"))
ret.to = toAddress(f["to"].toString());
if (f.contains("value"))
ret.value = toU256(f["value"].toString());
if (f.contains("gas"))
ret.gas = toU256(f["gas"].toString());
if (f.contains("gasPrice"))
ret.gasPrice = toU256(f["gasPrice"].toString());
if (f.contains("data"))
{
if (f["data"].isString())
ret.data = toBytes(f["data"].toString());
else if (f["data"].isArray())
for (auto i: f["data"].toArray())
eth::operator +=(ret.data, toBytes(padded(i.toString(), 32)));
else if (f["dataclose"].isArray())
for (auto i: f["dataclose"].toArray())
eth::operator +=(ret.data, toBytes(toBinary(i.toString())));
}
return ret;
}
static QString toJson(eth::PastMessages const& _pms) static QString toJson(eth::PastMessages const& _pms)
{ {
QJsonArray jsonArray; QJsonArray jsonArray;
@ -359,6 +403,41 @@ void QEthereum::doTransact(QString _secret, QString _amount, QString _dest, QStr
client()->flushTransactions(); client()->flushTransactions();
} }
void QEthereum::doTransact(QString _json)
{
if (!m_client)
return;
TransactionSkeleton t = toTransaction(_json);
if (!t.from && m_accounts.size())
t.from = m_accounts[0].secret();
if (!t.gasPrice)
t.gasPrice = 10 * eth::szabo;
if (!t.gas)
t.gas = client()->balanceAt(KeyPair(t.from).address()) / t.gasPrice;
if (t.to)
client()->transact(t.from, t.value, t.to, t.data, t.gas, t.gasPrice);
else
client()->transact(t.from, t.value, t.data, t.gas, t.gasPrice);
client()->flushTransactions();
}
QString QEthereum::doCall(QString _json)
{
if (!m_client)
return QString();
TransactionSkeleton t = toTransaction(_json);
if (!t.to)
return QString();
if (!t.from && m_accounts.size())
t.from = m_accounts[0].secret();
if (!t.gasPrice)
t.gasPrice = 10 * eth::szabo;
if (!t.gas)
t.gas = client()->balanceAt(KeyPair(t.from).address()) / t.gasPrice;
bytes out = client()->call(t.from, t.value, t.to, t.data, t.gas, t.gasPrice);
return asQString(out);
}
unsigned QEthereum::newWatch(QString _json) unsigned QEthereum::newWatch(QString _json)
{ {
if (!m_client) if (!m_client)

12
libqethereum/QEthereum.h

@ -72,6 +72,11 @@ inline QString toDecimal(QString const& _s)
return QString::fromStdString(eth::toString(toU256(_s))); return QString::fromStdString(eth::toString(toU256(_s)));
} }
inline double toFixed(QString const& _s)
{
return (double)toU256(_s) / (double)(eth::u256(1) << 128);
}
inline QString fromBinary(eth::bytes const& _s) inline QString fromBinary(eth::bytes const& _s)
{ {
return QString::fromStdString("0x" + eth::toHex(_s)); return QString::fromStdString("0x" + eth::toHex(_s));
@ -105,12 +110,14 @@ public:
Q_INVOKABLE QString lll(QString _s) const; Q_INVOKABLE QString lll(QString _s) const;
Q_INVOKABLE QString sha3(QString _s) const; Q_INVOKABLE QString sha3(QString _s) const;
Q_INVOKABLE QString offset(QString _s, int _offset) const;
Q_INVOKABLE QString pad(QString _s, unsigned _l) const { return padded(_s, _l); } 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 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 unpad(QString _s) const { return unpadded(_s); }
Q_INVOKABLE QString toBinary(QString _s) const { return ::toBinary(_s); } Q_INVOKABLE QString toBinary(QString _s) const { return ::toBinary(_s); }
Q_INVOKABLE QString fromBinary(QString _s) const { return ::fromBinary(_s); } Q_INVOKABLE QString fromBinary(QString _s) const { return ::fromBinary(_s); }
Q_INVOKABLE QString toDecimal(QString _s) const { return ::toDecimal(_s); } Q_INVOKABLE QString toDecimal(QString _s) const { return ::toDecimal(_s); }
Q_INVOKABLE double toFixed(QString _s) const { return ::toFixed(_s); }
// [NEW API] - Use this instead. // [NEW API] - Use this instead.
Q_INVOKABLE QString/*eth::u256*/ balanceAt(QString/*eth::Address*/ _a, int _block) const; Q_INVOKABLE QString/*eth::u256*/ balanceAt(QString/*eth::Address*/ _a, int _block) const;
@ -127,6 +134,8 @@ public:
Q_INVOKABLE QString doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice); Q_INVOKABLE QString doCreate(QString _secret, QString _amount, QString _init, QString _gas, QString _gasPrice);
Q_INVOKABLE void doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice); Q_INVOKABLE void doTransact(QString _secret, QString _amount, QString _dest, QString _data, QString _gas, QString _gasPrice);
Q_INVOKABLE void doTransact(QString _json);
Q_INVOKABLE QString doCall(QString _json);
Q_INVOKABLE unsigned newWatch(QString _json); Q_INVOKABLE unsigned newWatch(QString _json);
Q_INVOKABLE QString watchMessages(unsigned _w); Q_INVOKABLE QString watchMessages(unsigned _w);
@ -192,6 +201,8 @@ private:
frame->evaluateJavaScript("eth.watchPending = function() { return eth.makeWatch('pendingChanged') }"); \ frame->evaluateJavaScript("eth.watchPending = function() { return eth.makeWatch('pendingChanged') }"); \
frame->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { var v = eth.doCreate(s, v, c, g, p); if (f) f(v) }"); \ frame->evaluateJavaScript("eth.create = function(s, v, c, g, p, f) { var v = eth.doCreate(s, v, c, g, p); if (f) f(v) }"); \
frame->evaluateJavaScript("eth.transact = function(s, v, t, d, g, p, f) { eth.doTransact(s, v, t, d, g, p); if (f) f() }"); \ frame->evaluateJavaScript("eth.transact = function(s, v, t, d, g, p, f) { eth.doTransact(s, v, t, d, g, p); if (f) f() }"); \
frame->evaluateJavaScript("eth.transact = function(a, f) { eth.doTransactJson(JSON.stringify(a)); if (f) f() }"); \
frame->evaluateJavaScript("eth.call = function(a, f) { var ret = eth.doCallJson(JSON.stringify(a)); if (f) f(ret); return ret; }"); \
frame->evaluateJavaScript("eth.messages = function(a) { return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \ frame->evaluateJavaScript("eth.messages = function(a) { return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \
frame->evaluateJavaScript("eth.transactions = function(a) { env.warn('THIS CALL IS DEPRECATED. USE eth.messages INSTEAD.'); return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \ frame->evaluateJavaScript("eth.transactions = function(a) { env.warn('THIS CALL IS DEPRECATED. USE eth.messages INSTEAD.'); return JSON.parse(eth.getMessages(JSON.stringify(a))); }"); \
frame->evaluateJavaScript("String.prototype.pad = function(l, r) { return eth.pad(this, l, r) }"); \ frame->evaluateJavaScript("String.prototype.pad = function(l, r) { return eth.pad(this, l, r) }"); \
@ -199,6 +210,7 @@ private:
frame->evaluateJavaScript("String.prototype.unbin = function(l) { return eth.fromBinary(this) }"); \ frame->evaluateJavaScript("String.prototype.unbin = function(l) { return eth.fromBinary(this) }"); \
frame->evaluateJavaScript("String.prototype.unpad = function(l) { return eth.unpad(this) }"); \ frame->evaluateJavaScript("String.prototype.unpad = function(l) { return eth.unpad(this) }"); \
frame->evaluateJavaScript("String.prototype.dec = function() { return eth.toDecimal(this) }"); \ frame->evaluateJavaScript("String.prototype.dec = function() { return eth.toDecimal(this) }"); \
frame->evaluateJavaScript("String.prototype.fix = function() { return eth.toFixed(this) }"); \
frame->evaluateJavaScript("String.prototype.sha3 = function() { return eth.sha3(this) }"); \ frame->evaluateJavaScript("String.prototype.sha3 = function() { return eth.sha3(this) }"); \
} }

Loading…
Cancel
Save