Ejemplo n.º 1
0
    def compare(self):
        left = Expr.parse_value_expr(self.expr.left, self.context)
        right = Expr.parse_value_expr(self.expr.right, self.context)

        if right.value is None:
            raise InvalidLiteral(
                'Comparison to None is not allowed, compare against a default value.',
                self.expr,
            )

        if isinstance(left.typ, ByteArrayLike) and isinstance(
                right.typ, ByteArrayLike):
            # TODO: Can this if branch be removed ^
            pass

        elif isinstance(self.expr.op, vy_ast.In) and isinstance(
                right.typ, ListType):
            if left.typ != right.typ.subtype:
                raise TypeMismatch(
                    "Can't use IN comparison with different types!",
                    self.expr,
                )
            return self.build_in_comparator()

        if isinstance(self.expr.op, vy_ast.Gt):
            op = 'sgt'
        elif isinstance(self.expr.op, vy_ast.GtE):
            op = 'sge'
        elif isinstance(self.expr.op, vy_ast.LtE):
            op = 'sle'
        elif isinstance(self.expr.op, vy_ast.Lt):
            op = 'slt'
        elif isinstance(self.expr.op, vy_ast.Eq):
            op = 'eq'
        elif isinstance(self.expr.op, vy_ast.NotEq):
            op = 'ne'
        else:
            raise Exception("Unsupported comparison operator")

        # Compare (limited to 32) byte arrays.
        if isinstance(left.typ, ByteArrayLike) and isinstance(
                right.typ, ByteArrayLike):
            left = Expr(self.expr.left, self.context).lll_node
            right = Expr(self.expr.right, self.context).lll_node

            length_mismatch = (left.typ.maxlen != right.typ.maxlen)
            left_over_32 = left.typ.maxlen > 32
            right_over_32 = right.typ.maxlen > 32
            if length_mismatch or left_over_32 or right_over_32:
                left_keccak = keccak256_helper(self.expr, [left], None,
                                               self.context)
                right_keccak = keccak256_helper(self.expr, [right], None,
                                                self.context)

                if op == 'eq' or op == 'ne':
                    return LLLnode.from_list(
                        [op, left_keccak, right_keccak],
                        typ='bool',
                        pos=getpos(self.expr),
                    )

                else:
                    raise StructureException(
                        "Can only compare strings/bytes of length shorter",
                        " than 32 bytes other than equality comparisons",
                        self.expr,
                    )

            else:

                def load_bytearray(side):
                    if side.location == 'memory':
                        return ['mload', ['add', 32, side]]
                    elif side.location == 'storage':
                        return ['sload', ['add', 1, ['sha3_32', side]]]

                return LLLnode.from_list(
                    [op, load_bytearray(left),
                     load_bytearray(right)],
                    typ='bool',
                    pos=getpos(self.expr),
                )

        # Compare other types.
        if not is_numeric_type(left.typ) or not is_numeric_type(right.typ):
            if op not in ('eq', 'ne'):
                raise TypeMismatch("Invalid type for comparison op", self.expr)
        left_type, right_type = left.typ.typ, right.typ.typ

        # Special Case: comparison of a literal integer. If in valid range allow it to be compared.
        if {left_type, right_type} == {'int128', 'uint256'} and {
                left.typ.is_literal, right.typ.is_literal
        } == {True, False}:  # noqa: E501

            comparison_allowed = False
            if left.typ.is_literal and SizeLimits.in_bounds(
                    right_type, left.value):
                comparison_allowed = True
            elif right.typ.is_literal and SizeLimits.in_bounds(
                    left_type, right.value):
                comparison_allowed = True
            op = self._signed_to_unsigned_comparision_op(op)

            if comparison_allowed:
                return LLLnode.from_list([op, left, right],
                                         typ='bool',
                                         pos=getpos(self.expr))

        elif {left_type, right_type} == {'uint256', 'uint256'}:
            op = self._signed_to_unsigned_comparision_op(op)
        elif (left_type in ('decimal', 'int128') or right_type in
              ('decimal', 'int128')) and left_type != right_type:  # noqa: E501
            raise TypeMismatch(
                f'Implicit conversion from {left_type} to {right_type} disallowed, please convert.',
                self.expr,
            )

        if left_type == right_type:
            return LLLnode.from_list([op, left, right],
                                     typ='bool',
                                     pos=getpos(self.expr))
        else:
            raise TypeMismatch(
                f"Unsupported types for comparison: {left_type} {right_type}",
                self.expr,
            )
