mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #13571 from ethereum/explicit-fixedhash
Drop implicit alignment argument from FixedHash (and improve FunctionSelector helpers)
This commit is contained in:
		
						commit
						5f8b48793c
					
				| @ -411,7 +411,7 @@ struct ReservedErrorSelector: public PostTypeChecker::Checker | |||||||
| 			); | 			); | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			uint32_t selector = util::selectorFromSignature32(_error.functionType(true)->externalSignature()); | 			uint32_t selector = util::selectorFromSignatureU32(_error.functionType(true)->externalSignature()); | ||||||
| 			if (selector == 0 || ~selector == 0) | 			if (selector == 0 || ~selector == 0) | ||||||
| 				m_errorReporter.syntaxError( | 				m_errorReporter.syntaxError( | ||||||
| 					2855_error, | 					2855_error, | ||||||
|  | |||||||
| @ -52,7 +52,7 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract) | |||||||
| 	for (ErrorDefinition const* error: _contract.interfaceErrors()) | 	for (ErrorDefinition const* error: _contract.interfaceErrors()) | ||||||
| 	{ | 	{ | ||||||
| 		string signature = error->functionType(true)->externalSignature(); | 		string signature = error->functionType(true)->externalSignature(); | ||||||
| 		uint32_t hash = util::selectorFromSignature32(signature); | 		uint32_t hash = util::selectorFromSignatureU32(signature); | ||||||
| 		// Fail if there is a different signature for the same hash.
 | 		// Fail if there is a different signature for the same hash.
 | ||||||
| 		if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature)) | 		if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature)) | ||||||
| 		{ | 		{ | ||||||
|  | |||||||
| @ -27,6 +27,7 @@ | |||||||
| #include <libsolidity/ast/ASTVisitor.h> | #include <libsolidity/ast/ASTVisitor.h> | ||||||
| #include <libsolidity/ast/AST_accept.h> | #include <libsolidity/ast/AST_accept.h> | ||||||
| #include <libsolidity/ast/TypeProvider.h> | #include <libsolidity/ast/TypeProvider.h> | ||||||
|  | #include <libsolutil/FunctionSelector.h> | ||||||
| #include <libsolutil/Keccak256.h> | #include <libsolutil/Keccak256.h> | ||||||
| 
 | 
 | ||||||
| #include <range/v3/view/tail.hpp> | #include <range/v3/view/tail.hpp> | ||||||
| @ -281,8 +282,7 @@ vector<pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition: | |||||||
| 				if (signaturesSeen.count(functionSignature) == 0) | 				if (signaturesSeen.count(functionSignature) == 0) | ||||||
| 				{ | 				{ | ||||||
| 					signaturesSeen.insert(functionSignature); | 					signaturesSeen.insert(functionSignature); | ||||||
| 					util::FixedHash<4> hash(util::keccak256(functionSignature)); | 					interfaceFunctionList.emplace_back(util::selectorFromSignatureH32(functionSignature), fun); | ||||||
| 					interfaceFunctionList.emplace_back(hash, fun); |  | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -3583,12 +3583,12 @@ string FunctionType::externalSignature() const | |||||||
| 
 | 
 | ||||||
| u256 FunctionType::externalIdentifier() const | u256 FunctionType::externalIdentifier() const | ||||||
| { | { | ||||||
| 	return util::selectorFromSignature32(externalSignature()); | 	return util::selectorFromSignatureU32(externalSignature()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| string FunctionType::externalIdentifierHex() const | string FunctionType::externalIdentifierHex() const | ||||||
| { | { | ||||||
| 	return util::FixedHash<4>(util::keccak256(externalSignature())).hex(); | 	return util::selectorFromSignatureH32(externalSignature()).hex(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool FunctionType::isPure() const | bool FunctionType::isPure() const | ||||||
|  | |||||||
| @ -889,7 +889,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const | |||||||
| 			} | 			} | ||||||
| 			sstore(ref, slot_value) | 			sstore(ref, slot_value) | ||||||
| 		})"); | 		})"); | ||||||
| 		code("panicSelector", util::selectorFromSignature("Panic(uint256)").str()); | 		code("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str()); | ||||||
| 		code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop))); | 		code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop))); | ||||||
| 		m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"}); | 		m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"}); | ||||||
| 		m_context << Instruction::POP << Instruction::POP << Instruction::POP; | 		m_context << Instruction::POP << Instruction::POP << Instruction::POP; | ||||||
|  | |||||||
| @ -95,7 +95,7 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType) | |||||||
| { | { | ||||||
| 	solAssert(_argumentType.isImplicitlyConvertibleTo(*TypeProvider::fromElementaryTypeName("string memory"))); | 	solAssert(_argumentType.isImplicitlyConvertibleTo(*TypeProvider::fromElementaryTypeName("string memory"))); | ||||||
| 	fetchFreeMemoryPointer(); | 	fetchFreeMemoryPointer(); | ||||||
| 	m_context << util::selectorFromSignature("Error(string)"); | 	m_context << util::selectorFromSignatureU256("Error(string)"); | ||||||
| 	m_context << Instruction::DUP2 << Instruction::MSTORE; | 	m_context << Instruction::DUP2 << Instruction::MSTORE; | ||||||
| 	m_context << u256(4) << Instruction::ADD; | 	m_context << u256(4) << Instruction::ADD; | ||||||
| 	// Stack: <string data> <mem pos of encoding start>
 | 	// Stack: <string data> <mem pos of encoding start>
 | ||||||
| @ -111,7 +111,7 @@ void CompilerUtils::revertWithError( | |||||||
| ) | ) | ||||||
| { | { | ||||||
| 	fetchFreeMemoryPointer(); | 	fetchFreeMemoryPointer(); | ||||||
| 	m_context << util::selectorFromSignature(_signature); | 	m_context << util::selectorFromSignatureU256(_signature); | ||||||
| 	m_context << Instruction::DUP2 << Instruction::MSTORE; | 	m_context << Instruction::DUP2 << Instruction::MSTORE; | ||||||
| 	m_context << u256(4) << Instruction::ADD; | 	m_context << u256(4) << Instruction::ADD; | ||||||
| 	// Stack: <arguments...> <mem pos of encoding start>
 | 	// Stack: <arguments...> <mem pos of encoding start>
 | ||||||
|  | |||||||
| @ -253,7 +253,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract) | |||||||
| 			return(codepos, subSize) | 			return(codepos, subSize) | ||||||
| 		} | 		} | ||||||
| 		)") | 		)") | ||||||
| 		("panicSelector", util::selectorFromSignature("Panic(uint256)").str()) | 		("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str()) | ||||||
| 		("panicCode", "0") | 		("panicCode", "0") | ||||||
| 		.render(), | 		.render(), | ||||||
| 		{"subSize", "subOffset"} | 		{"subSize", "subOffset"} | ||||||
| @ -1046,7 +1046,7 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca | |||||||
| 		solAssert(m_context.evmVersion().supportsReturndata(), ""); | 		solAssert(m_context.evmVersion().supportsReturndata(), ""); | ||||||
| 
 | 
 | ||||||
| 		// stack: <selector>
 | 		// stack: <selector>
 | ||||||
| 		m_context << Instruction::DUP1 << util::selectorFromSignature32("Error(string)") << Instruction::EQ; | 		m_context << Instruction::DUP1 << util::selectorFromSignatureU32("Error(string)") << Instruction::EQ; | ||||||
| 		m_context << Instruction::ISZERO; | 		m_context << Instruction::ISZERO; | ||||||
| 		m_context.appendConditionalJumpTo(panicTag); | 		m_context.appendConditionalJumpTo(panicTag); | ||||||
| 		m_context << Instruction::POP; // remove selector
 | 		m_context << Instruction::POP; // remove selector
 | ||||||
| @ -1078,7 +1078,7 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca | |||||||
| 		solAssert(m_context.evmVersion().supportsReturndata(), ""); | 		solAssert(m_context.evmVersion().supportsReturndata(), ""); | ||||||
| 
 | 
 | ||||||
| 		// stack: <selector>
 | 		// stack: <selector>
 | ||||||
| 		m_context << util::selectorFromSignature32("Panic(uint256)") << Instruction::EQ; | 		m_context << util::selectorFromSignatureU32("Panic(uint256)") << Instruction::EQ; | ||||||
| 		m_context << Instruction::ISZERO; | 		m_context << Instruction::ISZERO; | ||||||
| 		m_context.appendConditionalJumpTo(fallbackTag); | 		m_context.appendConditionalJumpTo(fallbackTag); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1329,7 +1329,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | |||||||
| 					// hash the signature
 | 					// hash the signature
 | ||||||
| 					if (auto const* stringType = dynamic_cast<StringLiteralType const*>(selectorType)) | 					if (auto const* stringType = dynamic_cast<StringLiteralType const*>(selectorType)) | ||||||
| 					{ | 					{ | ||||||
| 						m_context << util::selectorFromSignature(stringType->value()); | 						m_context << util::selectorFromSignatureU256(stringType->value()); | ||||||
| 						dataOnStack = TypeProvider::fixedBytes(4); | 						dataOnStack = TypeProvider::fixedBytes(4); | ||||||
| 					} | 					} | ||||||
| 					else | 					else | ||||||
|  | |||||||
| @ -233,7 +233,7 @@ string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _mess | |||||||
| 			.render(); | 			.render(); | ||||||
| 
 | 
 | ||||||
| 		int const hashHeaderSize = 4; | 		int const hashHeaderSize = 4; | ||||||
| 		u256 const errorHash = util::selectorFromSignature("Error(string)"); | 		u256 const errorHash = util::selectorFromSignatureU256("Error(string)"); | ||||||
| 
 | 
 | ||||||
| 		string const encodeFunc = ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector) | 		string const encodeFunc = ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector) | ||||||
| 			.tupleEncoder( | 			.tupleEncoder( | ||||||
| @ -4426,7 +4426,7 @@ string YulUtilFunctions::revertReasonIfDebugBody( | |||||||
| 		revert(start, <overallLength>) | 		revert(start, <overallLength>) | ||||||
| 	)"); | 	)"); | ||||||
| 	templ("allocate", _allocation); | 	templ("allocate", _allocation); | ||||||
| 	templ("sig", util::selectorFromSignature("Error(string)").str()); | 	templ("sig", util::selectorFromSignatureU256("Error(string)").str()); | ||||||
| 	templ("length", to_string(_message.length())); | 	templ("length", to_string(_message.length())); | ||||||
| 
 | 
 | ||||||
| 	size_t words = (_message.length() + 31) / 32; | 	size_t words = (_message.length() + 31) / 32; | ||||||
| @ -4454,7 +4454,7 @@ string YulUtilFunctions::panicFunction(util::PanicCode _code) | |||||||
| 			} | 			} | ||||||
| 		)") | 		)") | ||||||
| 		("functionName", functionName) | 		("functionName", functionName) | ||||||
| 		("selector", util::selectorFromSignature("Panic(uint256)").str()) | 		("selector", util::selectorFromSignatureU256("Panic(uint256)").str()) | ||||||
| 		("code", toCompactHexWithPrefix(static_cast<unsigned>(_code))) | 		("code", toCompactHexWithPrefix(static_cast<unsigned>(_code))) | ||||||
| 		.render(); | 		.render(); | ||||||
| 	}); | 	}); | ||||||
|  | |||||||
| @ -1196,7 +1196,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) | |||||||
| 			// hash the signature
 | 			// hash the signature
 | ||||||
