Example #1
0
def create_contract(ext, msg):
    #print('CREATING WITH GAS', msg.gas)
    sender = decode_hex(msg.sender) if len(msg.sender) == 40 else msg.sender
    if ext.tx_origin != msg.sender:
        ext._block.increment_nonce(msg.sender)
    nonce = utils.encode_int(ext._block.get_nonce(msg.sender) - 1)
    msg.to = mk_contract_address(sender, nonce)
    b = ext.get_balance(msg.to)
    if b > 0:
        ext.set_balance(msg.to, b)
        ext._block.set_nonce(msg.to, 0)
        ext._block.set_code(msg.to, b'')
        ext._block.reset_storage(msg.to)
    msg.is_create = True
    # assert not ext.get_code(msg.to)
    code = msg.data.extract_all()
    msg.data = vm.CallData([], 0, 0)
    res, gas, dat = _apply_msg(ext, msg, code)
    assert utils.is_numeric(gas)

    if res:
        if not len(dat):
            return 1, gas, msg.to
        gcost = len(dat) * opcodes.GCONTRACTBYTE
        if gas >= gcost:
            gas -= gcost
        else:
            dat = []
            #print('CONTRACT CREATION OOG', 'have', gas, 'want', gcost)
            log_msg.debug('CONTRACT CREATION OOG', have=gas, want=gcost)
        ext._block.set_code(msg.to, b''.join(map(ascii_chr, dat)))
        return 1, gas, msg.to
    else:
        return 0, gas, b''
Example #2
0
 def format_message(self, msg, kwargs, highlight, level):
     if getattr(self, 'log_json', False):
         message = dict()
         message['event'] = '{}.{}'.format(
             self.name, msg.lower().replace(' ', '_'))
         message['level'] = logging.getLevelName(level)
         try:
             message.update(kwargs)
             try:
                 msg = json.dumps(message, cls=_LogJSONEncoder)
             except TypeError:
                 # Invalid value. With our custom encoder this can only happen with non-string
                 message = _stringify_dict_keys(message)
                 msg = json.dumps(message, cls=_LogJSONEncoder)
         except UnicodeDecodeError:
             message.update({
                 k: v if is_numeric(v) or isinstance(v, (float, complex)) else repr(v)
                 for k, v in kwargs.items()
             })
             msg = json.dumps(message, cls=_LogJSONEncoder)
     else:
         msg = "{}{} {}{}".format(
             bcolors.WARNING if highlight else "",
             msg,
             " ".join("{}={!s}".format(k, v) for k, v in kwargs.items()),
             bcolors.ENDC if highlight else ""
         )
     return msg
Example #3
0
 def to_snapshot(self, root_only=False, no_prevblocks=False):
     snapshot = {}
     if root_only:
         # Smaller snapshot format that only includes the state root
         # (requires original DB to re-initialize)
         snapshot["state_root"] = '0x' + encode_hex(self.trie.root_hash)
     else:
         # "Full" snapshot
         snapshot["alloc"] = self.to_dict()
     # Save non-state-root variables
     for k, default in STATE_DEFAULTS.items():
         default = copy.copy(default)
         v = getattr(self, k)
         if is_numeric(default):
             snapshot[k] = str(v)
         elif isinstance(default, (str, bytes)):
             snapshot[k] = '0x' + encode_hex(v)
         elif k == 'prev_headers' and not no_prevblocks:
             snapshot[k] = [
                 prev_header_to_dict(h)
                 for h in v[:self.config['PREV_HEADER_DEPTH']]
             ]
         elif k == 'recent_uncles' and not no_prevblocks:
             snapshot[k] = {
                 str(n): ['0x' + encode_hex(h) for h in headers]
                 for n, headers in v.items()
             }
     return snapshot
Example #4
0
    def get_block(self, block_id=None):
        """Return the block identified by `block_id`.

        This method also sets :attr:`default_block` to the value of `block_id`
        which will be returned if, at later calls, `block_id` is not provided.

        Subdispatchers using this function have to ensure sure that a
        chainmanager is registered via :attr:`required_services`.

        :param block_id: either the block number as integer or 'pending',
                        'earliest' or 'latest', or `None` for the default
                        block
        :returns: the requested block
        :raises: :exc:`KeyError` if the block does not exist
        """
        assert 'chain' in self.app.services
        chain = self.app.services.chain.chain
        if block_id is None:
            block_id = self.default_block
        else:
            self.default_block = block_id
        if block_id == 'pending':
            return self.app.services.chain.chain.head_candidate
        if block_id == 'latest':
            return chain.head
        if block_id == 'earliest':
            block_id = 0
        if is_numeric(block_id):
            # by number
            hash_ = chain.index.get_block_by_number(block_id)
        else:
            # by hash
            assert is_string(block_id)
            hash_ = block_id
        return chain.get(hash_)
Example #5
0
def create_contract(ext, msg):
    #print('CREATING WITH GAS', msg.gas)
    sender = decode_hex(msg.sender) if len(msg.sender) == 40 else msg.sender
    if ext.tx_origin != msg.sender:
        ext._block.increment_nonce(msg.sender)
    nonce = utils.encode_int(ext._block.get_nonce(msg.sender) - 1)
    msg.to = mk_contract_address(sender, nonce)
    b = ext.get_balance(msg.to)
    if b > 0:
        ext.set_balance(msg.to, b)
        ext._block.set_nonce(msg.to, 0)
        ext._block.set_code(msg.to, b'')
        ext._block.reset_storage(msg.to)
    msg.is_create = True
    # assert not ext.get_code(msg.to)
    code = msg.data.extract_all()
    msg.data = vm.CallData([], 0, 0)
    res, gas, dat = _apply_msg(ext, msg, code)
    assert utils.is_numeric(gas)

    if res:
        if not len(dat):
            return 1, gas, msg.to
        gcost = len(dat) * opcodes.GCONTRACTBYTE
        if gas >= gcost:
            gas -= gcost
        else:
            dat = []
            #print('CONTRACT CREATION OOG', 'have', gas, 'want', gcost)
            log_msg.debug('CONTRACT CREATION OOG', have=gas, want=gcost)
        ext._block.set_code(msg.to, b''.join(map(ascii_chr, dat)))
        return 1, gas, msg.to
    else:
        return 0, gas, b''
