Browse Source

POST for PoC-6

cl-refactor
Gav Wood 11 years ago
parent
commit
b902b3e701
  1. 1
      alethzero/MainWin.cpp
  2. 15
      eth/main.cpp
  3. 6
      libethereum/Client.cpp
  4. 12
      libethereum/Executive.cpp
  5. 2
      libethereum/Executive.h
  6. 18
      libethereum/ExtVM.h
  7. 10
      libethereum/Miner.h
  8. 2
      libethereum/PeerSession.cpp
  9. 10
      libethereum/State.cpp
  10. 5
      libethereum/State.h
  11. 17
      libevm/ExtVMFace.h
  12. 29
      libevm/VM.h
  13. 2
      libevmface/Instruction.cpp
  14. 1
      libevmface/Instruction.h

1
alethzero/MainWin.cpp

@ -1247,6 +1247,7 @@ void Main::populateDebugger(eth::bytesConstRef _r)
m_history.append(WorldState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), lastHash, lastDataHash, vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
};
m_currentExecution->go(onOp);
m_currentExecution->finalize(onOp);
initDebugger();
updateDebugger();
}

15
eth/main.cpp

@ -597,8 +597,9 @@ int main(int argc, char** argv)
bytes r = t.rlp();
e.setup(&r);
OnOpFunc oof;
if (format == "pretty")
e.go([&](uint64_t steps, Instruction instr, bigint newMemSize, bigint gasCost, void* vvm, void const* vextVM)
oof = [&](uint64_t steps, Instruction instr, bigint newMemSize, bigint gasCost, void* vvm, void const* vextVM)
{
eth::VM* vm = (VM*)vvm;
eth::ExtVM const* ext = (ExtVM const*)vextVM;
@ -610,16 +611,16 @@ int main(int argc, char** argv)
for (auto const& i: ext->state().storage(ext->myAddress))
f << showbase << hex << i.first << ": " << i.second << endl;
f << dec << ext->level << " | " << ext->myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm->curPC() << " : " << c_instructionInfo.at(instr).name << " | " << dec << vm->gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32";
});
};
else if (format == "standard")
e.go([&](uint64_t, Instruction instr, bigint, bigint, void* vvm, void const* vextVM)
oof = [&](uint64_t, Instruction instr, bigint, bigint, void* vvm, void const* vextVM)
{
eth::VM* vm = (VM*)vvm;
eth::ExtVM const* ext = (ExtVM const*)vextVM;
f << ext->myAddress << " " << hex << toHex(eth::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(eth::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(eth::toCompactBigEndian((uint64_t)vm->gas(), 1)) << endl;
});
};
else if (format == "standard+")
e.go([&](uint64_t, Instruction instr, bigint, bigint, void* vvm, void const* vextVM)
oof = [&](uint64_t, Instruction instr, bigint, bigint, void* vvm, void const* vextVM)
{
eth::VM* vm = (VM*)vvm;
eth::ExtVM const* ext = (ExtVM const*)vextVM;
@ -627,7 +628,9 @@ int main(int argc, char** argv)
for (auto const& i: ext->state().storage(ext->myAddress))
f << toHex(eth::toCompactBigEndian(i.first, 1)) << " " << toHex(eth::toCompactBigEndian(i.second, 1)) << endl;
f << ext->myAddress << " " << hex << toHex(eth::toCompactBigEndian(vm->curPC(), 1)) << " " << hex << toHex(eth::toCompactBigEndian((int)(byte)instr, 1)) << " " << hex << toHex(eth::toCompactBigEndian((uint64_t)vm->gas(), 1)) << endl;
});
};
e.go(oof);
e.finalize(oof);
}
}
else if (cmd == "inspect")

6
libethereum/Client.cpp

@ -115,7 +115,7 @@ void Client::clearPending()
appendFromNewPending(m_postMine.bloom(i), changeds);
changeds.insert(PendingChangedFilter);
m_postMine = m_preMine;
m_miner.restart();
m_miner.noteStateChange();
noteChanged(changeds);
}
@ -425,7 +425,7 @@ void Client::work()
changeds.insert(ChainChangedFilter);
//changeds.insert(PendingChangedFilter); // if we mined the new block, then we've probably reset the pending transactions.
}
m_miner.restart();
m_miner.noteStateChange();
}
// Synchronise state to block chain.
@ -476,7 +476,7 @@ void Client::work()
}
if (rsm)
m_miner.restart();
m_miner.noteStateChange();
}
cwork << "noteChanged" << changeds.size() << "items";

