示例#1
0
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, _gasAuto, _secret);
	Address address = right160(sha3(rlpList(t.sender(), t.nonce())));
	return address;
}
示例#2
0
// TODO: prototype changed - will need rejigging.
ExecutionResult MixClient::debugTransaction(Transaction const& _t, State const& _state, EnvInfo const& _envInfo, bool _call)
{
	State execState = _state;
	execState.addBalance(_t.sender(), _t.gas() * _t.gasPrice()); //give it enough balance for gas estimation
	eth::ExecutionResult er;
	Executive execution(execState, _envInfo);
	execution.setResultRecipient(er);
	execution.initialize(_t);
	execution.execute();

	std::vector<MachineState> machineStates;
	std::vector<unsigned> levels;
	std::vector<MachineCode> codes;
	std::map<bytes const*, unsigned> codeIndexes;
	std::vector<bytes> data;
	std::map<bytesConstRef const*, unsigned> dataIndexes;
	bytes const* lastCode = nullptr;
	bytesConstRef const* lastData = nullptr;
	unsigned codeIndex = 0;
	unsigned dataIndex = 0;
	auto onOp = [&](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, bigint gas, void* voidVM, void const* voidExt)
	{
		VM& vm = *static_cast<VM*>(voidVM);
		ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
		if (lastCode == nullptr || lastCode != &ext.code)
		{
			auto const& iter = codeIndexes.find(&ext.code);
			if (iter != codeIndexes.end())
				codeIndex = iter->second;
			else
			{
				codeIndex = codes.size();
				codes.push_back(MachineCode({ext.myAddress, ext.code}));
				codeIndexes[&ext.code] = codeIndex;
			}
			lastCode = &ext.code;
		}

		if (lastData == nullptr || lastData != &ext.data)
		{
			auto const& iter = dataIndexes.find(&ext.data);
			if (iter != dataIndexes.end())
				dataIndex = iter->second;
			else
			{
				dataIndex = data.size();
				data.push_back(ext.data.toBytes());
				dataIndexes[&ext.data] = dataIndex;
			}
			lastData = &ext.data;
		}

		if (levels.size() < ext.depth)
			levels.push_back(machineStates.size() - 1);
		else
			levels.resize(ext.depth);

		machineStates.push_back(MachineState{
									steps,
									vm.curPC(),
									inst,
									newMemSize,
									static_cast<u256>(gas),
									vm.stack(),
									vm.memory(),
									gasCost,
									ext.state().storage(ext.myAddress),
									std::move(levels),
									codeIndex,
									dataIndex
								});
	};

	execution.go(onOp);
	execution.finalize();

	switch (er.excepted)
	{
	case TransactionException::None:
		break;
	case TransactionException::NotEnoughCash:
		BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Insufficient balance for contract deployment"));
	case TransactionException::OutOfGasIntrinsic:
	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::BadJumpDestination:
		BOOST_THROW_EXCEPTION(OutOfGas() << errinfo_comment("Solidity exception (bad jump)"));
	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::InvalidSignature:
	case TransactionException::InvalidNonce:
	case TransactionException::InvalidFormat:
	case TransactionException::BadRLP:
		BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("Internal execution error"));
	}

	ExecutionResult d;
	d.inputParameters = _t.data();
	d.result = er;
	d.machineStates = machineStates;
	d.executionCode = std::move(codes);
	d.transactionData = std::move(data);
	d.address = _t.receiveAddress();
	d.sender = _t.sender();
	d.value = _t.value();
	d.gasUsed = er.gasUsed + er.gasRefunded + c_callStipend;
	if (_t.isCreation())
		d.contractAddress = right160(sha3(rlpList(_t.sender(), _t.nonce())));
	if (!_call)
		d.transactionIndex = m_postMine.pending().size();
	d.executonIndex = m_executions.size();
	return d;
}
示例#3
0
void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _call, bool _gasAuto, Secret const& _secret)
{
	Transaction t = _gasAuto ? replaceGas(_t, _secret, m_state.gasLimitRemaining()) : _t;
	bytes rlp = t.rlp();

	// do debugging run first
	LastHashes lastHashes(256);
	lastHashes[0] = bc().numberHash(bc().number());
	for (unsigned i = 1; i < 256; ++i)
		lastHashes[i] = lastHashes[i - 1] ? bc().details(lastHashes[i - 1]).parent : h256();

	State execState = _state;
	Executive execution(execState, lastHashes, 0);
	execution.initialize(&rlp);
	execution.execute();
	std::vector<MachineState> machineStates;
	std::vector<unsigned> levels;
	std::vector<MachineCode> codes;
	std::map<bytes const*, unsigned> codeIndexes;
	std::vector<bytes> data;
	std::map<bytesConstRef const*, unsigned> dataIndexes;
	bytes const* lastCode = nullptr;
	bytesConstRef const* lastData = nullptr;
	unsigned codeIndex = 0;
	unsigned dataIndex = 0;
	auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, void* voidVM, void const* voidExt)
	{
		VM& vm = *static_cast<VM*>(voidVM);
		ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
		if (lastCode == nullptr || lastCode != &ext.code)
		{
			auto const& iter = codeIndexes.find(&ext.code);
			if (iter != codeIndexes.end())
				codeIndex = iter->second;
			else
			{
				codeIndex = codes.size();
				codes.push_back(MachineCode({ext.myAddress, ext.code}));
				codeIndexes[&ext.code] = codeIndex;
			}
			lastCode = &ext.code;
		}

		if (lastData == nullptr || lastData != &ext.data)
		{
			auto const& iter = dataIndexes.find(&ext.data);
			if (iter != dataIndexes.end())
				dataIndex = iter->second;
			else
			{
				dataIndex = data.size();
				data.push_back(ext.data.toBytes());
				dataIndexes[&ext.data] = dataIndex;
			}
			lastData = &ext.data;
		}

		if (levels.size() < ext.depth)
			levels.push_back(machineStates.size() - 1);
		else
			levels.resize(ext.depth);

		machineStates.emplace_back(MachineState({steps, vm.curPC(), inst, newMemSize, vm.gas(),
									  vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels, codeIndex, dataIndex}));
	};

	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();
	d.machineStates = machineStates;
	d.executionCode = std::move(codes);
	d.transactionData = std::move(data);
	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)
		d.transactionIndex = m_state.pending().size();
	d.executonIndex = m_executions.size();

	// execute on a state
	if (!_call)
	{
		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);
		for (std::pair<h256 const, eth::InstalledFilter>& i: m_filters)
			if ((unsigned)i.second.filter.latest() > bc().number())
			{
				// acceptable number.
				auto m = i.second.filter.matches(_state.receipt(_state.pending().size() - 1));
				if (m.size())
				{
					// filter catches them
					for (LogEntry const& l: m)
						i.second.changes.push_back(LocalisedLogEntry(l, bc().number() + 1));
					changed.insert(i.first);
				}
			}
		changed.insert(dev::eth::PendingChangedFilter);
		noteChanged(changed);
	}
	WriteGuard l(x_executions);
	m_executions.emplace_back(std::move(d));
}