Example #6
0
    def get_block(self, block_id=None):
        """Return the block identified by `block_id`.

        This method also sets :attr:`default_block` to the value of `block_id`
        which will be returned if, at later calls, `block_id` is not provided.

        Subdispatchers using this function have to ensure sure that a
        chainmanager is registered via :attr:`required_services`.

        :param block_id: either the block number as integer or 'pending',
                        'earliest' or 'latest', or `None` for the default
                        block
        :returns: the requested block
        :raises: :exc:`KeyError` if the block does not exist
        """
        assert 'chain' in self.app.services
        chain = self.app.services.chain.chain
        if block_id is None:
            block_id = self.default_block
        else:
            self.default_block = block_id
        if block_id == 'pending':
            return self.app.services.chain.chain.head_candidate
        if block_id == 'latest':
            return chain.head
        if block_id == 'earliest':
            block_id = 0
        if is_numeric(block_id):
            # by number
            hash_ = chain.index.get_block_by_number(block_id)
        else:
            # by hash
            assert is_string(block_id)
            hash_ = block_id
        return chain.get(hash_)
Example #7
0
def decint(n):
    if is_numeric(n) and n < 2**256 and n > -2**255:
        return n
    elif is_numeric(n):
        raise Exception("Number out of range: %r" % n)
    elif is_string(n) and len(n) == 40:
        return big_endian_to_int(decode_hex(n))
    elif is_string(n) and len(n) <= 32:
        return big_endian_to_int(n)
    elif is_string(n) and len(n) > 32:
        raise Exception("String too long: %r" % n)
    elif n is True:
        return 1
    elif n is False or n is None:
        return 0
    else:
        raise Exception("Cannot encode integer: %r" % n)
Example #8
0
def decint(n):
    if is_numeric(n) and n < 2**256 and n > -2**255:
        return n
    elif is_numeric(n):
        raise Exception("Number out of range: %r" % n)
    elif is_string(n) and len(n) == 40:
        return big_endian_to_int(decode_hex(n))
    elif is_string(n) and len(n) <= 32:
        return big_endian_to_int(n)
    elif is_string(n) and len(n) > 32:
        raise Exception("String too long: %r" % n)
    elif n is True:
        return 1
    elif n is False or n is None:
        return 0
    else:
        raise Exception("Cannot encode integer: %r" % n)
Example #9
0
 def from_snapshot(cls, snapshot_data, env, executing_on_head=False):
     state = State(env=env)
     if "alloc" in snapshot_data:
         for addr, data in snapshot_data["alloc"].items():
             if len(addr) == 40:
                 addr = decode_hex(addr)
             assert len(addr) == 20
             if 'wei' in data:
                 state.set_balance(addr, parse_as_int(data['wei']))
             if 'balance' in data:
                 state.set_balance(addr, parse_as_int(data['balance']))
             if 'code' in data:
                 state.set_code(addr, parse_as_bin(data['code']))
             if 'nonce' in data:
                 state.set_nonce(addr, parse_as_int(data['nonce']))
             if 'storage' in data:
                 for k, v in data['storage'].items():
                     state.set_storage_data(
                         addr,
                         big_endian_to_int(parse_as_bin(k)),
                         big_endian_to_int(parse_as_bin(v)))
     elif "state_root" in snapshot_data:
         state.trie.root_hash = parse_as_bin(snapshot_data["state_root"])
     else:
         raise Exception(
             "Must specify either alloc or state root parameter")
     for k, default in STATE_DEFAULTS.items():
         default = copy.copy(default)
         v = snapshot_data[k] if k in snapshot_data else None
         if is_numeric(default):
             setattr(state, k, parse_as_int(v)
                     if k in snapshot_data else default)
         elif is_string(default):
             setattr(state, k, parse_as_bin(v)
                     if k in snapshot_data else default)
         elif k == 'prev_headers':
             if k in snapshot_data:
                 headers = [dict_to_prev_header(h) for h in v]
             else:
                 headers = default
             setattr(state, k, headers)
         elif k == 'recent_uncles':
             if k in snapshot_data:
                 uncles = {}
                 for height, _uncles in v.items():
                     uncles[int(height)] = []
                     for uncle in _uncles:
                         uncles[int(height)].append(parse_as_bin(uncle))
             else:
                 uncles = default
             setattr(state, k, uncles)
     if executing_on_head:
         state.executing_on_head = True
     state.commit()
     state.changed = {}
     return state
Example #10
0
def normalize_number(value):
    if is_numeric(value):
        return value
    elif is_string(value):
        if value.startswith(b'0x'):
            return int(value, 16)
        else:
            return big_endian_to_int(value)
    else:
        raise ValueError("Unknown numeric encoding: {0}".format(value))
Example #11
0
def encode_number(value, length=None):
    """Encode interger quantity `data`."""
    if not is_numeric(value):
        raise ValueError("Unsupported type: {0}".format(type(value)))
    hex_value = encode_data(int_to_big_endian(value), length)

    if length:
        return hex_value
    else:
        return add_0x(strip_0x(hex_value).lstrip(b'0') or b'0')
Example #12
0
def encode_number(value, length=None):
    """Encode interger quantity `data`."""
    if not is_numeric(value):
        raise ValueError("Unsupported type: {0}".format(type(value)))
    hex_value = encode_data(int_to_big_endian(value), length)

    if length:
        return hex_value
    else:
        return add_0x(strip_0x(hex_value).lstrip(b'0') or b'0')