12
libethereum/Executive.cpp

@ -217,21 +217,19 @@ u256 Executive::gas() const
return m_vm ? m_vm->gas() : m_endGas;
}
void Executive::finalize()
void Executive::finalize(OnOpFunc const& _onOp)
{
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);
if (m_ext)
m_endGas += m_ext->doPosts(_onOp);
// cnote << "Refunding" << formatBalance(m_endGas * m_ext->gasPrice) << "to origin (=" << m_endGas << "*" << formatBalance(m_ext->gasPrice) << ")";
m_s.addBalance(m_sender, m_endGas * m_t.gasPrice);
u256 gasSpentInEth = (m_t.gas - m_endGas) * m_t.gasPrice;
/* unsigned c_feesKept = 8;
u256 feesEarned = gasSpentInEth - (gasSpentInEth / c_feesKept);
cnote << "Transferring" << (100.0 - 100.0 / c_feesKept) << "% of" << formatBalance(gasSpent) << "=" << formatBalance(feesEarned) << "to miner (" << formatBalance(gasSpentInEth - feesEarned) << "is burnt).";
*/
u256 feesEarned = gasSpentInEth;
u256 feesEarned = (m_t.gas - m_endGas) * m_t.gasPrice;
// cnote << "Transferring" << formatBalance(gasSpent) << "to miner.";
m_s.addBalance(m_s.m_currentBlock.coinbaseAddress, feesEarned);

2
libethereum/Executive.h

@ -48,7 +48,7 @@ public:
bool create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress);
bool call(Address _myAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress);
bool go(OnOpFunc const& _onOp = OnOpFunc());
void finalize();
void finalize(OnOpFunc const& _onOp = OnOpFunc());
u256 gasUsed() const;
static OnOpFunc simpleTrace();

18
libethereum/ExtVM.h