| 			Type const& selectorType = type(*arguments.front()); | 			Type const& selectorType = type(*arguments.front()); | ||||||
| 			if (auto const* stringType = dynamic_cast<StringLiteralType const*>(&selectorType)) | 			if (auto const* stringType = dynamic_cast<StringLiteralType const*>(&selectorType)) | ||||||
| 				selector = formatNumber(util::selectorFromSignature(stringType->value())); | 				selector = formatNumber(util::selectorFromSignatureU256(stringType->value())); | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
| 				// Used to reset the free memory pointer later.
 | 				// Used to reset the free memory pointer later.
 | ||||||
| @ -1785,7 +1785,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) | |||||||
| 					"" | 					"" | ||||||
| 				); | 				); | ||||||
| 				define(IRVariable{_memberAccess}) << formatNumber( | 				define(IRVariable{_memberAccess}) << formatNumber( | ||||||
| 					util::selectorFromSignature(functionType.externalSignature()) | 					util::selectorFromSignatureU256(functionType.externalSignature()) | ||||||
| 				) << "\n"; | 				) << "\n"; | ||||||
| 			} | 			} | ||||||
| 			else if (functionType.kind() == FunctionType::Kind::Event) | 			else if (functionType.kind() == FunctionType::Kind::Event) | ||||||
| @ -3234,7 +3234,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) | |||||||
| 
 | 
 | ||||||
