diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index b6c2b00de..913a6e2e7 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -45,6 +45,7 @@ using eth::Executive;
// functions
using eth::toHex;
using eth::assemble;
+using eth::pushLiteral;
using eth::compileLisp;
using eth::disassemble;
using eth::formatBalance;
@@ -581,10 +582,8 @@ void Main::on_blocks_currentItemChanged()
s << "
Gas: " << tx.gas << "";
if (tx.isCreation())
{
- if (tx.init.size())
- s << "
Init
" << disassemble(tx.init);
if (tx.data.size())
- s << "Body
" << disassemble(tx.data);
+ s << "Code
" << disassemble(tx.data);
}
else
{
@@ -669,14 +668,15 @@ void Main::on_data_textChanged()
if (isCreation())
{
QString code = ui->data->toPlainText();
- m_init.clear();
+ bytes initBytes;
+ bytes bodyBytes;
auto init = code.indexOf("init:");
auto body = code.indexOf("body:");
if (body == -1)
body = code.indexOf("code:");
if (body == -1 && init == -1)
- m_data = compileLisp(code.toStdString(), true, m_init);
+ bodyBytes = compileLisp(code.toStdString(), true, initBytes);
else
{
init = (init == -1 ? 0 : (init + 5));
@@ -685,16 +685,37 @@ void Main::on_data_textChanged()
auto initCode = code.mid(init, initSize).trimmed();
auto bodyCode = code.mid(body).trimmed();
if (QRegExp("[^0-9a-fA-F]").indexIn(initCode) == -1)
- m_init = fromHex(initCode.toStdString());
+ initBytes = fromHex(initCode.toStdString());
else
- m_init = compileSerpent(initCode.toStdString());
+ initBytes = compileSerpent(initCode.toStdString());
if (QRegExp("[^0-9a-zA-Z]").indexIn(bodyCode) == -1)
- m_data = fromHex(bodyCode.toStdString());
+ bodyBytes = fromHex(bodyCode.toStdString());
else
- m_data = compileSerpent(bodyCode.toStdString());
+ bodyBytes = compileSerpent(bodyCode.toStdString());
}
- ui->code->setHtml((m_init.size() ? "Init
" + QString::fromStdString(disassemble(m_init)).toHtmlEscaped() : "") + "Body
" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped());
- ui->gas->setMinimum((qint64)state().createGas(m_data.size() + m_init.size(), 0));
+
+ m_data.clear();
+ if (initBytes.size())
+ m_data = initBytes;
+ if (bodyBytes.size())
+ {
+ unsigned s = bodyBytes.size();
+ auto ss = pushLiteral(m_data, s);
+ unsigned p = m_data.size() + 4 + 2 + 1 + ss + 2 + 1;
+ pushLiteral(m_data, p);
+ pushLiteral(m_data, 0);
+ m_data.push_back((byte)Instruction::CALLDATACOPY);
+ pushLiteral(m_data, s);
+ pushLiteral(m_data, 0);
+ m_data.push_back((byte)Instruction::RETURN);
+ while (m_data.size() < p)
+ m_data.push_back(0);
+ for (auto b: bodyBytes)
+ m_data.push_back(b);
+ }
+
+ ui->code->setHtml("Code
" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped());
+ ui->gas->setMinimum((qint64)state().createGas(m_data.size(), 0));
if (!ui->gas->isEnabled())
ui->gas->setValue(m_backupGas);
ui->gas->setEnabled(true);
@@ -861,7 +882,7 @@ void Main::on_send_clicked()
m_client->unlock();
Secret s = i.secret();
if (isCreation())
- m_client->transact(s, value(), m_data, m_init, ui->gas->value(), gasPrice());
+ m_client->transact(s, value(), m_data, ui->gas->value(), gasPrice());
else
m_client->transact(s, value(), fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice());
refresh();
@@ -891,16 +912,7 @@ void Main::on_debug_clicked()
t.gasPrice = gasPrice();
t.gas = ui->gas->value();
t.data = m_data;
- if (isCreation())
- {
- t.receiveAddress = Address();
- t.init = m_init;
- }
- else
- {
- t.receiveAddress = fromString(ui->destination->currentText());
- t.data = m_data;
- }
+ t.receiveAddress = isCreation() ? Address() : fromString(ui->destination->currentText());
t.sign(s);
auto r = t.rlp();
m_currentExecution->setup(&r);
@@ -942,14 +954,14 @@ void Main::debugFinished()
ui->debugMemory->setHtml("");
ui->debugStorage->setHtml("");
ui->debugStateInfo->setText("");
- ui->send->setEnabled(true);
+// ui->send->setEnabled(true);
ui->debugStep->setEnabled(false);
ui->debugPanel->setEnabled(false);
}
void Main::initDebugger()
{
- ui->send->setEnabled(false);
+// ui->send->setEnabled(false);
ui->debugStep->setEnabled(true);
ui->debugPanel->setEnabled(true);
ui->debugCode->setEnabled(false);
diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h
index 7e281c8c8..b61390416 100644
--- a/alethzero/MainWin.h
+++ b/alethzero/MainWin.h
@@ -113,7 +113,6 @@ private:
QList m_myKeys;
bool m_keysChanged = false;
eth::bytes m_data;
- eth::bytes m_init;
eth::Address m_nameReg;
unsigned m_backupGas;
diff --git a/libethereum/AddressState.h b/libethereum/AddressState.h
index 154858e07..9adbbb32c 100644
--- a/libethereum/AddressState.h
+++ b/libethereum/AddressState.h
@@ -59,6 +59,7 @@ public:
std::map const& memory() const { assert(m_type == AddressType::Contract && isComplete()); return m_memory; }
bytes const& code() const { assert(m_type == AddressType::Contract && isComplete()); return m_code; }
bool freshCode() const { return !m_codeHash && m_isComplete; }
+ void setCode(bytesConstRef _code) { assert(freshCode()); m_code = _code.toBytes(); }
private:
AddressType m_type;
diff --git a/libethereum/Client.cpp b/libethereum/Client.cpp
index c19efbe8d..7007ae91a 100644
--- a/libethereum/Client.cpp
+++ b/libethereum/Client.cpp
@@ -157,7 +157,7 @@ void Client::transact(Secret _secret, u256 _value, Address _dest, bytes const& _
m_changed = true;
}
-Address Client::transact(Secret _secret, u256 _endowment, bytes const& _code, bytes const& _init, u256 _gas, u256 _gasPrice)
+Address Client::transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice)
{
lock_guard l(m_lock);
Transaction t;
@@ -166,8 +166,7 @@ Address Client::transact(Secret _secret, u256 _endowment, bytes const& _code, by
t.gasPrice = _gasPrice;
t.gas = _gas;
t.receiveAddress = Address();
- t.data = _code;
- t.init = _init;
+ t.data = _init;
t.sign(_secret);
cnote << "New transaction " << t;
m_tq.attemptImport(t.rlp());
diff --git a/libethereum/Client.h b/libethereum/Client.h
index 0089b8a23..6075b0224 100644
--- a/libethereum/Client.h
+++ b/libethereum/Client.h
@@ -88,7 +88,7 @@ public:
/// Submits a new contract-creation transaction.
/// @returns the new contract's address (assuming it all goes through).
- Address transact(Secret _secret, u256 _endowment, bytes const& _code, bytes const& _init = bytes(), u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
+ Address transact(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas = 10000, u256 _gasPrice = 10 * szabo);
/// Makes the given call. Nothing is recorded into the state. TODO
// bytes call(Secret _secret, u256 _amount, u256 _gasPrice, Address _dest, u256 _gas, bytes _data = bytes());
diff --git a/libethereum/FeeStructure.cpp b/libethereum/FeeStructure.cpp
index c75835b49..f7dbbfbf8 100644
--- a/libethereum/FeeStructure.cpp
+++ b/libethereum/FeeStructure.cpp
@@ -33,3 +33,4 @@ u256 const eth::c_createGas = 100;
u256 const eth::c_callGas = 20;
u256 const eth::c_memoryGas = 1;
u256 const eth::c_txDataGas = 5;
+u256 const eth::c_txGas = 500;
diff --git a/libethereum/FeeStructure.h b/libethereum/FeeStructure.h
index c4f493954..42d6967aa 100644
--- a/libethereum/FeeStructure.h
+++ b/libethereum/FeeStructure.h
@@ -34,6 +34,7 @@ extern u256 const c_sstoreGas; ///< Once per non-zero storage element in a CRE
extern u256 const c_createGas; ///< Once per CREATE operation & contract-creation transaction.
extern u256 const c_callGas; ///< Once per CALL operation & message call transaction.
extern u256 const c_memoryGas; ///< Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
-extern u256 const c_txDataGas; ///< Per byte of data attached to a message-call transaction. NOTE: Not payable on data of calls between transactions.
+extern u256 const c_txDataGas; ///< Per byte of data attached to a transaction. NOTE: Not payable on data of calls between transactions.
+extern u256 const c_txGas; ///< Per transaction. NOTE: Not payable on data of calls between transactions.
}
diff --git a/libethereum/Instruction.cpp b/libethereum/Instruction.cpp
index 3d7db5c9e..1af9511ac 100644
--- a/libethereum/Instruction.cpp
+++ b/libethereum/Instruction.cpp
@@ -56,6 +56,7 @@ const std::map eth::c_instructions =
{ "CALLVALUE", Instruction::CALLVALUE },
{ "CALLDATALOAD", Instruction::CALLDATALOAD },
{ "CALLDATASIZE", Instruction::CALLDATASIZE },
+ { "CALLDATACOPY", Instruction::CALLDATACOPY },
{ "BASEFEE", Instruction::GASPRICE },
{ "PREVHASH", Instruction::PREVHASH },
{ "COINBASE", Instruction::COINBASE },
@@ -142,6 +143,7 @@ const std::map eth::c_instructionInfo =
{ Instruction::CALLVALUE, { "CALLVALUE", 0, 0, 1 } },
{ Instruction::CALLDATALOAD, { "CALLDATALOAD", 0, 1, 1 } },
{ Instruction::CALLDATASIZE, { "CALLDATASIZE", 0, 0, 1 } },
+ { Instruction::CALLDATACOPY, { "CALLDATACOPY", 0, 3, 0 } },
{ Instruction::GASPRICE, { "BASEFEE", 0, 0, 1 } },
{ Instruction::PREVHASH, { "PREVHASH", 0, 0, 1 } },
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1 } },
@@ -313,7 +315,7 @@ static void pushLocation(bytes& o_code, uint32_t _locationValue)
toBigEndian(_locationValue, r);
}
-static unsigned pushLiteral(bytes& o_code, u256 _literalValue)
+unsigned eth::pushLiteral(bytes& o_code, u256 _literalValue)
{
unsigned br = max(1, bytesRequired(_literalValue));
o_code.push_back((byte)Instruction::PUSH1 + br - 1);
diff --git a/libethereum/Instruction.h b/libethereum/Instruction.h
index 7fddec181..342076399 100644
--- a/libethereum/Instruction.h
+++ b/libethereum/Instruction.h
@@ -60,6 +60,7 @@ enum class Instruction: uint8_t
CALLVALUE,
CALLDATALOAD,
CALLDATASIZE,
+ CALLDATACOPY,
GASPRICE,
PREVHASH = 0x40,
@@ -146,4 +147,6 @@ std::string disassemble(bytes const& _mem);
/// Compile a Low-level Lisp-like Language program into EVM-code.
bytes compileLisp(std::string const& _code, bool _quiet, bytes& _init);
+unsigned pushLiteral(bytes& o_code, u256 _literalValue);
+
}
diff --git a/libethereum/PeerServer.cpp b/libethereum/PeerServer.cpp
index 1784ef49a..e86289d2c 100644
--- a/libethereum/PeerServer.cpp
+++ b/libethereum/PeerServer.cpp
@@ -115,7 +115,7 @@ PeerServer::~PeerServer()
unsigned PeerServer::protocolVersion()
{
- return 12;
+ return 13;
}
void PeerServer::determinePublic(string const& _publicAddress, bool _upnp)
diff --git a/libethereum/State.cpp b/libethereum/State.cpp
index 9a587915b..73cd4684c 100644
--- a/libethereum/State.cpp
+++ b/libethereum/State.cpp
@@ -631,11 +631,7 @@ void Executive::setup(bytesConstRef _rlp)
}
// Check gas cost is enough.
- u256 gasCost;
- if (m_t.isCreation())
- gasCost = (m_t.init.size() + m_t.data.size()) * c_txDataGas + c_createGas;
- else
- gasCost = m_t.data.size() * c_txDataGas + c_callGas;
+ u256 gasCost = m_t.data.size() * c_txDataGas + c_txGas;
if (m_t.gas < gasCost)
{
@@ -662,7 +658,7 @@ void Executive::setup(bytesConstRef _rlp)
m_s.subBalance(sender, cost);
if (m_t.isCreation())
- create(sender, m_t.value, m_t.gasPrice, m_t.gas - gasCost, &m_t.data, &m_t.init, sender);
+ create(sender, m_t.value, m_t.gasPrice, m_t.gas - gasCost, &m_t.data, sender);
else
call(m_t.receiveAddress, sender, m_t.value, m_t.gasPrice, bytesConstRef(&m_t.data), m_t.gas - gasCost, sender);
}
@@ -681,18 +677,18 @@ void Executive::call(Address _receiveAddress, Address _senderAddress, u256 _valu
m_endGas = _gas;
}
-void Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, bytesConstRef _init, Address _origin)
+void Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _init, Address _origin)
{
m_newAddress = right160(sha3(rlpList(_sender, m_s.transactionsFrom(_sender) - 1)));
while (m_s.isContractAddress(m_newAddress) || m_s.isNormalAddress(m_newAddress))
m_newAddress = (u160)m_newAddress + 1;
// Set up new account...
- m_s.m_cache[m_newAddress] = AddressState(0, 0, _code);
+ m_s.m_cache[m_newAddress] = AddressState(0, 0, bytesConstRef());
// Execute _init.
m_vm = new VM(_gas);
- m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init);
+ m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, _init, _init);
}
bool Executive::go(uint64_t _steps)
@@ -702,7 +698,7 @@ bool Executive::go(uint64_t _steps)
bool revert = false;
try
{
- m_vm->go(*m_ext, _steps);
+ m_out = m_vm->go(*m_ext, _steps);
m_endGas = m_vm->gas();
}
catch (StepsDone const&)
@@ -751,6 +747,10 @@ void Executive::finalize()
// cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")";
m_s.addBalance(m_ext->origin, m_endGas * m_ext->gasPrice);
+ if (m_t.isCreation() && m_newAddress && m_out.size())
+ // non-reverted creation - put code in place.
+ m_s.m_cache[m_newAddress].setCode(m_out);
+
u256 gasSpent = (m_startGas - m_endGas) * m_ext->gasPrice;
/* unsigned c_feesKept = 8;
u256 feesEarned = gasSpent - (gasSpent / c_feesKept);
@@ -763,78 +763,16 @@ void Executive::finalize()
void State::execute(bytesConstRef _rlp)
{
- // Entry point for a user-executed transaction.
- Transaction t(_rlp);
-
- auto sender = t.sender();
-
- // Avoid invalid transactions.
- auto nonceReq = transactionsFrom(sender);
- if (t.nonce != nonceReq)
+ Executive e(*this);
{
- clog(StateChat) << "Invalid Nonce.";
- throw InvalidNonce(nonceReq, t.nonce);
+ e.setup(_rlp);
+ e.go();
+ e.finalize();
}
- // Don't like transactions whose gas price is too low. NOTE: this won't stay here forever - it's just until we get a proper gas price discovery protocol going.
- if (t.gasPrice < 10 * szabo)
- {
- clog(StateChat) << "Offered gas-price is too low.";
- throw GasPriceTooLow();
- }
-
- // Check gas cost is enough.
- u256 gasCost;
- if (t.isCreation())
- gasCost = (t.init.size() + t.data.size()) * c_txDataGas + c_createGas;
- else
- gasCost = t.data.size() * c_txDataGas + c_callGas;
-
- if (t.gas < gasCost)
- {
- clog(StateChat) << "Not enough gas to pay for the transaction.";
- throw OutOfGas();
- }
-
- u256 cost = t.value + t.gas * t.gasPrice;
-
- // Avoid unaffordable transactions.
- if (balance(sender) < cost)
- {
- clog(StateChat) << "Not enough cash.";
- throw NotEnoughCash();
- }
-
- u256 gas = t.gas - gasCost;
-
- // Increment associated nonce for sender.
- noteSending(sender);
-
- // Pay...
-// cnote << "Paying" << formatBalance(cost) << "from sender (includes" << t.gas << "gas at" << formatBalance(t.gasPrice) << ")";
- subBalance(sender, cost);
-
- if (t.isCreation())
- create(sender, t.value, t.gasPrice, &gas, &t.data, &t.init);
- else
- call(t.receiveAddress, sender, t.value, t.gasPrice, bytesConstRef(&t.data), &gas, bytesRef());
-
-// cnote << "Refunding" << formatBalance(gas * t.gasPrice) << "to sender (=" << gas << "*" << formatBalance(t.gasPrice) << ")";
- addBalance(sender, gas * t.gasPrice);
-
- u256 gasSpent = (t.gas - gas) * t.gasPrice;
-/* unsigned c_feesKept = 8;
- u256 feesEarned = gasSpent - (gasSpent / c_feesKept);
- cnote << "Transferring" << (100.0 - 100.0 / c_feesKept) << "% of" << formatBalance(gasSpent) << "=" << formatBalance(feesEarned) << "to miner (" << formatBalance(gasSpent - feesEarned) << "is burnt).";
-*/
- u256 feesEarned = gasSpent;
-// cnote << "Transferring" << formatBalance(gasSpent) << "to miner.";
- addBalance(m_currentBlock.coinbaseAddress, feesEarned);
-
- // !!!!!!!!!!!!!!!!!!!!! If moving to use Executive, this still needs to be done - Executive won't do it.
// Add to the user-originated transactions that we've executed.
- m_transactions.push_back(t);
- m_transactionSet.insert(t.sha3());
+ m_transactions.push_back(e.t());
+ m_transactionSet.insert(e.t().sha3());
}
bool State::call(Address _receiveAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256* _gas, bytesRef _out, Address _originAddress)
@@ -885,7 +823,7 @@ bool State::call(Address _receiveAddress, Address _senderAddress, u256 _value, u
return true;
}
-h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, bytesConstRef _init, Address _origin)
+h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin)
{
if (!_origin)
_origin = _sender;
@@ -895,18 +833,17 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas,
newAddress = (u160)newAddress + 1;
// Set up new account...
- m_cache[newAddress] = AddressState(0, 0, _code);
+ m_cache[newAddress] = AddressState(0, 0, {});
// Execute _init.
VM vm(*_gas);
- ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init);
+ ExtVM evm(*this, newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code);
bool revert = false;
+ bytesConstRef out;
try
{
- /*auto out =*/ vm.go(evm);
- // Don't do anything with the output (yet).
- //memcpy(_out.data(), out.data(), std::min(out.size(), _out.size()));
+ out = vm.go(evm);
}
catch (OutOfGas const& /*_e*/)
{
@@ -926,13 +863,19 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas,
clog(StateChat) << "std::exception in VM: " << _e.what();
}
- // Write state out only in the case of a non-excepted transaction.
+ // Write state out only in the case of a non-out-of-gas transaction.
if (revert)
- {
evm.revert();
+
+ // Kill contract if there's no code.
+ if (out.empty())
+ {
m_cache.erase(newAddress);
newAddress = Address();
}
+ else
+ m_cache[newAddress].setCode(out);
+
*_gas = vm.gas();
diff --git a/libethereum/State.h b/libethereum/State.h
index e0dc6dae2..1895a6684 100644
--- a/libethereum/State.h
+++ b/libethereum/State.h
@@ -61,11 +61,13 @@ public:
~Executive();
void setup(bytesConstRef _transaction);
- void create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, bytesConstRef _init, Address _originAddress);
+ void create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress);
void call(Address _myAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress);
bool go(uint64_t _steps = (unsigned)-1);
void finalize();
+ Transaction const& t() const { return m_t; }
+
u256 gas() const;
bytesConstRef out() const { return m_out; }
@@ -244,7 +246,7 @@ private:
// We assume all instrinsic fees are paid up before this point.
/// Execute a contract-creation transaction.
- h160 create(Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, bytesConstRef _init, Address _originAddress = Address());
+ h160 create(Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = Address());
/// Execute a call.
/// @a _gas points to the amount of gas to use for the call, and will lower it accordingly.
@@ -309,12 +311,12 @@ public:
m_store->erase(_n);
}
- h160 create(u256 _endowment, u256* _gas, bytesConstRef _code, bytesConstRef _init)
+ h160 create(u256 _endowment, u256* _gas, bytesConstRef _code)
{
// Increment associated nonce for sender.
m_s.noteSending(myAddress);
- return m_s.create(myAddress, _endowment, gasPrice, _gas, _code, _init, origin);
+ return m_s.create(myAddress, _endowment, gasPrice, _gas, _code, origin);
}
bool call(Address _receiveAddress, u256 _txValue, bytesConstRef _txData, u256* _gas, bytesRef _out)
diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp
index 21b162ed4..828d85846 100644
--- a/libethereum/Transaction.cpp
+++ b/libethereum/Transaction.cpp
@@ -36,18 +36,12 @@ Transaction::Transaction(bytesConstRef _rlpData)
try
{
nonce = rlp[field = 0].toInt();
- value = rlp[field = 1].toInt();
- receiveAddress = rlp[field = 2].toHash();
- gasPrice = rlp[field = 3].toInt();
- gas = rlp[field = 4].toInt();
+ gasPrice = rlp[field = 1].toInt();
+ gas = rlp[field = 2].toInt();
+ receiveAddress = rlp[field = 3].toHash();
+ value = rlp[field = 4].toInt();
data = rlp[field = 5].toBytes();
- if (isCreation())
- {
- init = rlp[field = 6].toBytes();
- vrs = Signature{ rlp[field = 7].toInt(), rlp[field = 8].toInt(), rlp[field = 9].toInt() };
- }
- else
- vrs = Signature{ rlp[field = 6].toInt(), rlp[field = 7].toInt(), rlp[field = 8].toInt() };
+ vrs = Signature{ rlp[field = 6].toInt(), rlp[field = 7].toInt(), rlp[field = 8].toInt() };
}
catch (RLPException const&)
{
@@ -119,10 +113,8 @@ void Transaction::sign(Secret _priv)
void Transaction::fillStream(RLPStream& _s, bool _sig) const
{
- _s.appendList((_sig ? 3 : 0) + (isCreation() ? 7 : 6));
- _s << nonce << value << receiveAddress << gasPrice << gas << data;
- if (isCreation())
- _s << init;
+ _s.appendList((_sig ? 3 : 0) + 6);
+ _s << nonce << gasPrice << gas << receiveAddress << value << data;
if (_sig)
_s << vrs.v << vrs.r << vrs.s;
}
diff --git a/libethereum/Transaction.h b/libethereum/Transaction.h
index 7d557b6fa..fe37f2ee8 100644
--- a/libethereum/Transaction.h
+++ b/libethereum/Transaction.h
@@ -52,8 +52,7 @@ struct Transaction
u256 gasPrice; ///< The base fee and thus the implied exchange rate of ETH to GAS.
u256 gas; ///< The total gas to convert, paid for from sender's account. Any unused gas gets refunded once the contract is ended.
- bytes data; ///< The data associated with the transaction, or the main body if it's a creation transaction.
- bytes init; ///< The initialisation associated with the transaction.
+ bytes data; ///< The data associated with the transaction, or the initialiser if it's a creation transaction.
Signature vrs; ///< The signature of the transaction. Encodes the sender.
diff --git a/libethereum/VM.h b/libethereum/VM.h
index 64095725b..da2a7aef8 100644
--- a/libethereum/VM.h
+++ b/libethereum/VM.h
@@ -133,6 +133,10 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, uint64_t _steps)
runGas = c_sha3Gas;
newTempSize = (unsigned)m_stack.back() + (unsigned)m_stack[m_stack.size() - 2];
break;
+ case Instruction::CALLDATACOPY:
+ require(3);
+ newTempSize = (unsigned)m_stack.back() + (unsigned)m_stack[m_stack.size() - 3];
+ break;
case Instruction::BALANCE:
runGas = c_balanceGas;
@@ -147,19 +151,10 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, uint64_t _steps)
case Instruction::CREATE:
{
require(3);
-
- u256 gas = (unsigned)m_stack[m_stack.size() - 1];
unsigned inOff = (unsigned)m_stack[m_stack.size() - 2];
unsigned inSize = (unsigned)m_stack[m_stack.size() - 3];
newTempSize = inOff + inSize;
-
- unsigned wc = std::min(inSize / 32 * 32 + inOff, (unsigned)m_temp.size());
- unsigned nonZero = 0;
- for (unsigned i = inOff; i < wc; i += 32)
- if (!!*(h256*)(m_temp.data() + inOff))
- nonZero++;
-
- runGas += c_createGas + nonZero * c_sstoreGas + gas;
+ runGas += c_createGas;
break;
}
@@ -324,6 +319,18 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, uint64_t _steps)
case Instruction::CALLDATASIZE:
m_stack.push_back(_ext.data.size());
break;
+ case Instruction::CALLDATACOPY:
+ {
+ 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();
+ memcpy(m_temp.data() + mf, _ext.data.data() + cf, l);
+ break;
+ }
case Instruction::GASPRICE:
m_stack.push_back(_ext.gasPrice);
break;
@@ -477,14 +484,10 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, uint64_t _steps)
break;
case Instruction::CREATE:
{
- require(5);
+ require(3);
u256 endowment = m_stack.back();
m_stack.pop_back();
- unsigned codeOff = (unsigned)m_stack.back();
- m_stack.pop_back();
- unsigned codeSize = (unsigned)m_stack.back();
- m_stack.pop_back();
unsigned initOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned initSize = (unsigned)m_stack.back();
@@ -493,7 +496,7 @@ template eth::bytesConstRef eth::VM::go(Ext& _ext, uint64_t _steps)
if (_ext.balance(_ext.myAddress) >= endowment)
{
_ext.subBalance(endowment);
- m_stack.push_back((u160)_ext.create(endowment, &m_gas, bytesConstRef(m_temp.data() + codeOff, codeSize), bytesConstRef(m_temp.data() + initOff, initSize)));
+ m_stack.push_back((u160)_ext.create(endowment, &m_gas, bytesConstRef(m_temp.data() + initOff, initSize)));
}
else
m_stack.push_back(0);
diff --git a/libqethereum/QEthereum.cpp b/libqethereum/QEthereum.cpp
index 54ae9e9f1..e2c7f12c1 100644
--- a/libqethereum/QEthereum.cpp
+++ b/libqethereum/QEthereum.cpp
@@ -166,9 +166,9 @@ unsigned QmlEthereum::peerCount() const
return (unsigned)client()->peerCount();
}
-void QmlEthereum::transact(Secret _secret, u256 _amount, u256 _gasPrice, u256 _gas, QByteArray _code, QByteArray _init)
+void QmlEthereum::transact(Secret _secret, u256 _amount, u256 _gasPrice, u256 _gas, QByteArray _init)
{
- client()->transact(_secret, _amount, bytes(_code.data(), _code.data() + _code.size()), bytes(_init.data(), _init.data() + _init.size()), _gas, _gasPrice);
+ client()->transact(_secret, _amount, bytes(_init.data(), _init.data() + _init.size()), _gas, _gasPrice);
}
void QmlEthereum::transact(Secret _secret, Address _dest, u256 _amount, u256 _gasPrice, u256 _gas, QByteArray _data)
@@ -307,9 +307,9 @@ unsigned QEthereum::peerCount() const
return (unsigned)client()->peerCount();
}
-QVariant QEthereum::create(QVariant _secret, QVariant _amount, QByteArray _code, QByteArray _init, QVariant _gas, QVariant _gasPrice)
+QVariant QEthereum::create(QVariant _secret, QVariant _amount, QByteArray _init, QVariant _gas, QVariant _gasPrice)
{
- return toQJS(client()->transact(to(_secret), to(_amount), bytes(_code.data(), _code.data() + _code.size()), bytes(_init.data(), _init.data() + _init.size()), to(_gas), to(_gasPrice)));
+ return toQJS(client()->transact(to(_secret), to(_amount), bytes(_init.data(), _init.data() + _init.size()), to(_gas), to(_gasPrice)));
}
void QEthereum::transact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice)
diff --git a/libqethereum/QEthereum.h b/libqethereum/QEthereum.h
index de35aaaa8..23dc0c248 100644
--- a/libqethereum/QEthereum.h
+++ b/libqethereum/QEthereum.h
@@ -140,7 +140,7 @@ public:
public slots:
void transact(eth::Secret _secret, eth::Address _dest, eth::u256 _amount, eth::u256 _gasPrice, eth::u256 _gas, QByteArray _data);
- void transact(eth::Secret _secret, eth::u256 _amount, eth::u256 _gasPrice, eth::u256 _gas, QByteArray _code, QByteArray _init);
+ void transact(eth::Secret _secret, eth::u256 _amount, eth::u256 _gasPrice, eth::u256 _gas, QByteArray _init);
void setCoinbase(eth::Address);
void setMining(bool _l);
@@ -314,7 +314,7 @@ public:
Q_INVOKABLE QEthereum* self() { return this; }
- Q_INVOKABLE QVariant create(QVariant _secret, QVariant _amount, QByteArray _code, QByteArray _init, QVariant _gas, QVariant _gasPrice);
+ Q_INVOKABLE QVariant create(QVariant _secret, QVariant _amount, QByteArray _init, QVariant _gas, QVariant _gasPrice);
Q_INVOKABLE void transact(QVariant _secret, QVariant _amount, QVariant _dest, QByteArray _data, QVariant _gas, QVariant _gasPrice);
eth::u256 balanceAt(eth::Address _a) const;
diff --git a/neth/main.cpp b/neth/main.cpp
index 2c1a00914..73612e203 100644
--- a/neth/main.cpp
+++ b/neth/main.cpp
@@ -707,17 +707,14 @@ int main(int argc, char** argv)
cwarn << "No code submitted";
else
{
- bytes code = fromHex(scode);
cnote << "Assembled:";
stringstream ssc;
- ssc << disassemble(code);
- cnote << ssc.str();
bytes init = fromHex(sinit);
ssc.str(string());
ssc << disassemble(init);
cnote << "Init:";
cnote << ssc.str();
- c.transact(us.secret(), endowment, code, init, gas, gasPrice);
+ c.transact(us.secret(), endowment, init, gas, gasPrice);
}
}
}
diff --git a/test/vm.cpp b/test/vm.cpp
index 7d8501d35..abed42f77 100644
--- a/test/vm.cpp
+++ b/test/vm.cpp
@@ -70,14 +70,13 @@ public:
txs.push_back(_t);
}
}
- h160 create(u256 _endowment, u256* _gas, bytesConstRef _code, bytesConstRef _init)
+ h160 create(u256 _endowment, u256* _gas, bytesConstRef _init)
{
Transaction t;
t.value = _endowment;
t.gasPrice = gasPrice;
t.gas = *_gas;
- t.data = _code.toBytes();
- t.init = _init.toBytes();
+ t.data = _init.toBytes();
txs.push_back(t);
return right160(t.sha3(false));
}