|
|
@ -40,10 +40,8 @@ namespace dev |
|
|
|
namespace mix |
|
|
|
{ |
|
|
|
|
|
|
|
// TODO: merge as much as possible with the Client.cpp into a mutually inherited base class.
|
|
|
|
|
|
|
|
const Secret c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); |
|
|
|
const u256 c_mixGenesisDifficulty = c_minimumDifficulty; //TODO: make it lower for Mix somehow
|
|
|
|
Secret const c_defaultUserAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); |
|
|
|
u256 const c_mixGenesisDifficulty = c_minimumDifficulty; //TODO: make it lower for Mix somehow
|
|
|
|
|
|
|
|
bytes MixBlockChain::createGenesisBlock(h256 _stateRoot) |
|
|
|
{ |
|
|
@ -100,9 +98,18 @@ void MixClient::resetState(std::map<Secret, u256> _accounts) |
|
|
|
m_executions.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _call) |
|
|
|
Transaction MixClient::replaceGas(Transaction const& _t, Secret const& _secret, u256 const& _gas) |
|
|
|
{ |
|
|
|
if (_t.isCreation()) |
|
|
|
return Transaction(_t.value(), _t.gasPrice(), _gas, _t.data(), _t.nonce(), _secret); |
|
|
|
else |
|
|
|
return Transaction(_t.value(), _t.gasPrice(), _gas, _t.receiveAddress(), _t.data(), _t.nonce(), _secret); |
|
|
|
} |
|
|
|
|
|
|
|
void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _call, bool _gasAuto, Secret const& _secret) |
|
|
|
{ |
|
|
|
bytes rlp = _t.rlp(); |
|
|
|
Transaction t = _gasAuto ? replaceGas(_t, _secret, m_state.gasLimitRemaining()) : _t; |
|
|
|
bytes rlp = t.rlp(); |
|
|
|
|
|
|
|
// do debugging run first
|
|
|
|
LastHashes lastHashes(256); |
|
|
@ -167,6 +174,31 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c |
|
|
|
|
|
|
|
execution.go(onOp); |
|
|
|
execution.finalize(); |
|
|
|
dev::eth::ExecutionResult er = execution.executionResult(); |
|
|
|
|
|
|
|
switch (er.excepted) |
|
|
|
{ |
|
|
|
case TransactionException::None: |
|
|
|
break; |
|
|
|
case TransactionException::NotEnoughCash: |
|
|
|
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Insufficient balance for contract deployment")); |
|
|
|
case TransactionException::OutOfGasBase: |
|
|
|
case TransactionException::OutOfGas: |
|
|
|
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas")); |
|
|
|
case TransactionException::BlockGasLimitReached: |
|
|
|
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Block gas limit reached")); |
|
|
|
case TransactionException::OutOfStack: |
|
|
|
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Out of stack")); |
|
|
|
case TransactionException::StackUnderflow: |
|
|
|
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Stack underflow")); |
|
|
|
//these should not happen in mix
|
|
|
|
case TransactionException::Unknown: |
|
|
|
case TransactionException::BadInstruction: |
|
|
|
case TransactionException::BadJumpDestination: |
|
|
|
case TransactionException::InvalidSignature: |
|
|
|
case TransactionException::InvalidNonce: |
|
|
|
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Internal execution error")); |
|
|
|
}; |
|
|
|
|
|
|
|
ExecutionResult d; |
|
|
|
d.result = execution.executionResult(); |
|
|
@ -176,6 +208,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c |
|
|
|
d.address = _t.receiveAddress(); |
|
|
|
d.sender = _t.sender(); |
|
|
|
d.value = _t.value(); |
|
|
|
d.gasUsed = er.gasUsed + er.gasRefunded; |
|
|
|
if (_t.isCreation()) |
|
|
|
d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce()))); |
|
|
|
if (!_call) |
|
|
@ -185,9 +218,11 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c |
|
|
|
// execute on a state
|
|
|
|
if (!_call) |
|
|
|
{ |
|
|
|
dev::eth::ExecutionResult er =_state.execute(lastHashes, _t); |
|
|
|
if (_t.isCreation() && _state.code(d.contractAddress).empty()) |
|
|
|
t = _gasAuto ? replaceGas(_t, _secret, d.gasUsed) : _t; |
|
|
|
er =_state.execute(lastHashes, t); |
|
|
|
if (t.isCreation() && _state.code(d.contractAddress).empty()) |
|
|
|
BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Not enough gas for contract deployment")); |
|
|
|
d.gasUsed = er.gasUsed + er.gasRefunded + er.gasForDeposit; |
|
|
|
// collect watches
|
|
|
|
h256Set changed; |
|
|
|
Guard l(x_filtersWatches); |
|
|
@ -242,25 +277,25 @@ State MixClient::asOf(h256 const& _block) const |
|
|
|
return State(m_stateDB, bc(), _block); |
|
|
|
} |
|
|
|
|
|
|
|
void MixClient::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) |
|
|
|
void MixClient::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, bool _gasAuto) |
|
|
|
{ |
|
|
|
WriteGuard l(x_state); |
|
|
|
u256 n = m_state.transactionsFrom(toAddress(_secret)); |
|
|
|
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); |
|
|
|
executeTransaction(t, m_state, false); |
|
|
|
executeTransaction(t, m_state, false, _gasAuto, _secret); |
|
|
|
} |
|
|
|
|
|
|
|
Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) |
|
|
|
Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice, bool _gasAuto) |
|
|
|
{ |
|
|
|
WriteGuard l(x_state); |
|
|
|
u256 n = m_state.transactionsFrom(toAddress(_secret)); |
|
|
|
eth::Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret); |
|
|
|
executeTransaction(t, m_state, false); |
|
|
|
executeTransaction(t, m_state, false, _gasAuto, _secret); |
|
|
|
Address address = right160(sha3(rlpList(t.sender(), t.nonce()))); |
|
|
|
return address; |
|
|
|
} |
|
|
|
|
|
|
|
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) |
|
|
|
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber, bool _gasAuto) |
|
|
|
{ |
|
|
|
(void)_blockNumber; |
|
|
|
State temp = asOf(eth::PendingBlock); |
|
|
@ -268,10 +303,25 @@ dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _ |
|
|
|
Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); |
|
|
|
bytes rlp = t.rlp(); |
|
|
|
WriteGuard lw(x_state); //TODO: lock is required only for last execution state
|
|
|
|
executeTransaction(t, temp, true); |
|
|
|
executeTransaction(t, temp, true, _gasAuto, _secret); |
|
|
|
return lastExecution().result; |
|
|
|
} |
|
|
|
|
|
|
|
void MixClient::submitTransaction(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) |
|
|
|
{ |
|
|
|
submitTransaction(_secret, _value, _dest, _data, _gas, _gasPrice, false); |
|
|
|
} |
|
|
|
|
|
|
|
Address MixClient::submitTransaction(Secret _secret, u256 _endowment, bytes const& _init, u256 _gas, u256 _gasPrice) |
|
|
|
{ |
|
|
|
return submitTransaction(_secret, _endowment, _init, _gas, _gasPrice, false); |
|
|
|
} |
|
|
|
|
|
|
|
dev::eth::ExecutionResult MixClient::call(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) |
|
|
|
{ |
|
|
|
return call(_secret, _value, _dest, _data, _gas, _gasPrice, _blockNumber,false); |
|
|
|
} |
|
|
|
|
|
|
|
dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes const& _data, u256 _gas, u256 _gasPrice, BlockNumber _blockNumber) |
|
|
|
{ |
|
|
|
(void)_blockNumber; |
|
|
@ -285,7 +335,7 @@ dev::eth::ExecutionResult MixClient::create(Secret _secret, u256 _value, bytes c |
|
|
|
Transaction t(_value, _gasPrice, _gas, _data, n, _secret); |
|
|
|
bytes rlp = t.rlp(); |
|
|
|
WriteGuard lw(x_state); //TODO: lock is required only for last execution state
|
|
|
|
executeTransaction(t, temp, true); |
|
|
|
executeTransaction(t, temp, true, false, _secret); |
|
|
|
return lastExecution().result; |
|
|
|
} |
|
|
|
|
|
|
|