| 	if (TryCatchClause const* errorClause = _tryStatement.errorClause()) | 	if (TryCatchClause const* errorClause = _tryStatement.errorClause()) | ||||||
| 	{ | 	{ | ||||||
| 		appendCode() << "case " << selectorFromSignature32("Error(string)") << " {\n"; | 		appendCode() << "case " << selectorFromSignatureU32("Error(string)") << " {\n"; | ||||||
| 		setLocation(*errorClause); | 		setLocation(*errorClause); | ||||||
| 		string const dataVariable = m_context.newYulVariable(); | 		string const dataVariable = m_context.newYulVariable(); | ||||||
| 		appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n"; | 		appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n"; | ||||||
| @ -3254,7 +3254,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) | |||||||
| 	} | 	} | ||||||
| 	if (TryCatchClause const* panicClause = _tryStatement.panicClause()) | 	if (TryCatchClause const* panicClause = _tryStatement.panicClause()) | ||||||
| 	{ | 	{ | ||||||
| 		appendCode() << "case " << selectorFromSignature32("Panic(uint256)") << " {\n"; | 		appendCode() << "case " << selectorFromSignatureU32("Panic(uint256)") << " {\n"; | ||||||
| 		setLocation(*panicClause); | 		setLocation(*panicClause); | ||||||
| 		string const success = m_context.newYulVariable(); | 		string const success = m_context.newYulVariable(); | ||||||
| 		string const code = m_context.newYulVariable(); | 		string const code = m_context.newYulVariable(); | ||||||
| @ -3317,7 +3317,7 @@ void IRGeneratorForStatements::revertWithError( | |||||||
| 	})"); | 	})"); | ||||||
| 	templ("pos", m_context.newYulVariable()); | 	templ("pos", m_context.newYulVariable()); | ||||||
| 	templ("end", m_context.newYulVariable()); | 	templ("end", m_context.newYulVariable()); | ||||||
| 	templ("hash", util::selectorFromSignature(_signature).str()); | 	templ("hash", util::selectorFromSignatureU256(_signature).str()); | ||||||
| 	templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); | 	templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); | ||||||
| 
 | 
 | ||||||
