Exemplo n.º 1
0
void MixClient::executeTransaction(Transaction const& _t, Block& _block, bool _call, bool _gasAuto, Secret const& _secret)
{
	Transaction t = _gasAuto ? replaceGas(_t, m_postMine.gasLimitRemaining()) : _t;

	// do debugging run first
	EnvInfo envInfo(bc().info(), bc().lastHashes());
	ExecutionResult d = debugTransaction(t, _block.state(), envInfo, _call);

	// execute on a state
	if (!_call)
	{
		t = _gasAuto ? replaceGas(_t, d.gasUsed, _secret) : _t;
		eth::ExecutionResult const& er = _block.execute(envInfo.lastHashes(), t);
		if (t.isCreation() && _block.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 + c_callStipend;
		LocalisedLogEntries logs;
		TransactionReceipt const& tr = _block.receipt(_block.pending().size() - 1);

		LogEntries le = tr.log();
		if (le.size())
			for (unsigned j = 0; j < le.size(); ++j)
				logs.insert(logs.begin(), LocalisedLogEntry(le[j]));
		d.logs =  logs;
	}
	WriteGuard l(x_executions);
	m_executions.emplace_back(std::move(d));
}
Exemplo n.º 2
0
LocalisedLogEntries ClientBase::logs(LogFilter const& _f) const
{
	LocalisedLogEntries ret;
	unsigned begin = min(bc().number() + 1, (unsigned)numberFromHash(_f.latest()));
	unsigned end = min(bc().number(), min(begin, (unsigned)numberFromHash(_f.earliest())));
	
	// Handle pending transactions differently as they're not on the block chain.
	if (begin > bc().number())
	{
		State temp = postMine();
		for (unsigned i = 0; i < temp.pending().size(); ++i)
		{
			// Might have a transaction that contains a matching log.
			TransactionReceipt const& tr = temp.receipt(i);
			LogEntries le = _f.matches(tr);
			if (le.size())
				for (unsigned j = 0; j < le.size(); ++j)
					ret.insert(ret.begin(), LocalisedLogEntry(le[j]));
		}
		begin = bc().number();
	}
	
	set<unsigned> matchingBlocks;
	for (auto const& i: _f.bloomPossibilities())
		for (auto u: bc().withBlockBloom(i, end, begin))
			matchingBlocks.insert(u);

	unsigned falsePos = 0;
	for (auto n: matchingBlocks)
	{
		int total = 0;
		auto h = bc().numberHash(n);
		auto info = bc().info(h);
		auto receipts = bc().receipts(h).receipts;
		unsigned logIndex = 0;
		for (size_t i = 0; i < receipts.size(); i++)
		{
			logIndex++;
			TransactionReceipt receipt = receipts[i];
			if (_f.matches(receipt.bloom()))
			{
				auto th = transaction(info.hash(), i).sha3();
				LogEntries le = _f.matches(receipt);
				if (le.size())
				{
					total += le.size();
					for (unsigned j = 0; j < le.size(); ++j)
						ret.insert(ret.begin(), LocalisedLogEntry(le[j], info, th, i, logIndex));
				}
			}
			
			if (!total)
				falsePos++;
		}
	}

	cdebug << matchingBlocks.size() << "searched from" << (end - begin) << "skipped; " << falsePos << "false +ves";
	return ret;
}
Exemplo n.º 3
0
void ClientBase::prependLogsFromBlock(LogFilter const& _f, h256 const& _blockHash, BlockPolarity _polarity, LocalisedLogEntries& io_logs) const
{
	auto receipts = bc().receipts(_blockHash).receipts;
	for (size_t i = 0; i < receipts.size(); i++)
	{
		TransactionReceipt receipt = receipts[i];
		auto th = transaction(_blockHash, i).sha3();
		LogEntries le = _f.matches(receipt);
		for (unsigned j = 0; j < le.size(); ++j)
			io_logs.insert(io_logs.begin(), LocalisedLogEntry(le[j], _blockHash, (BlockNumber)bc().number(_blockHash), th, i, 0, _polarity));
	}
}
Exemplo n.º 4
0
LocalisedLogEntries ClientBase::logs(LogFilter const& _f) const
{
	LocalisedLogEntries ret;
	unsigned begin = min(bc().number() + 1, (unsigned)numberFromHash(_f.latest()));
	unsigned end = min(bc().number(), min(begin, (unsigned)numberFromHash(_f.earliest())));
	
	// Handle pending transactions differently as they're not on the block chain.
	if (begin > bc().number())
	{
		Block temp = postMine();
		for (unsigned i = 0; i < temp.pending().size(); ++i)
		{
			// Might have a transaction that contains a matching log.
			TransactionReceipt const& tr = temp.receipt(i);
			LogEntries le = _f.matches(tr);
			for (unsigned j = 0; j < le.size(); ++j)
				ret.insert(ret.begin(), LocalisedLogEntry(le[j]));
		}
		begin = bc().number();
	}

	// Handle reverted blocks
	// There are not so many, so let's iterate over them
	h256s blocks;
	h256 ancestor;
	unsigned ancestorIndex;
	tie(blocks, ancestor, ancestorIndex) = bc().treeRoute(_f.earliest(), _f.latest(), false);

	for (size_t i = 0; i < ancestorIndex; i++)
		prependLogsFromBlock(_f, blocks[i], BlockPolarity::Dead, ret);

	// cause end is our earliest block, let's compare it with our ancestor
	// if ancestor is smaller let's move our end to it
	// example:
	//
	// 3b -> 2b -> 1b
	//                -> g
	// 3a -> 2a -> 1a
	//
	// if earliest is at 2a and latest is a 3b, coverting them to numbers
	// will give us pair (2, 3)
	// and we want to get all logs from 1 (ancestor + 1) to 3
	// so we have to move 2a to g + 1
	end = min(end, (unsigned)numberFromHash(ancestor) + 1);

	// Handle blocks from main chain
	set<unsigned> matchingBlocks;
	if (!_f.isRangeFilter())
		for (auto const& i: _f.bloomPossibilities())
			for (auto u: bc().withBlockBloom(i, end, begin))
				matchingBlocks.insert(u);
	else
		// if it is a range filter, we want to get all logs from all blocks in given range
		for (unsigned i = end; i <= begin; i++)
			matchingBlocks.insert(i);

	for (auto n: matchingBlocks)
		prependLogsFromBlock(_f, bc().numberHash(n), BlockPolarity::Live, ret);

	reverse(ret.begin(), ret.end());
	return ret;
}