@ -56,7 +56,7 @@ public:
m_s.noteSending(myAddress);
if (m_ms)
m_ms->internal.resize(m_ms->internal.size() + 1);
auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _code, origin, &suicides, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, level + 1);
auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _code, origin, &suicides, &posts, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, level + 1);
if (m_ms && !m_ms->internal.back().from)
m_ms->internal.pop_back();
return ret;
@ -67,7 +67,7 @@ public:
{
if (m_ms)
m_ms->internal.resize(m_ms->internal.size() + 1);
auto ret = m_s.call(_receiveAddress, myAddress, _txValue, gasPrice, _txData, _gas, _out, origin, &suicides, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, level + 1);
auto ret = m_s.call(_receiveAddress, myAddress, _txValue, gasPrice, _txData, _gas, _out, origin, &suicides, &posts, m_ms ? &(m_ms->internal.back()) : nullptr, _onOp, level + 1);
if (m_ms && !m_ms->internal.back().from)
m_ms->internal.pop_back();
return ret;
@ -93,6 +93,20 @@ public:
/// @TODO check call site for the parent manifest being discarded.
void revert() { if (m_ms) *m_ms = Manifest(); m_s.m_cache = m_origCache; }
/// Execute any posts we have left.
u256 doPosts(OnOpFunc const& _onOp = OnOpFunc())
{
u256 ret;
while (posts.size())
{
Post& p = posts.front();
call(p.to, p.value, &p.data, &p.gas, bytesRef(), _onOp);
ret += p.gas;
posts.pop_front();
}
return ret;
}
State& state() const { return m_s; }
/// @note not a part of the main API; just for use by tracing/debug stuff.

10
libethereum/Miner.h

@ -61,7 +61,7 @@ public:
/**
* @brief Implements Miner.
* To begin mining, use start() & stop(). restart() can be used to reset the mining and set up the
* To begin mining, use start() & stop(). noteStateChange() can be used to reset the mining and set up the
* State object according to the host. Use isRunning() to determine if the miner has been start()ed.
* Use isComplete() to determine if the miner has finished mining.
*
@ -69,7 +69,7 @@ public:
*
* Information on the mining can be queried through miningProgress() and miningHistory().
* @threadsafe
* @todo signal from child->parent thread to wait on exit; refactor redundant dagger/miner stats
* @todo Signal Miner to restart once with condition variables.
*/
class Miner
{
@ -86,8 +86,8 @@ public:
/// Stop mining.
void stop();
/// Restart mining (and start if not already running).
void restart() { start(); m_miningStatus = Preparing; }
/// Call to notify Miner of a state change.
void noteStateChange() { m_miningStatus = Preparing; }
/// @returns true iff the mining has been start()ed. It may still not be actually mining, depending on the host's turbo() & force().
bool isRunning() { return !!m_work; }
@ -109,7 +109,7 @@ private:
void work();
MinerHost* m_host; ///< Our host.
unsigned m_id; ///< Our identity;
unsigned m_id; ///< Our identity.
std::mutex x_work; ///< Mutex protecting the creation of the work thread.
std::unique_ptr<std::thread> m_work; ///< The work thread.

2
libethereum/PeerSession.cpp

@ -184,7 +184,7 @@ bool PeerSession::interpret(RLP const& _r)
if (isPrivateAddress(peerAddress))
goto CONTINUE;
clogS(NetAllDetail) << "Checking: " << ep << "(" << toHex(id.ref().cropped(0, 4)) << ")";
clogS(NetAllDetail) << "Checking: " << ep << "(" << id.abridged() << ")";
// check that it's not us or one we already know:
if (id && (m_server->m_key.pub() == id || m_server->havePeer(id) || m_server->m_incomingPeers.count(id)))

10
libethereum/State.cpp

@ -1024,7 +1024,7 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit)
return e.gasUsed();
}
bool State::call(Address _receiveAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256* _gas, bytesRef _out, Address _originAddress, std::set<Address>* o_suicides, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level)
bool State::call(Address _receiveAddress, Address _senderAddress, u256 _value, u256 _gasPrice, bytesConstRef _data, u256* _gas, bytesRef _out, Address _originAddress, std::set<Address>* o_suicides, PostList* o_posts, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level)
{
if (!_originAddress)
_originAddress = _senderAddress;
@ -1053,6 +1053,9 @@ bool State::call(Address _receiveAddress, Address _senderAddress, u256 _value, u
if (o_suicides)
for (auto i: evm.suicides)
o_suicides->insert(i);
if (o_posts)
for (auto i: evm.posts)
o_posts->push_back(i);
if (o_ms)
o_ms->output = out.toBytes();
}
@ -1085,7 +1088,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, Address _origin, std::set<Address>* o_suicides, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level)
h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, std::set<Address>* o_suicides, PostList* o_posts, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level)
{
if (!_origin)
_origin = _sender;
@ -1119,6 +1122,9 @@ h160 State::create(Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas,
if (o_suicides)
for (auto i: evm.suicides)
o_suicides->insert(i);
if (o_posts)
for (auto i: evm.posts)
o_posts->push_back(i);
}
catch (OutOfGas const& /*_e*/)
{

5
libethereum/State.h

@ -307,12 +307,12 @@ 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, Address _originAddress = Address(), std::set<Address>* o_suicides = nullptr, Manifest* o_ms = nullptr, OnOpFunc const& _onOp = OnOpFunc(), unsigned _level = 0);
h160 create(Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = Address(), std::set<Address>* o_suicides = nullptr, PostList* o_posts = nullptr, Manifest* o_ms = nullptr, OnOpFunc const& _onOp = OnOpFunc(), unsigned _level = 0);
/// Execute a call.
/// @a _gas points to the amount of gas to use for the call, and will lower it accordingly.
/// @returns false if the call ran out of gas before completion. true otherwise.
bool call(Address _myAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256* _gas, bytesRef _out, Address _originAddress = Address(), std::set<Address>* o_suicides = nullptr, Manifest* o_ms = nullptr, OnOpFunc const& _onOp = OnOpFunc(), unsigned _level = 0);
bool call(Address _myAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256* _gas, bytesRef _out, Address _originAddress = Address(), std::set<Address>* o_suicides = nullptr, PostList* o_posts = nullptr, Manifest* o_ms = nullptr, OnOpFunc const& _onOp = OnOpFunc(), unsigned _level = 0);
/// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock).
void resetCurrent();
@ -332,7 +332,6 @@ private:
TrieDB<Address, OverlayDB> m_state; ///< Our state tree, as an OverlayDB DB.
std::vector<TransactionReceipt> m_transactions; ///< The current list of transactions that we've included in the state.
std::set<h256> m_transactionSet; ///< The set of transaction hashes that we've included in the state.
// GenericTrieDB<OverlayDB> m_transactionManifest; ///< The transactions trie; saved from the last commitToMine, or invalid/empty if commitToMine was never called.
OverlayDB m_lastTx;
mutable std::map<Address, AddressState> m_cache; ///< Our address cache. This stores the states of each address that has (or at least might have) been changed.

17
libevm/ExtVMFace.h

@ -29,6 +29,16 @@
namespace eth
{
struct Post
{
Address to;
u256 value;
bytes data;
u256 gas;
};
using PostList = std::list<Post>;
/**
* @brief A null implementation of the class for specifying VM externalities.
*/
@ -68,9 +78,15 @@ public:
/// Make a new message call.
bool call(Address, u256, bytesConstRef, u256*, bytesRef) { return false; }
/// Post a new message call.
void post(Address _to, u256 _value, bytesConstRef _data, u256 _gas) { posts.push_back(Post({_to, _value, _data.toBytes(), _gas})); }
/// Revert any changes made (by any of the other calls).
void revert() {}
/// Execute any posts that may exist, including those that are incurred as a result of earlier posts.
void doPosts() {}
Address myAddress; ///< Address associated with executing code (a contract, or contract-to-be).
Address caller; ///< Address which sent the message (either equal to origin or a contract).
Address origin; ///< Original transactor.
@ -81,6 +97,7 @@ public:
BlockInfo previousBlock; ///< The previous block's information.
BlockInfo currentBlock; ///< The current block's information.
std::set<Address> suicides; ///< Any accounts that have suicided.
std::list<Post> posts; ///< Any posts that have been made.
};
typedef std::function<void(uint64_t /*steps*/, Instruction /*instr*/, bigint /*newMemSize*/, bigint /*gasCost*/, void/*VM*/*, void/*ExtVM*/ const*)> OnOpFunc;

29
libevm/VM.h

@ -164,6 +164,12 @@ template <class Ext> eth::bytesConstRef eth::VM::go(Ext& _ext, OnOpFunc const& _
newTempSize = std::max(m_stack[m_stack.size() - 6] + m_stack[m_stack.size() - 7], m_stack[m_stack.size() - 4] + m_stack[m_stack.size() - 5]);
break;
case Instruction::POST:
require(5);
runGas = c_callGas + m_stack[m_stack.size() - 1];
newTempSize = m_stack[m_stack.size() - 4] + m_stack[m_stack.size() - 5];
break;
case Instruction::CREATE:
{
require(3);
@ -622,6 +628,29 @@ template <class Ext> eth::bytesConstRef eth::VM::go(Ext& _ext, OnOpFunc const& _
}
case Instruction::STOP:
return bytesConstRef();
case Instruction::POST:
{
require(5);
u256 gas = m_stack.back();
m_stack.pop_back();
u160 receiveAddress = asAddress(m_stack.back());
m_stack.pop_back();
u256 value = m_stack.back();
m_stack.pop_back();
unsigned inOff = (unsigned)m_stack.back();
m_stack.pop_back();
unsigned inSize = (unsigned)m_stack.back();
m_stack.pop_back();
if (_ext.balance(_ext.myAddress) >= value)
{
_ext.subBalance(value);
_ext.post(receiveAddress, value, bytesConstRef(m_temp.data() + inOff, inSize), gas);
}
break;
}
default:
throw BadInstruction();
}

2
libevmface/Instruction.cpp

@ -145,6 +145,7 @@ const std::map<std::string, Instruction> eth::c_instructions =
{ "CREATE", Instruction::CREATE },
{ "CALL", Instruction::CALL },
{ "RETURN", Instruction::RETURN },
{ "POST", Instruction::POST },
{ "SUICIDE", Instruction::SUICIDE }
};
@ -268,6 +269,7 @@ const std::map<Instruction, InstructionInfo> eth::c_instructionInfo =
{ Instruction::CREATE, { "CREATE", 0, 3, 1 } },
{ Instruction::CALL, { "CALL", 0, 7, 1 } },
{ Instruction::RETURN, { "RETURN", 0, 2, 0 } },
{ Instruction::POST, { "POST", 0, 5, 0 } },
{ Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} }
};

1
libevmface/Instruction.h

@ -162,6 +162,7 @@ enum class Instruction: uint8_t
CREATE = 0xf0,
CALL,
RETURN,
POST,
SUICIDE = 0xff
};

Loading…
Cancel
Save