| 	vector<string> errorArgumentVars; | 	vector<string> errorArgumentVars; | ||||||
|  | |||||||
| @ -1034,7 +1034,7 @@ Json::Value CompilerStack::interfaceSymbols(string const& _contractName) const | |||||||
| 	for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors()) | 	for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors()) | ||||||
| 	{ | 	{ | ||||||
| 		string signature = error->functionType(true)->externalSignature(); | 		string signature = error->functionType(true)->externalSignature(); | ||||||
| 		interfaceSymbols["errors"][signature] = util::toHex(toCompactBigEndian(util::selectorFromSignature32(signature), 4)); | 		interfaceSymbols["errors"][signature] = util::toHex(toCompactBigEndian(util::selectorFromSignatureU32(signature), 4)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (EventDefinition const* event: ranges::concat_view( | 	for (EventDefinition const* event: ranges::concat_view( | ||||||
|  | |||||||
| @ -30,6 +30,7 @@ | |||||||
| #include <libevmasm/ControlFlowGraph.h> | #include <libevmasm/ControlFlowGraph.h> | ||||||
| #include <libevmasm/KnownState.h> | #include <libevmasm/KnownState.h> | ||||||
| #include <libevmasm/PathGasMeter.h> | #include <libevmasm/PathGasMeter.h> | ||||||
|  | #include <libsolutil/FunctionSelector.h> | ||||||
| #include <libsolutil/Keccak256.h> | #include <libsolutil/Keccak256.h> | ||||||
| 
 | 
 | ||||||
| #include <functional> | #include <functional> | ||||||
| @ -54,7 +55,7 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation( | |||||||
| 		ExpressionClasses& classes = state->expressionClasses(); | 		ExpressionClasses& classes = state->expressionClasses(); | ||||||
| 		using Id = ExpressionClasses::Id; | 		using Id = ExpressionClasses::Id; | ||||||
| 		using Ids = vector<Id>; | 		using Ids = vector<Id>; | ||||||
| 		Id hashValue = classes.find(u256(util::FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256(_signature))))); | 		Id hashValue = classes.find(u256(util::selectorFromSignatureU32(_signature))); | ||||||
| 		Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))}); | 		Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))}); | ||||||
| 		if (!m_evmVersion.hasBitwiseShifting()) | 		if (!m_evmVersion.hasBitwiseShifting()) | ||||||
| 			// div(calldataload(0), 1 << 224) equals to hashValue
 | 			// div(calldataload(0), 1 << 224) equals to hashValue
 | ||||||
|  | |||||||
| @ -61,7 +61,7 @@ public: | |||||||
| 	explicit FixedHash() { m_data.fill(0); } | 	explicit FixedHash() { m_data.fill(0); } | ||||||
| 
 | 
 | ||||||
| 	/// Construct from another hash, filling with zeroes or cropping as necessary.
 | 	/// Construct from another hash, filling with zeroes or cropping as necessary.
 | ||||||