Example #13
0
def normalize_number(value):
    if is_numeric(value):
        return value
    elif is_string(value):
        if value.startswith(b'0x'):
            return int(value, 16)
        else:
            return big_endian_to_int(value)
    else:
        raise ValueError("Unknown numeric encoding: {0}".format(value))
Example #14
0
def _apply_msg(ext, msg, code):
    if log_msg.is_active('trace'):
        log_msg.debug("MSG APPLY",
                      sender=encode_hex(msg.sender),
                      to=encode_hex(msg.to),
                      gas=msg.gas,
                      value=msg.value,
                      data=encode_hex(msg.data.extract_all()))
    if log_state.is_active('trace'):
        log_state.trace('MSG PRE STATE SENDER',
                        account=msg.sender,
                        bal=ext.get_balance(msg.sender),
                        state=ext.log_storage(msg.sender))
        log_state.trace('MSG PRE STATE RECIPIENT',
                        account=msg.to,
                        bal=ext.get_balance(msg.to),
                        state=ext.log_storage(msg.to))
    # Transfer value, instaquit if not enough
    snapshot = ext._block.snapshot()
    o = ext._block.transfer_value(msg.sender, msg.to, msg.value)
    if not o:
        log_msg.debug('MSG TRANSFER FAILED',
                      have=ext.get_balance(msg.to),
                      want=msg.value)
        return 1, msg.gas, []
    # Main loop
    if msg.code_address in specials.specials:
        res, gas, dat = specials.specials[msg.code_address](ext, msg)
    else:
        res, gas, dat = vm.vm_execute(ext, msg, code)
    gas = int(gas)
    assert utils.is_numeric(gas)
    if log_msg.is_active('trace'):
        log_msg.debug('MSG APPLIED',
                      result=o,
                      gas_remained=gas,
                      sender=msg.sender,
                      to=msg.to,
                      data=dat)
    if log_state.is_active('trace'):
        log_state.trace('MSG PRE STATE SENDER',
                        account=msg.sender,
                        bal=ext.get_balance(msg.sender),
                        state=ext.log_storage(msg.sender))
        log_state.trace('MSG PRE STATE RECIPIENT',
                        account=msg.to,
                        bal=ext.get_balance(msg.to),
                        state=ext.log_storage(msg.to))

    if res == 0:
        log_msg.debug('REVERTING')
        ext._block.revert(snapshot)

    return res, gas, dat
