mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #857 from LianaHus/StringToHash
conversion for string to/from hash
This commit is contained in:
commit
18fc2ed2d6
@ -628,38 +628,65 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
|
|||||||
return;
|
return;
|
||||||
Type::Category stackTypeCategory = _typeOnStack.getCategory();
|
Type::Category stackTypeCategory = _typeOnStack.getCategory();
|
||||||
Type::Category targetTypeCategory = _targetType.getCategory();
|
Type::Category targetTypeCategory = _targetType.getCategory();
|
||||||
if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT ||
|
|
||||||
stackTypeCategory == Type::Category::INTEGER_CONSTANT)
|
if (stackTypeCategory == Type::Category::STRING)
|
||||||
{
|
{
|
||||||
solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
|
if (targetTypeCategory == Type::Category::INTEGER)
|
||||||
IntegerType addressType(0, IntegerType::Modifier::ADDRESS);
|
|
||||||
IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER
|
|
||||||
? dynamic_cast<IntegerType const&>(_targetType) : addressType;
|
|
||||||
if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
|
|
||||||
{
|
{
|
||||||
IntegerConstantType const& constType = dynamic_cast<IntegerConstantType const&>(_typeOnStack);
|
// conversion from string to hash. no need to clean the high bit
|
||||||
// We know that the stack is clean, we only have to clean for a narrowing conversion
|
// only to shift right because of opposite alignment
|
||||||
// where cleanup is forced.
|
IntegerType const& targetIntegerType = dynamic_cast<IntegerType const&>(_targetType);
|
||||||
if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded)
|
StaticStringType const& typeOnStack = dynamic_cast<StaticStringType const&>(_typeOnStack);
|
||||||
appendHighBitsCleanup(targetType);
|
solAssert(targetIntegerType.isHash(), "Only conversion between String and Hash is allowed.");
|
||||||
|
solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same.");
|
||||||
|
m_context << (u256(1) << (256 - typeOnStack.getNumBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER
|
solAssert(targetTypeCategory == Type::Category::STRING, "Invalid type conversion requested.");
|
||||||
? dynamic_cast<IntegerType const&>(_typeOnStack) : addressType;
|
// nothing to do, strings are high-order-bit-aligned
|
||||||
// Widening: clean up according to source type width
|
//@todo clear lower-order bytes if we allow explicit conversion to shorter strings
|
||||||
// Non-widening and force: clean up according to target type bits
|
|
||||||
if (targetType.getNumBits() > typeOnStack.getNumBits())
|
|
||||||
appendHighBitsCleanup(typeOnStack);
|
|
||||||
else if (_cleanupNeeded)
|
|
||||||
appendHighBitsCleanup(targetType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (stackTypeCategory == Type::Category::STRING)
|
else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT ||
|
||||||
|
stackTypeCategory == Type::Category::INTEGER_CONSTANT)
|
||||||
{
|
{
|
||||||
solAssert(targetTypeCategory == Type::Category::STRING, "");
|
if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER)
|
||||||
// nothing to do, strings are high-order-bit-aligned
|
{
|
||||||
//@todo clear lower-order bytes if we allow explicit conversion to shorter strings
|
// conversion from hash to string. no need to clean the high bit
|
||||||
|
// only to shift left because of opposite alignment
|
||||||
|
StaticStringType const& targetStringType = dynamic_cast<StaticStringType const&>(_targetType);
|
||||||
|
IntegerType const& typeOnStack = dynamic_cast<IntegerType const&>(_typeOnStack);
|
||||||
|
solAssert(typeOnStack.isHash(), "Only conversion between String and Hash is allowed.");
|
||||||
|
solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same.");
|
||||||
|
m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
|
||||||
|
IntegerType addressType(0, IntegerType::Modifier::ADDRESS);
|
||||||
|
IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER
|
||||||
|
? dynamic_cast<IntegerType const&>(_targetType) : addressType;
|
||||||
|
if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
|
||||||
|
{
|
||||||
|
IntegerConstantType const& constType = dynamic_cast<IntegerConstantType const&>(_typeOnStack);
|
||||||
|
// We know that the stack is clean, we only have to clean for a narrowing conversion
|
||||||
|
// where cleanup is forced.
|
||||||
|
if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded)
|
||||||
|
appendHighBitsCleanup(targetType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER
|
||||||
|
? dynamic_cast<IntegerType const&>(_typeOnStack) : addressType;
|
||||||
|
// Widening: clean up according to source type width
|
||||||
|
// Non-widening and force: clean up according to target type bits
|
||||||
|
if (targetType.getNumBits() > typeOnStack.getNumBits())
|
||||||
|
appendHighBitsCleanup(typeOnStack);
|
||||||
|
else if (_cleanupNeeded)
|
||||||
|
appendHighBitsCleanup(targetType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (_typeOnStack != _targetType)
|
else if (_typeOnStack != _targetType)
|
||||||
// All other types should not be convertible to non-equal types.
|
// All other types should not be convertible to non-equal types.
|
||||||
|
16
Types.cpp
16
Types.cpp
@ -140,6 +140,11 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
|||||||
|
|
||||||
bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||||
{
|
{
|
||||||
|
if (_convertTo.getCategory() == Category::STRING)
|
||||||
|
{
|
||||||
|
StaticStringType const& convertTo = dynamic_cast<StaticStringType const&>(_convertTo);
|
||||||
|
return isHash() && (m_bits == convertTo.getNumBytes() * 8);
|
||||||
|
}
|
||||||
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT;
|
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,6 +372,17 @@ bool StaticStringType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
|||||||
return convertTo.m_bytes >= m_bytes;
|
return convertTo.m_bytes >= m_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StaticStringType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||||
|
{
|
||||||
|
if (_convertTo.getCategory() == Category::INTEGER)
|
||||||
|
{
|
||||||
|
IntegerType const& convertTo = dynamic_cast<IntegerType const&>(_convertTo);
|
||||||
|
if (convertTo.isHash() && (m_bytes * 8 == convertTo.getNumBits()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return isImplicitlyConvertibleTo(_convertTo);
|
||||||
|
}
|
||||||
|
|
||||||
bool StaticStringType::operator==(Type const& _other) const
|
bool StaticStringType::operator==(Type const& _other) const
|
||||||
{
|
{
|
||||||
if (_other.getCategory() != getCategory())
|
if (_other.getCategory() != getCategory())
|
||||||
|
3
Types.h
3
Types.h
@ -233,9 +233,10 @@ public:
|
|||||||
/// if no type fits.
|
/// if no type fits.
|
||||||
static std::shared_ptr<StaticStringType> smallestTypeForLiteral(std::string const& _literal);
|
static std::shared_ptr<StaticStringType> smallestTypeForLiteral(std::string const& _literal);
|
||||||
|
|
||||||
StaticStringType(int _bytes);
|
explicit StaticStringType(int _bytes);
|
||||||
|
|
||||||
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||||
|
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||||
virtual bool operator==(Type const& _other) const override;
|
virtual bool operator==(Type const& _other) const override;
|
||||||
|
|
||||||
virtual unsigned getCalldataEncodedSize() const override { return m_bytes; }
|
virtual unsigned getCalldataEncodedSize() const override { return m_bytes; }
|
||||||
|
Loading…
Reference in New Issue
Block a user