| 	template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft) | 	template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t) | ||||||
| 	{ | 	{ | ||||||
| 		m_data.fill(0); | 		m_data.fill(0); | ||||||
| 		unsigned c = std::min(M, N); | 		unsigned c = std::min(M, N); | ||||||
|  | |||||||
| @ -26,17 +26,22 @@ | |||||||
| namespace solidity::util | namespace solidity::util | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| /// @returns the ABI selector for a given function signature, as a 32 bit number.
 | /// @returns the ABI selector for a given function signature, as a FixedHash h32.
 | ||||||
| inline uint32_t selectorFromSignature32(std::string const& _signature) | inline FixedHash<4> selectorFromSignatureH32(std::string const& _signature) | ||||||
| { | { | ||||||
| 	return uint32_t(FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256(_signature)))); | 	return FixedHash<4>(util::keccak256(_signature), FixedHash<4>::AlignLeft); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// @returns the ABI selector for a given function signature, as a 32 bit number.
 | ||||||
|  | inline uint32_t selectorFromSignatureU32(std::string const& _signature) | ||||||
|  | { | ||||||
|  | 	return uint32_t(FixedHash<4>::Arith(selectorFromSignatureH32(_signature))); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// @returns the ABI selector for a given function signature, as a u256 (left aligned) number.
 | /// @returns the ABI selector for a given function signature, as a u256 (left aligned) number.
 | ||||||
| inline u256 selectorFromSignature(std::string const& _signature) | inline u256 selectorFromSignatureU256(std::string const& _signature) | ||||||
| { | { | ||||||
| 	return u256(selectorFromSignature32(_signature)) << (256 - 32); | 	return u256(selectorFromSignatureU32(_signature)) << (256 - 32); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -35,6 +35,7 @@ set(libsolutil_sources | |||||||
|     libsolutil/CommonData.cpp |     libsolutil/CommonData.cpp | ||||||
|     libsolutil/CommonIO.cpp |     libsolutil/CommonIO.cpp | ||||||
|     libsolutil/FixedHash.cpp |     libsolutil/FixedHash.cpp | ||||||
|  |     libsolutil/FunctionSelector.cpp | ||||||
|     libsolutil/IndentedWriter.cpp |     libsolutil/IndentedWriter.cpp | ||||||
|     libsolutil/IpfsHash.cpp |     libsolutil/IpfsHash.cpp | ||||||
|     libsolutil/IterateReplacing.cpp |     libsolutil/IterateReplacing.cpp | ||||||
|  | |||||||
| @ -255,7 +255,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept | |||||||
| 		h160 createAddress(keccak256( | 		h160 createAddress(keccak256( | ||||||
| 			bytes(begin(message.sender.bytes), end(message.sender.bytes)) + | 			bytes(begin(message.sender.bytes), end(message.sender.bytes)) + | ||||||
| 			asBytes(to_string(sender.nonce++)) | 			asBytes(to_string(sender.nonce++)) | ||||||
| 		)); | 		), h160::AlignLeft); | ||||||
| 		message.destination = convertToEVMC(createAddress); | 		message.destination = convertToEVMC(createAddress); | ||||||
| 		code = evmc::bytes(message.input_data, message.input_data + message.input_size); | 		code = evmc::bytes(message.input_data, message.input_data + message.input_size); | ||||||
| 	} | 	} | ||||||
| @ -266,7 +266,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept | |||||||
| 			bytes(begin(message.sender.bytes), end(message.sender.bytes)) + | 			bytes(begin(message.sender.bytes), end(message.sender.bytes)) + | ||||||
| 			bytes(begin(message.create2_salt.bytes), end(message.create2_salt.bytes)) + | 			bytes(begin(message.create2_salt.bytes), end(message.create2_salt.bytes)) + | ||||||
| 			keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes() | 			keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes() | ||||||
| 		)); | 		), h160::AlignLeft); | ||||||
| 		message.destination = convertToEVMC(createAddress); | 		message.destination = convertToEVMC(createAddress); | ||||||
| 		if (accounts.count(message.destination) && ( | 		if (accounts.count(message.destination) && ( | ||||||
| 			accounts[message.destination].nonce > 0 || | 			accounts[message.destination].nonce > 0 || | ||||||
|  | |||||||
| @ -30,7 +30,6 @@ | |||||||
| #include <test/libsolidity/util/SoltestTypes.h> | #include <test/libsolidity/util/SoltestTypes.h> | ||||||
| 
 | 
 | ||||||
| #include <libsolutil/CommonIO.h> | #include <libsolutil/CommonIO.h> | ||||||
| #include <libsolutil/FunctionSelector.h> |  | ||||||
| 
 | 
 | ||||||
| #include <liblangutil/Exceptions.h> | #include <liblangutil/Exceptions.h> | ||||||
| 
 | 
 | ||||||
| @ -123,7 +122,7 @@ bytes ExecutionFramework::panicData(util::PanicCode _code) | |||||||
| { | { | ||||||
| 	return | 	return | ||||||
| 		m_evmVersion.supportsReturndata() ? | 		m_evmVersion.supportsReturndata() ? | ||||||
| 		toCompactBigEndian(selectorFromSignature32("Panic(uint256)"), 4) + encode(u256(static_cast<unsigned>(_code))) : | 		toCompactBigEndian(selectorFromSignatureU32("Panic(uint256)"), 4) + encode(u256(static_cast<unsigned>(_code))) : | ||||||
| 		bytes(); | 		bytes(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -31,8 +31,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <liblangutil/EVMVersion.h> | #include <liblangutil/EVMVersion.h> | ||||||
| 
 | 
 | ||||||
| #include <libsolutil/FixedHash.h> | #include <libsolutil/FunctionSelector.h> | ||||||
| #include <libsolutil/Keccak256.h> |  | ||||||
| #include <libsolutil/ErrorCodes.h> | #include <libsolutil/ErrorCodes.h> | ||||||
| 
 | 
 | ||||||
| #include <functional> | #include <functional> | ||||||
| @ -108,8 +107,7 @@ public: | |||||||
| 
 | 
 | ||||||
| 	bytes const& callContractFunctionWithValueNoEncoding(std::string _sig, u256 const& _value, bytes const& _arguments) | 	bytes const& callContractFunctionWithValueNoEncoding(std::string _sig, u256 const& _value, bytes const& _arguments) | ||||||
| 	{ | 	{ | ||||||
| 		util::FixedHash<4> hash(util::keccak256(_sig)); | 		sendMessage(util::selectorFromSignatureH32(_sig).asBytes() + _arguments, false, _value); | ||||||
| 		sendMessage(hash.asBytes() + _arguments, false, _value); |  | ||||||
| 		return m_output; | 		return m_output; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -591,7 +591,7 @@ BOOST_AUTO_TEST_CASE(revoke_addOwner) | |||||||
| 	BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs()); | 	BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs()); | ||||||
| 	// add a new owner
 | 	// add a new owner
 | ||||||
| 	h160 deployer = m_sender; | 	h160 deployer = m_sender; | ||||||
| 	h256 opHash = util::keccak256(FixedHash<4>(util::keccak256("addOwner(address)")).asBytes() + h256(0x33).asBytes()); | 	h256 opHash = util::keccak256(util::selectorFromSignatureH32("addOwner(address)").asBytes() + h256(0x33).asBytes()); | ||||||
| 	BOOST_REQUIRE(callContractFunction("addOwner(address)", h160(0x33)) == encodeArgs()); | 	BOOST_REQUIRE(callContractFunction("addOwner(address)", h160(0x33)) == encodeArgs()); | ||||||
| 	BOOST_REQUIRE(callContractFunction("isOwner(address)", h160(0x33)) == encodeArgs(false)); | 	BOOST_REQUIRE(callContractFunction("isOwner(address)", h160(0x33)) == encodeArgs(false)); | ||||||
| 	m_sender = account(0); | 	m_sender = account(0); | ||||||
|  | |||||||
| @ -342,7 +342,7 @@ BOOST_AUTO_TEST_CASE(external_function) | |||||||
| 	BOTH_ENCODERS( | 	BOTH_ENCODERS( | ||||||
| 		compileAndRun(sourceCode); | 		compileAndRun(sourceCode); | ||||||
| 		callContractFunction("f(uint256)", u256(0)); | 		callContractFunction("f(uint256)", u256(0)); | ||||||
| 		string functionIdF = asString(m_contractAddress.ref()) + asString(FixedHash<4>(keccak256("f(uint256)")).ref()); | 		string functionIdF = asString(m_contractAddress.ref()) + asString(util::selectorFromSignatureH32("f(uint256)").ref()); | ||||||
| 		REQUIRE_LOG_DATA(encodeArgs(functionIdF, functionIdF)); | 		REQUIRE_LOG_DATA(encodeArgs(functionIdF, functionIdF)); | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <liblangutil/Scanner.h> | #include <liblangutil/Scanner.h> | ||||||
| 
 | 
 | ||||||
| #include <libsolutil/Keccak256.h> | #include <libsolutil/FunctionSelector.h> | ||||||
| 
 | 
 | ||||||
| #include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||||
| 
 | 
 | ||||||
| @ -170,6 +170,5 @@ FunctionTypePointer AnalysisFramework::retrieveFunctionBySignature( | |||||||
| 	std::string const& _signature | 	std::string const& _signature | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	FixedHash<4> hash(util::keccak256(_signature)); | 	return _contract.interfaceFunctions()[util::selectorFromSignatureH32(_signature)]; | ||||||
| 	return _contract.interfaceFunctions()[hash]; |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -78,7 +78,7 @@ public: | |||||||
| 	{ | 	{ | ||||||
| 		u256 gasUsed = 0; | 		u256 gasUsed = 0; | ||||||
| 		GasMeter::GasConsumption gas; | 		GasMeter::GasConsumption gas; | ||||||
| 		util::FixedHash<4> hash(util::keccak256(_sig)); | 		util::FixedHash<4> hash = util::selectorFromSignatureH32(_sig); | ||||||
| 		for (bytes const& arguments: _argumentVariants) | 		for (bytes const& arguments: _argumentVariants) | ||||||
| 		{ | 		{ | ||||||
| 			sendMessage(hash.asBytes() + arguments, false, 0); | 			sendMessage(hash.asBytes() + arguments, false, 0); | ||||||
|  | |||||||
| @ -1627,7 +1627,7 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) | |||||||
| 	ALSO_VIA_YUL( | 	ALSO_VIA_YUL( | ||||||
| 		DISABLE_EWASM_TESTRUN(); | 		DISABLE_EWASM_TESTRUN(); | ||||||
| 		compileAndRun(sourceCode); | 		compileAndRun(sourceCode); | ||||||
| 		bytes calldata1 = FixedHash<4>(util::keccak256("f()")).asBytes() + bytes(61, 0x22) + bytes(12, 0x12); | 		bytes calldata1 = util::selectorFromSignatureH32("f()").asBytes() + bytes(61, 0x22) + bytes(12, 0x12); | ||||||
| 		sendMessage(calldata1, false); | 		sendMessage(calldata1, false); | ||||||
| 		BOOST_CHECK(m_transactionSuccessful); | 		BOOST_CHECK(m_transactionSuccessful); | ||||||
| 		BOOST_CHECK(m_output == encodeArgs(util::keccak256(bytes{'a', 'b', 'c'} + calldata1))); | 		BOOST_CHECK(m_output == encodeArgs(util::keccak256(bytes{'a', 'b', 'c'} + calldata1))); | ||||||
| @ -1872,8 +1872,8 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) | |||||||
| 
 | 
 | ||||||
| 		compileAndRun(sourceCode); | 		compileAndRun(sourceCode); | ||||||
| 
 | 
 | ||||||
| 		string innercalldata1 = asString(FixedHash<4>(util::keccak256("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9)); | 		string innercalldata1 = asString(util::selectorFromSignatureH32("f(uint256,uint256)").asBytes() + encodeArgs(8, 9)); | ||||||
| 		string innercalldata2 = asString(FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + encodeArgs(3)); | 		string innercalldata2 = asString(util::selectorFromSignatureH32("g(uint256)").asBytes() + encodeArgs(3)); | ||||||
| 		bytes calldata = encodeArgs( | 		bytes calldata = encodeArgs( | ||||||
| 			12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13, | 			12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13, | ||||||
| 			u256(innercalldata1.length()), innercalldata1, | 			u256(innercalldata1.length()), innercalldata1, | ||||||
| @ -2205,8 +2205,8 @@ BOOST_AUTO_TEST_CASE(calldata_struct_function_type) | |||||||
| 	)"; | 	)"; | ||||||
| 	compileAndRun(sourceCode, 0, "C"); | 	compileAndRun(sourceCode, 0, "C"); | ||||||
| 
 | 
 | ||||||
| 	bytes fn_C_g = m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + bytes(8,0); | 	bytes fn_C_g = m_contractAddress.asBytes() + util::selectorFromSignatureH32("g(uint256)").asBytes() + bytes(8,0); | ||||||
| 	bytes fn_C_h = m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("h(uint256)")).asBytes() + bytes(8,0); | 	bytes fn_C_h = m_contractAddress.asBytes() + util::selectorFromSignatureH32("h(uint256)").asBytes() + bytes(8,0); | ||||||
| 	ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_g), encodeArgs(42 * 3)); | 	ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_g), encodeArgs(42 * 3)); | ||||||
| 	ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_h), encodeArgs(23)); | 	ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_h), encodeArgs(23)); | ||||||
| } | } | ||||||
| @ -3007,7 +3007,7 @@ BOOST_AUTO_TEST_CASE(receive_external_function_type) | |||||||
| 		compileAndRun(sourceCode, 0, "C"); | 		compileAndRun(sourceCode, 0, "C"); | ||||||
| 		ABI_CHECK(callContractFunction( | 		ABI_CHECK(callContractFunction( | ||||||
| 			"f(function)", | 			"f(function)", | ||||||
| 			m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) | 			m_contractAddress.asBytes() + util::selectorFromSignatureH32("g()").asBytes() + bytes(32 - 4 - 20, 0) | ||||||
| 		), encodeArgs(u256(7))); | 		), encodeArgs(u256(7))); | ||||||
| 	) | 	) | ||||||
| } | } | ||||||
| @ -3026,7 +3026,7 @@ BOOST_AUTO_TEST_CASE(return_external_function_type) | |||||||
| 	compileAndRun(sourceCode, 0, "C"); | 	compileAndRun(sourceCode, 0, "C"); | ||||||
| 	ABI_CHECK( | 	ABI_CHECK( | ||||||
| 		callContractFunction("f()"), | 		callContractFunction("f()"), | ||||||
| 		m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) | 		m_contractAddress.asBytes() + util::selectorFromSignatureH32("g()").asBytes() + bytes(32 - 4 - 20, 0) | ||||||
| 	); | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -338,9 +338,9 @@ solidity::frontend::test::ParameterList ContractABIUtils::failureParameters(byte | |||||||
| 		parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::HexString, ABIType::AlignNone, 4}, FormatInfo{}}); | 		parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::HexString, ABIType::AlignNone, 4}, FormatInfo{}}); | ||||||
| 
 | 
 | ||||||
