예제 #1
0
파일: parser.py 프로젝트: mingderwang/viper
def add_globals_and_events(_contracts, _defs, _events, _getters, _globals,
                           item):
    if item.value is not None:
        raise StructureException('May not assign value whilst defining type',
                                 item)
    elif isinstance(item.annotation,
                    ast.Call) and item.annotation.func.id == "__log__":
        if _globals or len(_defs):
            raise StructureException(
                "Events must all come before global declarations and function definitions",
                item)
        _events.append(item)
    elif not isinstance(item.target, ast.Name):
        raise StructureException(
            "Can only assign type to variable in top-level statement", item)
    # Check if variable name is reserved or invalid
    elif not is_varname_valid(item.target.id):
        raise VariableDeclarationException(
            "Variable name invalid or reserved: ", item.target)
    # Check if global already exists, if so error
    elif item.target.id in _globals:
        raise VariableDeclarationException(
            "Cannot declare a persistent variable twice!", item.target)
    elif len(_defs):
        raise StructureException(
            "Global variables must all come before function definitions", item)
    # If the type declaration is of the form public(<type here>), then proceed with
    # the underlying type but also add getters
    elif isinstance(item.annotation,
                    ast.Call) and item.annotation.func.id == "address":
        if len(item.annotation.args) != 1:
            raise StructureException("Address expects one arg (the type)")
        if item.annotation.args[0].id not in premade_contracts:
            raise VariableDeclarationException(
                "Unsupported premade contract declaration",
                item.annotation.args[0])
        premade_contract = premade_contracts[item.annotation.args[0].id]
        _contracts[item.target.id] = add_contract(premade_contract.body)
        _globals[item.target.id] = VariableRecord(item.target.id,
                                                  len(_globals),
                                                  BaseType('address'), True)
    elif isinstance(item.annotation,
                    ast.Call) and item.annotation.func.id == "public":
        if len(item.annotation.args) != 1:
            raise StructureException("Public expects one arg (the type)")
        typ = parse_type(item.annotation.args[0], 'storage')
        _globals[item.target.id] = VariableRecord(item.target.id,
                                                  len(_globals), typ, True)
        # Adding getters here
        for getter in mk_getter(item.target.id, typ):
            _getters.append(parse_line('\n' * (item.lineno - 1) + getter))
            _getters[-1].pos = getpos(item)
    else:
        _globals[item.target.id] = VariableRecord(
            item.target.id, len(_globals),
            parse_type(item.annotation, 'storage'), True)
    return _contracts, _events, _globals, _getters
예제 #2
0
 def from_declaration(cls, code):
     name = code.target.id
     pos = 0
     # Determine the arguments, expects something of the form def foo(arg1: num, arg2: num ...
     args = []
     indexed_list = []
     topics_count = 1
     if code.annotation.args:
         keys = code.annotation.args[0].keys
         values = code.annotation.args[0].values
         for i in range(len(keys)):
             typ = values[i]
             arg = keys[i].id
             is_indexed = False
             # Check to see if argument is a topic
             if isinstance(typ, ast.Call) and typ.func.id == 'indexed':
                 typ = values[i].args[0]
                 indexed_list.append(True)
                 topics_count += 1
                 is_indexed = True
             else:
                 indexed_list.append(False)
             if hasattr(
                     typ,
                     'left') and typ.left.id == 'bytes' and typ.comparators[
                         0].n > 32 and is_indexed:
                 raise VariableDeclarationException(
                     "Indexed arguments are limited to 32 bytes")
             if topics_count > 4:
                 raise VariableDeclarationException(
                     "Maximum of 3 topics {} given".format(topics_count -
                                                           1), arg)
             if not isinstance(arg, str):
                 raise VariableDeclarationException("Argument name invalid",
                                                    arg)
             if not typ:
                 raise InvalidTypeException("Argument must have type", arg)
             if not is_varname_valid(arg):
                 raise VariableDeclarationException(
                     "Argument name invalid or reserved: " + arg, arg)
             if arg in (x.name for x in args):
                 raise VariableDeclarationException(
                     "Duplicate function argument name: " + arg, arg)
             parsed_type = parse_type(typ, None)
             args.append(VariableRecord(arg, pos, parsed_type, False))
             if isinstance(parsed_type, ByteArrayType):
                 pos += ceil32(typ.comparators[0].n)
             else:
                 pos += get_size_of_type(parsed_type) * 32
     sig = name + '(' + ','.join([
         canonicalize_type(arg.typ, indexed_list[pos])
         for pos, arg in enumerate(args)
     ]) + ')'
     event_id = bytes_to_int(sha3(bytes(sig, 'utf-8')))
     return cls(name, args, indexed_list, event_id, sig)
예제 #3
0
파일: parser.py 프로젝트: kittynet/viper
 def new_variable(self, name, typ):
     if not is_varname_valid(name):
         raise VariableDeclarationException(
             "Variable name invalid or reserved: " + name)
     if name in self.vars or name in self.globals:
         raise VariableDeclarationException("Duplicate variable name: %s" %
                                            name)
     self.vars[name] = VariableRecord(name, self.next_mem, typ, True)
     pos = self.next_mem
     self.next_mem += 32 * get_size_of_type(typ)
     return pos
예제 #4
0
파일: expr.py 프로젝트: sdtsui/viper
 def struct_literals(self):
     o = {}
     members = {}
     for key, value in zip(self.expr.keys, self.expr.values):
         if not isinstance(key, ast.Name) or not is_varname_valid(key.id):
             raise TypeMismatchException("Invalid member variable for struct: %r" % vars(key).get('id', key), key)
         if key.id in o:
             raise TypeMismatchException("Member variable duplicated: " + key.id, key)
         o[key.id] = Expr(value, self.context).lll_node
         members[key.id] = o[key.id].typ
     return LLLnode.from_list(["multi"] + [o[key] for key in sorted(list(o.keys()))], typ=StructType(members), pos=getpos(self.expr))