Ejemplo n.º 2
0
    def parse_Compare(self):
        left = Expr.parse_value_expr(self.expr.left, self.context)
        right = Expr.parse_value_expr(self.expr.right, self.context)

        if right.value is None:
            return

        if isinstance(left.typ, ByteArrayLike) and isinstance(
                right.typ, ByteArrayLike):
            # TODO: Can this if branch be removed ^
            pass

        elif isinstance(self.expr.op,
                        (vy_ast.In, vy_ast.NotIn)) and isinstance(
                            right.typ, ListType):
            return self.build_in_comparator()

        if isinstance(self.expr.op, vy_ast.Gt):
            op = "sgt"
        elif isinstance(self.expr.op, vy_ast.GtE):
            op = "sge"
        elif isinstance(self.expr.op, vy_ast.LtE):
            op = "sle"
        elif isinstance(self.expr.op, vy_ast.Lt):
            op = "slt"
        elif isinstance(self.expr.op, vy_ast.Eq):
            op = "eq"
        elif isinstance(self.expr.op, vy_ast.NotEq):
            op = "ne"
        else:
            return

        # Compare (limited to 32) byte arrays.
        if isinstance(left.typ, ByteArrayLike) and isinstance(
                right.typ, ByteArrayLike):
            left = Expr(self.expr.left, self.context).lll_node
            right = Expr(self.expr.right, self.context).lll_node

            length_mismatch = left.typ.maxlen != right.typ.maxlen
            left_over_32 = left.typ.maxlen > 32
            right_over_32 = right.typ.maxlen > 32
            if length_mismatch or left_over_32 or right_over_32:
                left_keccak = keccak256_helper(self.expr, [left], None,
                                               self.context)
                right_keccak = keccak256_helper(self.expr, [right], None,
                                                self.context)

                if op == "eq" or op == "ne":
                    return LLLnode.from_list(
                        [op, left_keccak, right_keccak],
                        typ="bool",
                        pos=getpos(self.expr),
                    )

                else:
                    return

            else:

                def load_bytearray(side):
                    if side.location == "memory":
                        return ["mload", ["add", 32, side]]
                    elif side.location == "storage":
                        return ["sload", ["add", 1, side]]

                return LLLnode.from_list(
                    [op, load_bytearray(left),
                     load_bytearray(right)],
                    typ="bool",
                    pos=getpos(self.expr),
                )

        # Compare other types.
        if is_numeric_type(left.typ) and is_numeric_type(right.typ):
            if left.typ.typ == right.typ.typ == "uint256":
                # this works because we only have one unsigned integer type
                # in the future if others are added, this logic must be expanded
                op = self._signed_to_unsigned_comparision_op(op)

        elif op not in ("eq", "ne"):
            return

        return LLLnode.from_list([op, left, right],
                                 typ="bool",
                                 pos=getpos(self.expr))
Ejemplo n.º 3
0
    def parse_Compare(self):
        left = Expr.parse_value_expr(self.expr.left, self.context)
        right = Expr.parse_value_expr(self.expr.right, self.context)

        if right.value is None:
            return

        if isinstance(left.typ, ByteArrayLike) and isinstance(
                right.typ, ByteArrayLike):
            # TODO: Can this if branch be removed ^
            pass

        elif isinstance(self.expr.op, vy_ast.In) and isinstance(
                right.typ, ListType):
            if left.typ != right.typ.subtype:
                return
            return self.build_in_comparator()

        if isinstance(self.expr.op, vy_ast.Gt):
            op = "sgt"
        elif isinstance(self.expr.op, vy_ast.GtE):
            op = "sge"
        elif isinstance(self.expr.op, vy_ast.LtE):
            op = "sle"
        elif isinstance(self.expr.op, vy_ast.Lt):
            op = "slt"
        elif isinstance(self.expr.op, vy_ast.Eq):
            op = "eq"
        elif isinstance(self.expr.op, vy_ast.NotEq):
            op = "ne"
        else:
            return

        # Compare (limited to 32) byte arrays.
        if isinstance(left.typ, ByteArrayLike) and isinstance(
                right.typ, ByteArrayLike):
            left = Expr(self.expr.left, self.context).lll_node
            right = Expr(self.expr.right, self.context).lll_node

            length_mismatch = left.typ.maxlen != right.typ.maxlen
            left_over_32 = left.typ.maxlen > 32
            right_over_32 = right.typ.maxlen > 32
            if length_mismatch or left_over_32 or right_over_32:
                left_keccak = keccak256_helper(self.expr, [left], None,
                                               self.context)
                right_keccak = keccak256_helper(self.expr, [right], None,
                                                self.context)

                if op == "eq" or op == "ne":
                    return LLLnode.from_list(
                        [op, left_keccak, right_keccak],
                        typ="bool",
                        pos=getpos(self.expr),
                    )

                else:
                    return

            else:

                def load_bytearray(side):
                    if side.location == "memory":
                        return ["mload", ["add", 32, side]]
                    elif side.location == "storage":
                        return ["sload", ["add", 1, ["sha3_32", side]]]

                return LLLnode.from_list(
                    [op, load_bytearray(left),
                     load_bytearray(right)],
                    typ="bool",
                    pos=getpos(self.expr),
                )

        # Compare other types.
        if not is_numeric_type(left.typ) or not is_numeric_type(right.typ):
            if op not in ("eq", "ne"):
                return
        left_type, right_type = left.typ.typ, right.typ.typ

        # Special Case: comparison of a literal integer. If in valid range allow it to be compared.
        if {left_type, right_type} == {"int128", "uint256"} and {
                left.typ.is_literal,
                right.typ.is_literal,
        } == {
                True,
                False,
        }:  # noqa: E501

            comparison_allowed = False
            if left.typ.is_literal and SizeLimits.in_bounds(
                    right_type, left.value):
                comparison_allowed = True
            elif right.typ.is_literal and SizeLimits.in_bounds(
                    left_type, right.value):
                comparison_allowed = True
            op = self._signed_to_unsigned_comparision_op(op)

            if comparison_allowed:
                return LLLnode.from_list([op, left, right],
                                         typ="bool",
                                         pos=getpos(self.expr))

        elif {left_type, right_type} == {"uint256", "uint256"}:
            op = self._signed_to_unsigned_comparision_op(op)
        elif (left_type in ("decimal", "int128") or right_type in
              ("decimal", "int128")) and left_type != right_type:  # noqa: E501
            return

        if left_type == right_type:
            return LLLnode.from_list([op, left, right],
                                     typ="bool",
                                     pos=getpos(self.expr))
Ejemplo n.º 4
0
 def build_LLL(self, expr, args, kwargs, context):
     return keccak256_helper(expr, args, kwargs, context)
Ejemplo n.º 5
0
def _keccak256(expr, args, kwargs, context):
    return keccak256_helper(expr, args, kwargs, context)