| 		uint64_t selector = fromBigEndian<uint64_t>(bytes{_bytes.begin(), _bytes.begin() + 4}); | 		uint64_t selector = fromBigEndian<uint64_t>(bytes{_bytes.begin(), _bytes.begin() + 4}); | ||||||
| 		if (selector == selectorFromSignature32("Panic(uint256)")) | 		if (selector == selectorFromSignatureU32("Panic(uint256)")) | ||||||
| 			parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}}); | 			parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}}); | ||||||
| 		else if (selector == selectorFromSignature32("Error(string)")) | 		else if (selector == selectorFromSignatureU32("Error(string)")) | ||||||
| 		{ | 		{ | ||||||
| 			parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}}); | 			parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}}); | ||||||
| 			parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}}); | 			parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}}); | ||||||
|  | |||||||
| @ -146,29 +146,30 @@ BOOST_AUTO_TEST_CASE(string_constructor_frombytes) | |||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(converting_constructor) | BOOST_AUTO_TEST_CASE(converting_constructor) | ||||||
| { | { | ||||||
| 	// Truncation
 | 	// Left-aligned truncation
 | ||||||
| 	FixedHash<8> a = FixedHash<8>(FixedHash<12>("112233445566778899001122")); | 	FixedHash<8> a = FixedHash<8>(FixedHash<12>("112233445566778899001122"), FixedHash<8>::AlignLeft); | ||||||
| 	BOOST_CHECK_EQUAL(a.size, 8); | 	BOOST_CHECK_EQUAL(a.size, 8); | ||||||
| 	BOOST_CHECK_EQUAL(a.hex(), "1122334455667788"); | 	BOOST_CHECK_EQUAL(a.hex(), "1122334455667788"); | ||||||
| 
 | 
 | ||||||
|  | 	// Right-aligned truncation
 | ||||||
|  | 	FixedHash<8> b = FixedHash<8>(FixedHash<12>("112233445566778899001122"), FixedHash<8>::AlignRight); | ||||||
|  | 	BOOST_CHECK_EQUAL(b.size, 8); | ||||||
|  | 	BOOST_CHECK_EQUAL(b.hex(), "5566778899001122"); | ||||||
|  | 
 | ||||||
| 	// Left-aligned extension
 | 	// Left-aligned extension
 | ||||||
| 	FixedHash<12> b = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignLeft); | 	FixedHash<12> c = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignLeft); | ||||||
| 	BOOST_CHECK_EQUAL(b.size, 12); | 	BOOST_CHECK_EQUAL(c.size, 12); | ||||||
| 	BOOST_CHECK_EQUAL(b.hex(), "112233445566778800000000"); | 	BOOST_CHECK_EQUAL(c.hex(), "112233445566778800000000"); | ||||||
| 
 | 
 | ||||||