Example #15
0
def mine(block_number, difficulty, mining_hash, start_nonce=0, rounds=1000):
    assert utils.is_numeric(start_nonce)
    cache = get_cache(block_number)
    nonce = start_nonce
    target = utils.zpad(utils.int_to_big_endian(2**256 // (difficulty or 1) - 1), 32)
    for i in range(1, rounds + 1):
        bin_nonce = utils.zpad(utils.int_to_big_endian((nonce + i) & TT64M1), 8)
        o = hashimoto_light(block_number, cache, mining_hash, bin_nonce)
        if o[b"result"] <= target:
            log.debug("nonce found")
            assert len(bin_nonce) == 8
            assert len(o[b"mix digest"]) == 32
            return bin_nonce, o[b"mix digest"]
    return None, None
Example #16
0
def create_contract(ext, msg):
    log_msg.debug("CONTRACT CREATION")
    # print('CREATING WITH GAS', msg.gas)
    sender = decode_hex(msg.sender) if len(msg.sender) == 40 else msg.sender
    code = msg.data.extract_all()
    if ext._block.number >= ext._block.config["METROPOLIS_FORK_BLKNUM"]:
        msg.to = mk_metropolis_contract_address(msg.sender, code)
        if ext.get_code(msg.to):
            if ext.get_nonce(msg.to) >= 2 ** 40:
                ext.set_nonce(msg.to, (ext.get_nonce(msg.to) + 1) % 2 ** 160)
                msg.to = normalize_address((ext.get_nonce(msg.to) - 1) % 2 ** 160)
            else:
                ext.set_nonce(msg.to, (big_endian_to_int(msg.to) + 2) % 2 ** 160)
                msg.to = normalize_address((ext.get_nonce(msg.to) - 1) % 2 ** 160)
    else:
        if ext.tx_origin != msg.sender:
            ext._block.increment_nonce(msg.sender)
        nonce = utils.encode_int(ext._block.get_nonce(msg.sender) - 1)
        msg.to = mk_contract_address(sender, nonce)
    b = ext.get_balance(msg.to)
    if b > 0:
        ext.set_balance(msg.to, b)
        ext._block.set_nonce(msg.to, 0)
        ext._block.set_code(msg.to, b"")
        ext._block.reset_storage(msg.to)
    msg.is_create = True
    # assert not ext.get_code(msg.to)
    msg.data = vm.CallData([], 0, 0)
    snapshot = ext._block.snapshot()
    res, gas, dat = _apply_msg(ext, msg, code)
    assert utils.is_numeric(gas)

    if res:
        if not len(dat):
            return 1, gas, msg.to
        gcost = len(dat) * opcodes.GCONTRACTBYTE
        if gas >= gcost:
            gas -= gcost
        else:
            dat = []
            log_msg.debug("CONTRACT CREATION OOG", have=gas, want=gcost, block_number=ext._block.number)
            if ext._block.number >= ext._block.config["HOMESTEAD_FORK_BLKNUM"]:
                ext._block.revert(snapshot)
                return 0, 0, b""
        ext._block.set_code(msg.to, b"".join(map(ascii_chr, dat)))
        return 1, gas, msg.to
    else:
        return 0, gas, b""
Example #17
0
def decint(n, signed=False):  # pylint: disable=invalid-name,too-many-branches
    """ Decode an unsigned/signed integer. """

    if isinstance(n, str):
        n = utils.to_string(n)

    if n is True:
        return 1

    if n is False:
        return 0

    if n is None:
        return 0

    if is_numeric(n):
        if signed:
            if not -TT255 <= n <= TT255 - 1:
                raise EncodingError('Number out of range: %r' % n)
        else:
            if not 0 <= n <= TT256 - 1:
                raise EncodingError('Number out of range: %r' % n)

        return n

    if is_string(n):
        if len(n) > 32:
            raise EncodingError('String too long: %r' % n)

        if len(n) == 40:
            int_bigendian = decode_hex(n)
        else:
            int_bigendian = n  # pylint: disable=redefined-variable-type

        result = big_endian_to_int(int_bigendian)
        if signed:
            if result >= TT255:
                result -= TT256

            if not -TT255 <= result <= TT255 - 1:
                raise EncodingError('Number out of range: %r' % n)
        else:
            if not 0 <= result <= TT256 - 1:
                raise EncodingError('Number out of range: %r' % n)

        return result

    raise EncodingError('Cannot decode integer: %r' % n)
def create_contract(ext, msg):
    log_msg.debug('CONTRACT CREATION')
    #print('CREATING WITH GAS', msg.gas)
    sender = decode_hex(msg.sender) if len(msg.sender) == 40 else msg.sender
    code = msg.data.extract_all()
    if ext._block.number >= ext._block.config['METROPOLIS_FORK_BLKNUM']:
        msg.to = mk_metropolis_contract_address(msg.sender, code)
        if ext.get_code(msg.to):
            if ext.get_nonce(msg.to) >= 2 ** 40:
                ext.set_nonce(msg.to, (ext.get_nonce(msg.to) + 1) % 2 ** 160)
                msg.to = normalize_address((ext.get_nonce(msg.to) - 1) % 2 ** 160)
            else:
                ext.set_nonce(msg.to, (big_endian_to_int(msg.to) + 2) % 2 ** 160)
                msg.to = normalize_address((ext.get_nonce(msg.to) - 1) % 2 ** 160)
    else:
        if ext.tx_origin != msg.sender:
            ext._block.increment_nonce(msg.sender)
        nonce = utils.encode_int(ext._block.get_nonce(msg.sender) - 1)
        msg.to = mk_contract_address(sender, nonce)
    b = ext.get_balance(msg.to)
    if b > 0:
        ext.set_balance(msg.to, b)
        ext._block.set_nonce(msg.to, 0)
        ext._block.set_code(msg.to, b'')
        ext._block.reset_storage(msg.to)
    msg.is_create = True
    # assert not ext.get_code(msg.to)
    msg.data = vm.CallData([], 0, 0)
    snapshot = ext._block.snapshot()
    res, gas, dat = _apply_msg(ext, msg, code)
    assert utils.is_numeric(gas)

    if res:
        if not len(dat):
            return 1, gas, msg.to
        gcost = len(dat) * opcodes.GCONTRACTBYTE
        if gas >= gcost:
            gas -= gcost
        else:
            dat = []
            log_msg.debug('CONTRACT CREATION OOG', have=gas, want=gcost, block_number=ext._block.number)
            if ext._block.number >= ext._block.config['HOMESTEAD_FORK_BLKNUM']:
                ext._block.revert(snapshot)
                return 0, 0, b''
        ext._block.set_code(msg.to, b''.join(map(ascii_chr, dat)))
        return 1, gas, msg.to
    else:
        return 0, gas, b''
Example #19
0
    def __init__(self, chain, blocks=None, addresses=None, topics=None,
                 pending=False, latest=False):
        self.chain = chain
        if blocks is not None:
            self.blocks = blocks
        else:
            self.blocks = []
        self.addresses = addresses
        self.topics = topics
        if self.topics:
            for topic in self.topics:
                assert topic is None or is_numeric(topic)
        self.pending = pending
        self.latest = latest

        self.blocks_done = set()
        self._logs = {}
        self._new_logs = {}
Example #20
0
def decode_filter(filter_dict, block):
    """Decodes a filter as expected by eth_newFilter or eth_getLogs to a :class:`Filter`."""
    if not isinstance(filter_dict, dict):
        raise Exception('Filter must be an object')
    address = filter_dict.get('address', None)
    if utils.is_string(address):
        addresses = [decode_hex(strip_0x(address))]
    elif isinstance(address, Iterable):
        addresses = [decode_hex(strip_0x(addr)) for addr in address]
    elif address is None:
        addresses = None
    else:
        raise Exception('Parameter must be address or list of addresses')
    if 'topics' in filter_dict:
        topics = []
        for topic in filter_dict['topics']:
            if topic is not None:
                topics.append(utils.big_endian_to_int(decode_hex(strip_0x(topic))))
            else:
                topics.append(None)
    else:
        topics = None

    from_block = filter_dict.get('fromBlock') or 'latest'
    to_block = filter_dict.get('toBlock') or 'latest'

    if from_block not in ('earliest', 'latest', 'pending'):
        from_block = decode_number(from_block)

    if to_block not in ('earliest', 'latest', 'pending'):
        to_block = decode_number(to_block)

    # check order
    block_id_dict = {
        'earliest': 0,
        'latest': block.number,
        'pending': block.number+1
    }
    range_ = [b if utils.is_numeric(b) else block_id_dict[b] for b in (from_block, to_block)]
    if range_[0] > range_[1]:
        raise Exception('fromBlock must be newer or equal to toBlock')

    return {"from_block": from_block, "to_block": to_block, "addresses": addresses, "topics": topics}
Example #21
0
def _apply_msg(ext, msg, code):
    if log_msg.is_active('trace'):
        log_msg.debug("MSG APPLY", sender=encode_hex(msg.sender), to=encode_hex(msg.to),
                      gas=msg.gas, value=msg.value,
                      data=encode_hex(msg.data.extract_all()))
    if log_state.is_active('trace'):
        log_state.trace('MSG PRE STATE SENDER', account=msg.sender,
                        bal=ext.get_balance(msg.sender),
                        state=ext.log_storage(msg.sender))
        log_state.trace('MSG PRE STATE RECIPIENT', account=msg.to,
                        bal=ext.get_balance(msg.to),
                        state=ext.log_storage(msg.to))
    # Transfer value, instaquit if not enough
    snapshot = ext._block.snapshot()
    o = ext._block.transfer_value(msg.sender, msg.to, msg.value)
    if not o:
        log_msg.debug('MSG TRANSFER FAILED', have=ext.get_balance(msg.to),
                      want=msg.value)
        return 1, msg.gas, []
    # Main loop
    if msg.code_address in specials.specials:
        res, gas, dat = specials.specials[msg.code_address](ext, msg)
    else:
        res, gas, dat = vm.vm_execute(ext, msg, code)
    gas = int(gas)
    assert utils.is_numeric(gas)
    if log_msg.is_active('trace'):
        log_msg.debug('MSG APPLIED', result=o, gas_remained=gas,
                      sender=msg.sender, to=msg.to, data=dat)
    if log_state.is_active('trace'):
        log_state.trace('MSG PRE STATE SENDER', account=msg.sender,
                        bal=ext.get_balance(msg.sender),
                        state=ext.log_storage(msg.sender))
        log_state.trace('MSG PRE STATE RECIPIENT', account=msg.to,
                        bal=ext.get_balance(msg.to),
                        state=ext.log_storage(msg.to))

    if res == 0:
        log_msg.debug('REVERTING')
        ext._block.revert(snapshot)

    return res, gas, dat
Example #22
0
def decint(n, signed=False):
    if isinstance(n, str):
        n = utils.to_string(n)

    if is_numeric(n):
        min_, max_ = (-TT255, TT255 - 1) if signed else (0, TT256 - 1)
        if n > max_ or n < min_:
            raise EncodingError("Number out of range: %r" % n)
        return n
    elif is_string(n):
        if len(n) == 40:
            n = decode_hex(n)
        if len(n) > 32:
            raise EncodingError("String too long: %r" % n)

        i = big_endian_to_int(n)
        return (i - TT256) if signed and i >= TT255 else i
    elif n is True:
        return 1
    elif n is False or n is None:
        return 0
    else:
        raise EncodingError("Cannot encode integer: %r" % n)
Example #23
0
    def __init__(self,
                 chain,
                 blocks=None,
                 addresses=None,
                 topics=None,
                 pending=False,
                 latest=False):
        self.chain = chain
        if blocks is not None:
            self.blocks = blocks
        else:
            self.blocks = []
        self.addresses = addresses
        self.topics = topics
        if self.topics:
            for topic in self.topics:
                assert topic is None or is_numeric(topic)
        self.pending = pending
        self.latest = latest

        self.blocks_done = set()
        self._logs = {}
        self._new_logs = {}
Example #24
0
def encode_single(typ, arg):  # pylint: disable=too-many-return-statements,too-many-branches,too-many-statements,too-many-locals
    """ Encode `arg` as `typ`.

    `arg` will be encoded in a best effort manner, were necessary the function
    will try to correctly define the underlying binary representation (ie.
    decoding a hex-encoded address/hash).

    Args:
        typ (Tuple[(str, int, list)]): A 3-tuple defining the `arg` type.

            The first element defines the type name.
            The second element defines the type length in bits.
            The third element defines if it's an array type.

            Together the first and second defines the elementary type, the third
            element must be present but is ignored.

            Valid type names are:
                - uint
                - int
                - bool
                - ufixed
                - fixed
                - string
                - bytes
                - hash
                - address

        arg (object): The object to be encoded, it must be a python object
            compatible with the `typ`.

    Raises:
        ValueError: when an invalid `typ` is supplied.
        ValueOutOfBounds: when `arg` cannot be encoded as `typ` because of the
            binary contraints.

    Note:
        This function don't work with array types, for that use the `enc`
        function.
    """
    base, sub, _ = typ

    if base == 'uint':
        sub = int(sub)

        if not (0 < sub <= 256 and sub % 8 == 0):
            raise ValueError(
                'invalid unsigned integer bit length {}'.format(sub))

        try:
            i = decint(arg, signed=False)
        except EncodingError:
            # arg is larger than 2**256
            raise ValueOutOfBounds(repr(arg))

        if not 0 <= i < 2 ** sub:
            raise ValueOutOfBounds(repr(arg))

        value_encoded = int_to_big_endian(i)
        return zpad(value_encoded, 32)

    if base == 'int':
        sub = int(sub)
        bits = sub - 1

        if not (0 < sub <= 256 and sub % 8 == 0):
            raise ValueError('invalid integer bit length {}'.format(sub))

        try:
            i = decint(arg, signed=True)
        except EncodingError:
            # arg is larger than 2**255
            raise ValueOutOfBounds(repr(arg))

        if not -2 ** bits <= i < 2 ** bits:
            raise ValueOutOfBounds(repr(arg))

        value = i % 2 ** 256  # convert negative to "equivalent" positive
        value_encoded = int_to_big_endian(value)
        return zpad(value_encoded, 32)

    if base == 'bool':
        if arg is True:
            value_encoded = int_to_big_endian(1)
        elif arg is False:
            value_encoded = int_to_big_endian(0)
        else:
            raise ValueError('%r is not bool' % arg)

        return zpad(value_encoded, 32)

    if base == 'ufixed':
        sub = str(sub)  # pylint: disable=redefined-variable-type

        high_str, low_str = sub.split('x')
        high = int(high_str)
        low = int(low_str)

        if not (0 < high + low <= 256 and high % 8 == 0 and low % 8 == 0):
            raise ValueError('invalid unsigned fixed length {}'.format(sub))

        if not 0 <= arg < 2 ** high:
            raise ValueOutOfBounds(repr(arg))

        float_point = arg * 2 ** low
        fixed_point = int(float_point)
        return zpad(int_to_big_endian(fixed_point), 32)

    if base == 'fixed':
        sub = str(sub)  # pylint: disable=redefined-variable-type

        high_str, low_str = sub.split('x')
        high = int(high_str)
        low = int(low_str)
        bits = high - 1

        if not (0 < high + low <= 256 and high % 8 == 0 and low % 8 == 0):
            raise ValueError('invalid unsigned fixed length {}'.format(sub))

        if not -2 ** bits <= arg < 2 ** bits:
            raise ValueOutOfBounds(repr(arg))

        float_point = arg * 2 ** low
        fixed_point = int(float_point)
        value = fixed_point % 2 ** 256
        return zpad(int_to_big_endian(value), 32)

    # Decimals
    if base == 'decimal':
        val_to_encode = int(arg * 10**int(sub))
        return zpad(encode_int(val_to_encode % 2**256), 32)

    if base == 'string':
        if isinstance(arg, utils.unicode):
            arg = arg.encode('utf8')
        else:
            try:
                arg.decode('utf8')
            except UnicodeDecodeError:
                raise ValueError('string must be utf8 encoded')

        if len(sub):  # fixed length
            if not 0 <= len(arg) <= int(sub):
                raise ValueError('invalid string length {}'.format(sub))

            if not 0 <= int(sub) <= 32:
                raise ValueError('invalid string length {}'.format(sub))

            return rzpad(arg, 32)

        if not 0 <= len(arg) < TT256:
            raise Exception('Integer invalid or out of range: %r' % arg)

        length_encoded = zpad(int_to_big_endian(len(arg)), 32)
        value_encoded = rzpad(arg, utils.ceil32(len(arg)))

        return length_encoded + value_encoded

    if base == 'bytes':
        if not is_string(arg):
            if isinstance(arg, str):
                arg = bytes(arg, 'utf8')
            else:
                raise EncodingError('Expecting string: %r' % arg)

        arg = utils.to_string(arg)  # py2: force unicode into str

        if len(sub):  # fixed length
            if not 0 <= len(arg) <= int(sub):
                raise ValueError('string must be utf8 encoded')

            if not 0 <= int(sub) <= 32:
                raise ValueError('string must be utf8 encoded')

            return rzpad(arg, 32)

        if not 0 <= len(arg) < TT256:
            raise Exception('Integer invalid or out of range: %r' % arg)

        length_encoded = zpad(int_to_big_endian(len(arg)), 32)
        value_encoded = rzpad(arg, utils.ceil32(len(arg)))

        return length_encoded + value_encoded

    if base == 'hash':
        if not (int(sub) and int(sub) <= 32):
            raise EncodingError('too long: %r' % arg)

        if is_numeric(arg):
            return zpad(encode_int(arg), 32)

        if len(arg) == int(sub):
            return zpad(arg, 32)

        if len(arg) == int(sub) * 2:
            return zpad(decode_hex(arg), 32)

        raise EncodingError('Could not parse hash: %r' % arg)

    if base == 'address':
        assert sub == ''

        if is_numeric(arg):
            return zpad(encode_int(arg), 32)

        if len(arg) == 20:
            return zpad(arg, 32)

        if len(arg) == 40:
            return zpad(decode_hex(arg), 32)

        if len(arg) == 42 and arg[:2] == '0x':
            return zpad(decode_hex(arg[2:]), 32)

        raise EncodingError('Could not parse address: %r' % arg)
    raise EncodingError('Unhandled type: %r %r' % (base, sub))
Example #25
0
def snapshot_form(val):
    if is_numeric(val):
        return str(val)
    elif is_string(val):
        return '0x' + encode_hex(val)
Example #26
0
def apply_transaction(block, tx):
    validate_transaction(block, tx)

    log_tx.debug('TX NEW', tx_dict=tx.log_dict())
    # start transacting #################
    block.increment_nonce(tx.sender)
    # print block.get_nonce(tx.sender), '@@@'

    # buy startgas
    assert block.get_balance(tx.sender) >= tx.startgas * tx.gasprice
    block.delta_balance(tx.sender, -tx.startgas * tx.gasprice)
    message_gas = tx.startgas - intrinsic_gas_used(tx)
    message_data = vm.CallData([safe_ord(x) for x in tx.data], 0, len(tx.data))
    message = vm.Message(tx.sender, tx.to, tx.value, message_gas, message_data, code_address=tx.to)

    # MESSAGE
    ext = VMExt(block, tx)
    if tx.to and tx.to != CREATE_CONTRACT_ADDRESS:
        result, gas_remained, data = apply_msg(ext, message)
        log_tx.debug('_res_', result=result, gas_remained=gas_remained, data=data)
    else:  # CREATE
        result, gas_remained, data = create_contract(ext, message)
        assert utils.is_numeric(gas_remained)
        log_tx.debug('_create_', result=result, gas_remained=gas_remained, data=data)

    assert gas_remained >= 0

    log_tx.debug("TX APPLIED", result=result, gas_remained=gas_remained,
                 data=data)

    if not result:  # 0 = OOG failure in both cases
        log_tx.debug('TX FAILED', reason='out of gas',
                     startgas=tx.startgas, gas_remained=gas_remained)
        block.gas_used += tx.startgas
        block.delta_balance(block.coinbase, tx.gasprice * tx.startgas)
        output = b''
        success = 0
    else:
        log_tx.debug('TX SUCCESS', data=data)
        gas_used = tx.startgas - gas_remained
        block.refunds += len(set(block.suicides)) * opcodes.GSUICIDEREFUND
        if block.refunds > 0:
            log_tx.debug('Refunding', gas_refunded=min(block.refunds, gas_used // 2))
            gas_remained += min(block.refunds, gas_used // 2)
            gas_used -= min(block.refunds, gas_used // 2)
            block.refunds = 0
        # sell remaining gas
        block.delta_balance(tx.sender, tx.gasprice * gas_remained)
        block.delta_balance(block.coinbase, tx.gasprice * gas_used)
        block.gas_used += gas_used
        if tx.to:
            output = b''.join(map(ascii_chr, data))
        else:
            output = data
        success = 1
    block.commit_state()
    suicides = block.suicides
    block.suicides = []
    for s in suicides:
        block.ether_delta -= block.get_balance(s)
        block.set_balance(s, 0)
        block.del_account(s)
    block.add_transaction_to_list(tx)
    block.logs = []
    return success, output
Example #27
0
def apply_transaction(block, tx):
    validate_transaction(block, tx)

    # print(block.get_nonce(tx.sender), '@@@')

    def rp(what, actual, target):
        return "%r: %r actual:%r target:%r" % (tx, what, actual, target)

    intrinsic_gas = tx.intrinsic_gas_used
    if block.number >= block.config["HOMESTEAD_FORK_BLKNUM"]:
        assert tx.s * 2 < transactions.secpk1n
        if not tx.to or tx.to == CREATE_CONTRACT_ADDRESS:
            intrinsic_gas += opcodes.CREATE[3]
            if tx.startgas < intrinsic_gas:
                raise InsufficientStartGas(rp("startgas", tx.startgas, intrinsic_gas))

    log_tx.debug("TX NEW", tx_dict=tx.log_dict())
    # start transacting #################
    block.increment_nonce(tx.sender)

    # buy startgas
    assert block.get_balance(tx.sender) >= tx.startgas * tx.gasprice
    block.delta_balance(tx.sender, -tx.startgas * tx.gasprice)
    message_gas = tx.startgas - intrinsic_gas
    message_data = vm.CallData([safe_ord(x) for x in tx.data], 0, len(tx.data))
    message = vm.Message(tx.sender, tx.to, tx.value, message_gas, message_data, code_address=tx.to)

    # MESSAGE
    ext = VMExt(block, tx)
    if tx.to and tx.to != CREATE_CONTRACT_ADDRESS:
        result, gas_remained, data = apply_msg(ext, message)
        log_tx.debug("_res_", result=result, gas_remained=gas_remained, data=lazy_safe_encode(data))
    else:  # CREATE
        result, gas_remained, data = create_contract(ext, message)
        assert utils.is_numeric(gas_remained)
        log_tx.debug("_create_", result=result, gas_remained=gas_remained, data=lazy_safe_encode(data))

    assert gas_remained >= 0

    log_tx.debug("TX APPLIED", result=result, gas_remained=gas_remained, data=lazy_safe_encode(data))

    if not result:  # 0 = OOG failure in both cases
        log_tx.debug("TX FAILED", reason="out of gas", startgas=tx.startgas, gas_remained=gas_remained)
        block.gas_used += tx.startgas
        block.delta_balance(block.coinbase, tx.gasprice * tx.startgas)
        output = b""
        success = 0
    else:
        log_tx.debug("TX SUCCESS", data=lazy_safe_encode(data))
        gas_used = tx.startgas - gas_remained
        block.refunds += len(set(block.suicides)) * opcodes.GSUICIDEREFUND
        if block.refunds > 0:
            log_tx.debug("Refunding", gas_refunded=min(block.refunds, gas_used // 2))
            gas_remained += min(block.refunds, gas_used // 2)
            gas_used -= min(block.refunds, gas_used // 2)
            block.refunds = 0
        # sell remaining gas
        block.delta_balance(tx.sender, tx.gasprice * gas_remained)
        block.delta_balance(block.coinbase, tx.gasprice * gas_used)
        block.gas_used += gas_used
        if tx.to:
            output = b"".join(map(ascii_chr, data))
        else:
            output = data
        success = 1
    block.commit_state()
    suicides = block.suicides
    block.suicides = []
    for s in suicides:
        block.ether_delta -= block.get_balance(s)
        block.set_balance(s, 0)
        block.del_account(s)
    block.add_transaction_to_list(tx)
    block.logs = []
    return success, output
Example #28
0
 def getStorageAt(self, address, index, block_id=None):
     block = self.json_rpc_server.get_block(block_id)
     i = block.get_storage_data(address, index)
     assert is_numeric(i)
     return int_to_big_endian(i)
Example #29
0
def quantity_encoder(i):
    """Encode interger quantity `data`."""
    assert is_numeric(i)
    data = int_to_big_endian(i)
    return '0x' + (encode_hex(data).lstrip('0') or '0')
Example #30
0
def apply_transaction(block, tx):
    validate_transaction(block, tx)

    log_tx.debug('TX NEW', tx_dict=tx.log_dict())
    # start transacting #################
    block.increment_nonce(tx.sender)
    # print block.get_nonce(tx.sender), '@@@'

    # buy startgas
    assert block.get_balance(tx.sender) >= tx.startgas * tx.gasprice
    block.delta_balance(tx.sender, -tx.startgas * tx.gasprice)
    message_gas = tx.startgas - intrinsic_gas_used(tx)
    message_data = vm.CallData([safe_ord(x) for x in tx.data], 0, len(tx.data))
    message = vm.Message(tx.sender,
                         tx.to,
                         tx.value,
                         message_gas,
                         message_data,
                         code_address=tx.to)

    # MESSAGE
    ext = VMExt(block, tx)
    if tx.to and tx.to != CREATE_CONTRACT_ADDRESS:
        result, gas_remained, data = apply_msg(ext, message)
        log_tx.debug('_res_',
                     result=result,
                     gas_remained=gas_remained,
                     data=data)
    else:  # CREATE
        result, gas_remained, data = create_contract(ext, message)
        assert utils.is_numeric(gas_remained)
        log_tx.debug('_create_',
                     result=result,
                     gas_remained=gas_remained,
                     data=data)

    assert gas_remained >= 0

    log_tx.debug("TX APPLIED",
                 result=result,
                 gas_remained=gas_remained,
                 data=data)

    if not result:  # 0 = OOG failure in both cases
        log_tx.debug('TX FAILED',
                     reason='out of gas',
                     startgas=tx.startgas,
                     gas_remained=gas_remained)
        block.gas_used += tx.startgas
        block.delta_balance(block.coinbase, tx.gasprice * tx.startgas)
        output = b''
        success = 0
    else:
        log_tx.debug('TX SUCCESS', data=data)
        gas_used = tx.startgas - gas_remained
        block.refunds += len(set(block.suicides)) * opcodes.GSUICIDEREFUND
        if block.refunds > 0:
            log_tx.debug('Refunding',
                         gas_refunded=min(block.refunds, gas_used // 2))
            gas_remained += min(block.refunds, gas_used // 2)
            gas_used -= min(block.refunds, gas_used // 2)
            block.refunds = 0
        # sell remaining gas
        block.delta_balance(tx.sender, tx.gasprice * gas_remained)
        block.delta_balance(block.coinbase, tx.gasprice * gas_used)
        block.gas_used += gas_used
        if tx.to:
            output = b''.join(map(ascii_chr, data))
        else:
            output = data
        success = 1
    block.commit_state()
    suicides = block.suicides
    block.suicides = []
    for s in suicides:
        block.ether_delta -= block.get_balance(s)
        block.set_balance(s, 0)
        block.del_account(s)
    block.add_transaction_to_list(tx)
    block.logs = []
    return success, output
Example #31
0
def quantity_encoder(i):
    """Encode interger quantity `data`."""
    assert is_numeric(i)
    data = int_to_big_endian(i)
    return '0x' + (encode_hex(data).lstrip('0') or '0')
Example #32
0
 def getStorageAt(self, address, index, block_id=None):
     block = self.json_rpc_server.get_block(block_id)
     i = block.get_storage_data(address, index)
     assert is_numeric(i)
     return int_to_big_endian(i)
Example #33
0
def apply_transaction(block, tx, cb=None, validate=True):
    eth_call = False
    def dummy_cb(*args, **kwargs):
        pass

    if cb is None:
        cb = dummy_cb
        eth_call = True

    if validate:
        validate_transaction(block, tx)

    log_tx.debug('TX NEW', tx_dict=tx.log_dict())
    # start transacting #################
    block.increment_nonce(tx.sender)

    intrinsic_gas = intrinsic_gas_used(tx)
    if block.number >= block.config['HOMESTEAD_FORK_BLKNUM']:
        assert tx.s * 2 < transactions.secpk1n
        if not tx.to or tx.to == CREATE_CONTRACT_ADDRESS:
            intrinsic_gas += opcodes.CREATE[3]
            if tx.startgas < intrinsic_gas:
                raise InsufficientStartGas(rp('startgas', tx.startgas, intrinsic_gas))

    # buy startgas
    if validate:
        assert block.get_balance(tx.sender) >= tx.startgas * tx.gasprice

    block.delta_balance(tx.sender, -tx.startgas * tx.gasprice)
    message_gas = tx.startgas - intrinsic_gas
    message_data = vm.CallData([safe_ord(x) for x in tx.data], 0, len(tx.data))
    message = vm.Message(tx.sender, tx.to, tx.value, message_gas, message_data, code_address=tx.to)

    # MESSAGE
    ext = CapVMExt(block, tx, cb)
    if tx.to and tx.to != CREATE_CONTRACT_ADDRESS:
        result, gas_remained, data = ext._msg(message)
        log_tx.debug('_res_', result=result, gas_remained=gas_remained, data=data)
    else:  # CREATE
        result, gas_remained, data = create_contract(ext, message)
        assert utils.is_numeric(gas_remained)
        log_tx.debug('_create_', result=result, gas_remained=gas_remained, data=data)

    assert gas_remained >= 0

    log_tx.debug("TX APPLIED", result=result, gas_remained=gas_remained,
                 data=data)

    if not result:  # 0 = OOG failure in both cases
        log_tx.debug('TX FAILED', reason='out of gas',
                     startgas=tx.startgas, gas_remained=gas_remained)
        block.gas_used += tx.startgas
        block.delta_balance(block.coinbase, tx.gasprice * tx.startgas)
        output = b''
        success = 0
    else:
        log_tx.debug('TX SUCCESS', data=data)
        gas_used = tx.startgas - gas_remained
        block.refunds += len(set(block.suicides)) * opcodes.GSUICIDEREFUND
        if block.refunds > 0:
            log_tx.debug('Refunding', gas_refunded=min(block.refunds, gas_used // 2))
            gas_remained += min(block.refunds, gas_used // 2)
            gas_used -= min(block.refunds, gas_used // 2)
            block.refunds = 0
        # sell remaining gas
        block.delta_balance(tx.sender, tx.gasprice * gas_remained)
        block.delta_balance(block.coinbase, tx.gasprice * gas_used)
        block.gas_used += gas_used
        if tx.to:
            output = b''.join(map(ascii_chr, data))
        else:
            output = data
        success = 1
    block.commit_state()
    suicides = block.suicides
    block.suicides = []
    for s in suicides:
        block.ether_delta -= block.get_balance(s)
        block.set_balance(s, 0)
        block.del_account(s)
    block.add_transaction_to_list(tx)
    block.logs = []
    return success, output