| 	// Right-aligned extension
 | 	// Right-aligned extension
 | ||||||
| 	FixedHash<12> c = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignRight); | 	FixedHash<12> d = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignRight); | ||||||
| 	BOOST_CHECK_EQUAL(c.size, 12); | 	BOOST_CHECK_EQUAL(d.size, 12); | ||||||
| 	BOOST_CHECK_EQUAL(c.hex(), "000000001122334455667788"); | 	BOOST_CHECK_EQUAL(d.hex(), "000000001122334455667788"); | ||||||
| 
 |  | ||||||
| 	// Default setting
 |  | ||||||
| 	FixedHash<12> d = FixedHash<12>(FixedHash<8>("1122334455667788")); |  | ||||||
| 	BOOST_CHECK_EQUAL(d, b); |  | ||||||
| 
 | 
 | ||||||
| 	// FailIfDifferent setting
 | 	// FailIfDifferent setting
 | ||||||
| 	// TODO: Shouldn't this throw?
 | 	// TODO: Shouldn't this throw?
 | ||||||
| 	FixedHash<12> e = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::FailIfDifferent); | 	FixedHash<12> e = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::FailIfDifferent); | ||||||
| 	BOOST_CHECK_EQUAL(e, b); | 	BOOST_CHECK_EQUAL(e, c); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(arith_constructor) | BOOST_AUTO_TEST_CASE(arith_constructor) | ||||||
|  | |||||||
							
								
								
									
										53
									
								
								test/libsolutil/FunctionSelector.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								test/libsolutil/FunctionSelector.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | /*
 | ||||||
|  | 	This file is part of solidity. | ||||||
|  | 
 | ||||||
|  | 	solidity is free software: you can redistribute it and/or modify | ||||||
|  | 	it under the terms of the GNU General Public License as published by | ||||||
|  | 	the Free Software Foundation, either version 3 of the License, or | ||||||
|  | 	(at your option) any later version. | ||||||
|  | 
 | ||||||
|  | 	solidity is distributed in the hope that it will be useful, | ||||||
|  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | 	GNU General Public License for more details. | ||||||
|  | 
 | ||||||
|  | 	You should have received a copy of the GNU General Public License | ||||||
|  | 	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | */ | ||||||
|  | /**
 | ||||||
|  |  * Unit tests for FunctionSelector. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <libsolutil/FunctionSelector.h> | ||||||
|  | 
 | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | 
 | ||||||
|  | #include <cstdint> | ||||||
|  | #include <sstream> | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | 
 | ||||||
|  | namespace solidity::util::test | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(FunctionSelectorTest) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(conversions) | ||||||
|  | { | ||||||
|  | 	BOOST_CHECK_EQUAL( | ||||||
|  | 		util::selectorFromSignatureH32("test()"), | ||||||
|  | 		util::FixedHash<4>(0xf8a8fd6d) | ||||||
|  | 	); | ||||||
|  | 	BOOST_CHECK_EQUAL( | ||||||
|  | 		util::selectorFromSignatureU32("test()"), | ||||||
|  | 		0xf8a8fd6d | ||||||
|  | 	); | ||||||
|  | 	BOOST_CHECK_EQUAL( | ||||||
|  | 		util::selectorFromSignatureU256("test()"), | ||||||
|  | 		u256("0xf8a8fd6d00000000000000000000000000000000000000000000000000000000") | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -439,7 +439,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t | |||||||
| 	} | 	} | ||||||
| 	else if (_fun == "getExternalCodeSize") | 	else if (_fun == "getExternalCodeSize") | ||||||
| 		// Generate "random" code length.
 | 		// Generate "random" code length.
 | ||||||
| 		return uint32_t(u256(keccak256(h256(readAddress(arg[0])))) & 0xfff); | 		return uint32_t(u256(keccak256(h256(readAddress(arg[0]), h256::AlignLeft))) & 0xfff); | ||||||
| 	else if (_fun == "getGasLeft") | 	else if (_fun == "getGasLeft") | ||||||
| 		return 0x99; | 		return 0x99; | ||||||
| 	else if (_fun == "getBlockGasLimit") | 	else if (_fun == "getBlockGasLimit") | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user