Beispiel #1
0
def test():
    t.gas_price = 0
    s = t.state()
    c = s.abi_contract('randao.se')
    votes = []
    ids = []
    xor = 0
    for i in range(5):
        r = random.randrange(2**256)
        xor ^= r
        votes.append(utils.zpad(utils.encode_int(r), 32))
    f = c.getFee()
    for i in range(5):
        ids.append(c.submitHash(utils.sha3(votes[i]), value=f))
    while c.getPhase() == 0:
        s.mine(10)
    for i in range(5):
        c.submitValue(ids[i], votes[i])
    while c.getPhase() == 1:
        s.mine(10)
    c.claimResults()
    assert c.getNextResultPos() == 1
    assert c.getResult(0) == utils.zpad(
        utils.encode_int(xor),
        32), (c.getResult(0), utils.zpad(utils.encode_int(xor), 32))
Beispiel #2
0
def test():
    t.gas_price = 0
    s = t.state()
    c = s.abi_contract("randao.se")
    votes = []
    ids = []
    xor = 0
    for i in range(5):
        r = random.randrange(2 ** 256)
        xor ^= r
        votes.append(utils.zpad(utils.encode_int(r), 32))
    f = c.getFee()
    for i in range(5):
        ids.append(c.submitHash(utils.sha3(votes[i]), value=f))
    while c.getPhase() == 0:
        s.mine(10)
    for i in range(5):
        c.submitValue(ids[i], votes[i])
    while c.getPhase() == 1:
        s.mine(10)
    c.claimResults()
    assert c.getNextResultPos() == 1
    assert c.getResult(0) == utils.zpad(utils.encode_int(xor), 32), (
        c.getResult(0),
        utils.zpad(utils.encode_int(xor), 32),
    )
Beispiel #3
0
 def to_dict(self):
     odict = self.storage_trie.to_dict()
     for k, v in self.storage_cache.items():
         odict[utils.encode_int(k)] = rlp.encode(utils.encode_int(v))
     return {'balance': str(self.balance), 'nonce': str(self.nonce), 'code': '0x' + encode_hex(self.code),
             'storage': {'0x' + encode_hex(key.lstrip(b'\x00') or b'\x00'):
                         '0x' + encode_hex(rlp.decode(val)) for key, val in odict.items()}}
Beispiel #4
0
def mk_independent_transaction_spv_proof(block, index):
    block = blocks.Block.init_from_header(block.db, block.list_header())
    tx = transactions.Transaction.create(block.get_transaction(index))
    block.get_receipt(index)
    if index > 0:
        pre_med, pre_gas, _, _ = block.get_receipt(index - 1)
    else:
        pre_med, pre_gas = block.get_parent().state_root, 0
    block.state_root = pre_med
    block.gas_used = pre_gas
    nodes = mk_transaction_spv_proof(block, tx)
    nodes.extend(
        block.transactions.produce_spv_proof(
            rlp.encode(utils.encode_int(index))))
    if index > 0:
        nodes.extend(
            block.transactions.produce_spv_proof(
                rlp.encode(utils.encode_int(index - 1))))
    nodes = list(map(rlp.decode, list(set(map(rlp.encode, nodes)))))
    print(nodes)
    return rlp.encode([
        utils.encode_int(64),
        block.get_parent().list_header(),
        block.list_header(),
        utils.encode_int(index), nodes
    ])
 def listen(cls, log_, address=None, callback=None):
     if not len(log_.topics) or log_.topics[0] != cls.event_id():
         return
     if address and address != log_.address:
         return
     # o = dict(address=log_.address)
     o = dict()
     for i, t in enumerate(log_.topics[1:]):
         name = cls.args[i]['name']
         if cls.arg_types()[i] in ('string', 'bytes'):
             assert t < 2**256, "error with {}, user bytes32".format(
                 cls.args[i])
             d = encode_int(t)
         else:
             assert t < 2**256
             d = zpad(encode_int(t), 32)
         data = abi.decode_abi([cls.arg_types()[i]], d)[0]
         o[name] = data
     o['event_type'] = cls.__name__
     unindexed_types = [a['type'] for a in cls.args if not a['indexed']]
     o['args'] = abi.decode_abi(unindexed_types, log_.data)
     if callback:
         callback(o)
     else:
         print(o)
Beispiel #6
0
def sign_block(block, key, randao_parent, vchash, skips):
    block.header.extra_data = \
        randao_parent + \
        utils.zpad(utils.encode_int(skips), 32) + \
        vchash
    for val in utils.ecsign(block.header.signing_hash, key):
        block.header.extra_data += utils.zpad(utils.encode_int(val), 32)
    return block
Beispiel #7
0
    def _encode_function(self, signature, param_values):

        prefix = utils.big_endian_to_int(utils.sha3(signature)[:4])

        if signature.find('(') == -1:
            raise RuntimeError('Invalid function signature. Missing "(" and/or ")"...')

        if signature.find(')') - signature.find('(') == 1:
            return utils.encode_int(prefix)

        types = signature[signature.find('(') + 1: signature.find(')')].split(',')
        encoded_params = encode_abi(types, param_values)
        return utils.zpad(utils.encode_int(prefix), 4) + encoded_params
Beispiel #8
0
    def _encode_function(self, signature, param_values):

        prefix = utils.big_endian_to_int(utils.sha3(signature)[:4])

        if signature.find('(') == -1:
            raise RuntimeError('Invalid function signature. Missing "(" and/or ")"...')

        if signature.find(')') - signature.find('(') == 1:
            return utils.encode_int(prefix)

        types = signature[signature.find('(') + 1: signature.find(')')].split(',')
        encoded_params = encode_abi(types, param_values)
        return utils.zpad(utils.encode_int(prefix), 4) + encoded_params
Beispiel #9
0
def hash_array(arr):
    o = b''
    for x in arr:
        if isinstance(x, int):
            x = utils.zpad(utils.encode_int(x), 32)
        o += x
    return utils.big_endian_to_int(utils.sha3(o))
Beispiel #10
0
def hash_array(arr):
    o = ''
    for x in arr:
        if isinstance(x, (int, long)):
            x = utils.zpad(utils.encode_int(x), 32)
        o += x
    return utils.big_endian_to_int(utils.sha3(o))
Beispiel #11
0
 def listen(self, log, noprint=False):
     if not len(log.topics) or log.topics[0] not in self.event_data:
         return
     types = self.event_data[log.topics[0]]['types']
     name = self.event_data[log.topics[0]]['name']
     names = self.event_data[log.topics[0]]['names']
     indexed = self.event_data[log.topics[0]]['indexed']
     indexed_types = [types[i] for i in range(len(types)) if indexed[i]]
     unindexed_types = [
         types[i] for i in range(len(types)) if not indexed[i]
     ]
     # print('listen', log.data.encode('hex'), log.topics)
     deserialized_args = decode_abi(unindexed_types, log.data)
     o = {}
     c1, c2 = 0, 0
     for i in range(len(names)):
         if indexed[i]:
             topic_bytes = utils.zpad(utils.encode_int(log.topics[c1 + 1]),
                                      32)
             o[names[i]] = decode_single(process_type(indexed_types[c1]),
                                         topic_bytes)
             c1 += 1
         else:
             o[names[i]] = deserialized_args[c2]
             c2 += 1
     o["_event_type"] = utils.to_string(name)
     if not noprint:
         print(o)
     return o
Beispiel #12
0
 def listen(self, log, noprint=False):
     if not len(log.topics) or log.topics[0] not in self.event_data:
         return
     types = self.event_data[log.topics[0]]['types']
     name = self.event_data[log.topics[0]]['name']
     names = self.event_data[log.topics[0]]['names']
     indexed = self.event_data[log.topics[0]]['indexed']
     indexed_types = [types[i] for i in range(len(types))
                      if indexed[i]]
     unindexed_types = [types[i] for i in range(len(types))
                        if not indexed[i]]
     # print('listen', log.data.encode('hex'), log.topics)
     deserialized_args = decode_abi(unindexed_types, log.data)
     o = {}
     c1, c2 = 0, 0
     for i in range(len(names)):
         if indexed[i]:
             topic_bytes = utils.zpad(utils.encode_int(log.topics[c1 + 1]), 32)
             o[names[i]] = decode_single(process_type(indexed_types[c1]),
                                         topic_bytes)
             c1 += 1
         else:
             o[names[i]] = deserialized_args[c2]
             c2 += 1
     o["_event_type"] = utils.to_string(name)
     if not noprint:
         print(o)
     return o
Beispiel #13
0
def mk_wrapper(code):
    lencodepush = b'\x60' + utils.encode_int(len(code))  # length of code
    returner = lencodepush + b'\x60\x0c\x60\x00'  # start from 12 in code, 0 in memory
    returner += b'\x39'  # CODECOPY
    returner += lencodepush + b'\x60\x00' + b'\xf3'  # return code
    assert len(returner) == 12
    return returner + code
Beispiel #14
0
 def commit_refcount_changes(self, epoch):
     # Save death row nodes
     timeout_epoch = epoch + self.ttl
     try:
         death_row_nodes = rlp.decode(self.db.get('deathrow:'+str(timeout_epoch)))
     except:
         death_row_nodes = []
     for nodekey in self.death_row:
         refcount, val = rlp.decode(self.db.get(b'r:'+nodekey))
         if refcount == ZERO_ENCODED:
             new_refcount = utils.encode_int(DEATH_ROW_OFFSET + timeout_epoch)
             self.db.put(b'r:'+nodekey, rlp.encode([new_refcount, val]))
     if len(self.death_row) > 0:
         sys.stderr.write('%d nodes marked for pruning during block %d\n' %
                          (len(self.death_row), timeout_epoch))
     death_row_nodes.extend(self.death_row)
     self.death_row = []
     self.db.put('deathrow:'+str(timeout_epoch),
                 rlp.encode(death_row_nodes))
     # Save journal
     try:
         journal = rlp.decode(self.db.get('journal:'+str(epoch)))
     except:
         journal = []
     journal.extend(self.journal)
     self.journal = []
     self.db.put('journal:'+str(epoch), rlp.encode(journal))
Beispiel #15
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''
Beispiel #16
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''
Beispiel #17
0
    def _safe_call(self):
        log.debug('create native contract instance called')
        assert len(self._msg.sender) == 20
        assert len(self._msg.data.extract_all()) >= 4

        # get native contract
        nc_address = registry.native_contract_address_prefix + self._msg.data.extract_all()[:4]
        if nc_address not in registry:
            return 0, self._msg.gas, b''
        native_contract = registry[nc_address].im_self

        # get new contract address
        if self._ext.tx_origin != self._msg.sender:
            self._ext._block.increment_nonce(self._msg.sender)
        nonce = utils.encode_int(self._ext._block.get_nonce(self._msg.sender) - 1)
        self._msg.to = registry.mk_instance_address(native_contract, self._msg.sender, nonce)
        assert not self._ext.get_balance(self._msg.to)  # must be none existant

        # value was initially added to this contract's address, we need to transfer
        success = self._ext._block.transfer_value(self.address, self._msg.to, self._msg.value)
        assert success
        assert not self._ext.get_balance(self.address)

        # call new instance with additional data
        self._msg.is_create = True
        self._msg.data = vm.CallData(self._msg.data.data[4:], 0, 0)
        res, gas, dat = registry[self._msg.to](self._ext, self._msg)
        assert gas >= 0
        log.debug('created native contract instance', template=nc_address.encode('hex'),
                  instance=self._msg.to.encode('hex'))
        return res, gas, memoryview(self._msg.to).tolist()
Beispiel #18
0
 def encode_function_call(self, function_name, args):
     if function_name not in self.function_data:
         raise ValueError('Unkown function {}'.format(function_name))
     description = self.function_data[function_name]
     function_selector = zpad(encode_int(description['prefix']), 4)
     arguments = encode_abi(description['encode_types'], args)
     return function_selector + arguments
Beispiel #19
0
def sha3num(*args):
    o = ''
    for arg in args:
        if isinstance(arg, (int, long)):
            o += utils.zpad(utils.encode_int(arg), 32)
        else:
            o += arg
    return utils.sha3(o)
Beispiel #20
0
 def eth_getStorageAt(self, address, position):
     '''
     gets account storage data at position
     '''
     account = self.reader._get_account(address)
     return _encode_hex(
         utils.zpad(utils.encode_int(account.get_storage_data(position)),
                    32))
Beispiel #21
0
def sha3num(*args):
    o = ''
    for arg in args:
        if isinstance(arg, (int, long)):
            o += utils.zpad(utils.encode_int(arg), 32)
        else:
            o += arg
    return utils.sha3(o)
Beispiel #22
0
def mk_independent_transaction_spv_proof(block, index):
    block = blocks.Block.init_from_header(block.db, block.list_header())
    tx = transactions.Transaction.create(block.get_transaction(index))
    block.get_receipt(index)
    if index > 0:
        pre_med, pre_gas, _, _ = block.get_receipt(index - 1)
    else:
        pre_med, pre_gas = block.get_parent().state_root, 0
    block.state_root = pre_med
    block.gas_used = pre_gas
    nodes = mk_transaction_spv_proof(block, tx)
    nodes.extend(block.transactions.produce_spv_proof(rlp.encode(utils.encode_int(index))))
    if index > 0:
        nodes.extend(block.transactions.produce_spv_proof(rlp.encode(utils.encode_int(index - 1))))
    nodes = list(map(rlp.decode, list(set(map(rlp.encode, nodes)))))
    print(nodes)
    return rlp.encode([utils.encode_int(64), block.get_parent().list_header(),
                       block.list_header(), utils.encode_int(index), nodes])
Beispiel #23
0
 def create_wrapper(msg):
     sender = decode_hex(msg.sender) if \
         len(msg.sender) == 40 else msg.sender
     nonce = utils.encode_int(ext._block.get_nonce(msg.sender))
     addr = utils.sha3(rlp.encode([sender, nonce]))[12:]
     hexdata = encode_hex(msg.data.extract_all())
     apply_message_calls.append(dict(gasLimit=to_string(msg.gas),
                                     value=to_string(msg.value),
                                     destination=b'', data=b'0x' + hexdata))
     return 1, msg.gas, addr
Beispiel #24
0
def get_multisend_gas(payments):
    o = 26002  # 21000 + 2 (CALLER) + 5000 (SELFDESTRUCT)
    for address, wei in payments.items():
        encoded_wei = utils.encode_int(wei) or b'\x00'
        # 20 bytes in txdata for address = 1360
        # bytes in txdata for wei = 68 * n
        # gas for pushes and pops = 3 * 7 + 2 = 23
        # CALL = 9700 + 25000 (possible if new account)
        o += 1360 + 68 * len(encoded_wei) + 23 + 34700
    return o
Beispiel #25
0
 def zpadhex(data, digit=64):
     if type(data) == int:
         d = str(data)
         h = '0' * (64 - len(d)) + d
     elif type(data) == str:
         d = data.encode().hex()
         h = '0' * (64 - len(d)) + d
     else:
         h = zpad(encode_int(data), digit).hex()
     return h
Beispiel #26
0
def mk_multisend_code(payments):  # expects a dictionary, {address: wei}
    kode = b''
    for address, wei in payments.items():
        kode += b'\x60\x00\x60\x00\x60\x00\x60\x00'  # 0 0 0 0
        encoded_wei = utils.encode_int(wei) or b'\x00'
        kode += utils.ascii_chr(0x5f + len(encoded_wei)) + encoded_wei  # value
        kode += b'\x73' + utils.normalize_address(address)  # to
        kode += b'\x60\x00\xf1\x50'  # 0 CALL POP
    kode += b'\x33\xff'  # CALLER SELFDESTRUCT
    return kode
Beispiel #27
0
 def create_wrapper(msg):
     sender = decode_hex(msg.sender) if \
         len(msg.sender) == 40 else msg.sender
     nonce = utils.encode_int(ext._block.get_nonce(msg.sender))
     addr = utils.sha3(rlp.encode([sender, nonce]))[12:]
     hexdata = encode_hex(msg.data.extract_all())
     apply_message_calls.append(dict(gasLimit=to_string(msg.gas),
                                     value=to_string(msg.value),
                                     destination=b'', data=b'0x' + hexdata))
     return 1, msg.gas, addr
Beispiel #28
0
    def eth_getStorageAt(self, address, position):
        """Get account storage data at position.

        :param address:
        :param position:
        :return:
        """
        account = self.reader._get_account(address)
        return _encode_hex(
            utils.zpad(utils.encode_int(account.get_storage_data(position)),
                       32))
Beispiel #29
0
def rlp_cost(nonce):
    if nonce == 0:
        return 1036
    elif nonce <= 127:
        return 906
    else:
        hex = utils.encode_hex(utils.encode_int(nonce))
        num_bytes = len(hex) / 2
        cost = 1058 + num_bytes * 60
        if nonce >= 256**8:
            cost -= 50
        return cost
Beispiel #30
0
 def listen(cls, log, address=None, callback=None):
     if not len(log.topics) or log.topics[0] != cls.event_id():
         return
     if address and address != log.address:
         return
     o = {}
     for i, t in enumerate(log.topics[1:]):
         name = cls.args[i]['name']
         if cls.arg_types()[i] in ('string', 'bytes'):
             d = encode_int(t)
         else:
             d = zpad(encode_int(t), 32)
         data = abi.decode_abi([cls.arg_types()[i]], d)[0]
         o[name] = data
     o['event_type'] = cls.__name__
     unindexed_types = [a['type'] for a in cls.args if not a['indexed']]
     o['args'] = abi.decode_abi(unindexed_types, log.data)
     if callback:
         callback(o)
     else:
         print(o)
Beispiel #31
0
 def listen(cls, log, address=None, callback=None):
     if not len(log.topics) or log.topics[0] != cls.event_id():
         return
     if address and address != log.address:
         return
     o = {}
     for i, t in enumerate(log.topics[1:]):
         name = cls.args[i]['name']
         if cls.arg_types()[i] in ('string', 'bytes'):
             d = encode_int(t)
         else:
             d = zpad(encode_int(t), 32)
         data = abi.decode_abi([cls.arg_types()[i]], d)[0]
         o[name] = data
     o['event_type'] = cls.__name__
     unindexed_types = [a['type'] for a in cls.args if not a['indexed']]
     o['args'] = abi.decode_abi(unindexed_types, log.data)
     if callback:
         callback(o)
     else:
         print(o)
Beispiel #32
0
 def dec_refcount(self, k):
     # raise Exception("WHY AM I CHANGING A REFCOUNT?!:?")
     node_object = rlp.decode(self.db.get(b'r:'+k))
     refcount = utils.decode_int(node_object[0])
     if self.logging:
         sys.stderr.write('decreasing %s to: %d\n' % (utils.encode_hex(k), refcount - 1))
     assert refcount > 0
     self.journal.append([node_object[0], k])
     new_refcount = utils.encode_int(refcount - 1)
     self.db.put(b'r:'+k, rlp.encode([new_refcount, node_object[1]]))
     if new_refcount == ZERO_ENCODED:
         self.death_row.append(k)
Beispiel #33
0
    def decode_event(self, log_topics, log_data):
        """ Return a dictionary representation the log.

        Note:
            This function won't work with anonymous events.

        Args:
            log_topics (List[bin]): The log's indexed arguments.
            log_data (bin): The encoded non-indexed arguments.
        """

        # topics[0]: keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")
        # If the event is declared as anonymous the topics[0] is not generated;
        if not len(log_topics) or log_topics[0] not in self.event_data:
            raise ValueError('Unknown log type')

        event_id_ = log_topics[0]

        event = self.event_data[event_id_]

        # data: abi_serialise(EVENT_NON_INDEXED_ARGS)
        # EVENT_NON_INDEXED_ARGS is the series of EVENT_ARGS that are not
        # indexed, abi_serialise is the ABI serialisation function used for
        # returning a series of typed values from a function.
        unindexed_types = [
            type_
            for type_, indexed in zip(event['types'], event['indexed'])
            if not indexed
        ]
        unindexed_args = decode_abi(unindexed_types, log_data)

        # topics[n]: EVENT_INDEXED_ARGS[n - 1]
        # EVENT_INDEXED_ARGS is the series of EVENT_ARGS that are indexed
        indexed_count = 1  # skip topics[0]

        result = {}
        for name, type_, indexed in zip(
                event['names'], event['types'], event['indexed']):
            if indexed:
                topic_bytes = utils.zpad(
                    utils.encode_int(log_topics[indexed_count]),
                    32,
                )
                indexed_count += 1
                value = decode_single(process_type(type_), topic_bytes)
            else:
                value = unindexed_args.pop(0)

            result[name] = value
        result['_event_type'] = utils.to_string(event['name'])

        return result
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''
Beispiel #35
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""
Beispiel #36
0
 def decode_contract_call(contract_abi, call_data):
     call_data_bin = decode_hex(call_data)
     method_signature = call_data_bin[:4]
     for description in contract_abi:
         if description.get('type') != 'function':
             continue
         method_name = normalize_abi_method_name(description['name'])
         arg_types = [item['type'] for item in description['inputs']]
         method_id = get_abi_method_id(method_name, arg_types)
         if zpad(encode_int(method_id), 4) == method_signature:
             try:
                 args = decode_abi(arg_types, call_data_bin[4:])
             except AssertionError:
                 # Invalid args
                 continue
             return method_name, args
    def make_match(self, buyer, seller):
        if buyer.epoch < self.current_block + self.SEALED_WINDOW:
            print(self.name, 'making sealed offer', buyer.id, seller.id)
            # TODO: check hash for adding sealed offer, ie hash preferences?
            # TODO: rework this, see reveal
            hash_arr = [buyer.epoch, buyer.id, seller.id]
            shasum = utils.sha3(''.join(map(lambda x: utils.zpad(utils.encode_int(x), 32), hash_arr)))
            # shasum = utils.sha3(hash_arr)
            # TODO check epoch against SEALED_WINDOW
            offer_id = self.market.add_sealed_offer(buyer.id, shasum)
            print(self.name, 'shasum', utils.decode_int(shasum))

            # TODO, combine preferences
            # TODO rework this, can probably just have buyer and seller instead of id's only
            offer = Offer(offer_id, buyer.epoch, buyer.id, seller.id, shasum, buyer.preferences)
            self.sealed_offers.append(offer)
    def new_ticket(self, price):
        ticket_id = self.market.add()
        # self.market.add_preference(ticket, 'head', 10)
        # self.market.add_preference(ticket, 'tail', 20)
        self.market.add_preference(ticket_id, 'price', price)
        self.market.activate(ticket_id)

        info = self.market.get_info(ticket_id)
        # Rebuild Preferences
        preferences = self.market.get_preferences(ticket_id)
        keys = [utils.encode_int(x) for x in preferences[::2]]
        preferences = dict(zip(keys, preferences[1::2]))
        del preferences['']

        self.ticket = Ticket(ticket_id, info[0], info[1], preferences)
        print(self.name, 'created new ticket', ticket_id, price)
Beispiel #39
0
 def inc_refcount(self, k, v):
     # raise Exception("WHY AM I CHANGING A REFCOUNT?!:?")
     try:
         node_object = rlp.decode(self.db.get(b'r:'+k))
         refcount = utils.decode_int(node_object[0])
         self.journal.append([node_object[0], k])
         if refcount >= DEATH_ROW_OFFSET:
             refcount = 0
         new_refcount = utils.encode_int(refcount + 1)
         self.db.put(b'r:'+k, rlp.encode([new_refcount, v]))
         if self.logging:
             sys.stderr.write('increasing %s %r to: %d\n' % (utils.encode_hex(k), v, refcount + 1))
     except:
         self.db.put(b'r:'+k, rlp.encode([ONE_ENCODED, v]))
         self.journal.append([ZERO_ENCODED, k])
         if self.logging:
             sys.stderr.write('increasing %s %r to: %d\n' % (utils.encode_hex(k), v, 1))
Beispiel #40
0
 def OP_CREATE():
     value, mstart, msz = stk.pop(), stk.pop(), stk.pop()
     if not mem_extend(mem, msgtop.compustate, '', mstart, msz):
         return drop(OUT_OF_GAS)
     if block.get_balance(msgtop.to) >= value:
         sender = decode_hex(msgtop.to) if len(msgtop.to) == 40 else msgtop.to
         block.increment_nonce(msgtop.to)
         data = [0] * ((msz >> 5) + 1)
         copy32(mem, data, mstart, 0, msz)
         create_msg = Message(msgtop.to, '', value, gaz() - 100, data, msz)
         msgtop.compustate.gas -= gaz() - 100
         nonce = utils.encode_int(block.get_nonce(msgtop.to) - 1)
         create_msg.to = encode_hex(utils.sha3(rlp.encode([sender, nonce]))[12:])
         special[0] = 'create'
         special[1] = create_msg
         special[2] = ''.join([ascii_chr(x) for x in extract_bytes(data, 0, msz)])
     else:
         stk.append(0)
Beispiel #41
0
    def make_match(self, buyer, seller):
        if buyer.epoch < self.current_block + self.SEALED_WINDOW:
            print(self.name, 'making sealed offer', buyer.id, seller.id)
            # TODO: check hash for adding sealed offer, ie hash preferences?
            # TODO: rework this, see reveal
            hash_arr = [buyer.epoch, buyer.id, seller.id]
            shasum = utils.sha3(''.join(
                map(lambda x: utils.zpad(utils.encode_int(x), 32), hash_arr)))
            # shasum = utils.sha3(hash_arr)
            # TODO check epoch against SEALED_WINDOW
            offer_id = self.market.add_sealed_offer(buyer.id, shasum)
            print(self.name, 'shasum', utils.decode_int(shasum))

            # TODO, combine preferences
            # TODO rework this, can probably just have buyer and seller instead of id's only
            offer = Offer(offer_id, buyer.epoch, buyer.id, seller.id, shasum,
                          buyer.preferences)
            self.sealed_offers.append(offer)
Beispiel #42
0
    def chain_difficulty(self):
        """Get the summarized difficulty.

        If the summarized difficulty is not stored in the database, it will be
        calculated recursively and put in the database.
        """
        if self.is_genesis():
            return self.difficulty
        elif b'difficulty:' + encode_hex(self.hash) in self.db:
            encoded = self.db.get(b'difficulty:' + encode_hex(self.hash))
            return utils.decode_int(encoded)
        else:
            o = self.difficulty + self.get_parent().chain_difficulty()
            # o += sum([uncle.difficulty for uncle in self.uncles])
            self.state.db.put(b'difficulty:' + encode_hex(self.hash),
                              utils.encode_int(o))
            return o

            return rlp.decode(rlp.encode(l)) == l
    def listener(self, msg):
        '''
        Dynamically call Methods based on first param
        Currently only announce exists

        Also calls process on new block number, based on delta event
        '''
        event = msg['event']
        # if event != 'LOG' and event != 'vm':
        #     print(event)

        if event == 'LOG' and msg['to'] == self.market.address:
            msg_type = utils.encode_int(msg['topics'][0]).rstrip('\x00')
            msg_data = msg['topics'][1:]
            if hasattr(self, msg_type):
                getattr(self, msg_type)(msg_data)
        elif event == 'delta':
            if self.current_block < self.state.block.number:
                self.current_block = self.state.block.number
                self.process()
    def listener(self, msg):
        '''
        Dynamically call Methods based on first param
        Currently only announce exists

        Also calls process on new block number, based on delta event
        '''
        event = msg['event']
        # if event != 'LOG' and event != 'vm':
        #     print(event)

        if event == 'LOG' and msg['to'] == self.market.address:
            msg_type = utils.encode_int(msg['topics'][0]).rstrip('\x00')
            msg_data = msg['topics'][1:]
            if hasattr(self, msg_type):
                getattr(self, msg_type)(msg_data)
        elif event == 'delta':
            if self.current_block < self.state.block.number:
                self.current_block = self.state.block.number
                self.process()
    def announce(self, data):
        ''' A new ticket has arrived '''
        ticket_id = data[0]
        info = self.market.get_info(ticket_id)

        # Rebuild Preferences
        preferences = self.market.get_preferences(ticket_id)
        keys = [utils.encode_int(x) for x in preferences[::2]]
        preferences = dict(zip(keys, preferences[1::2]))
        del preferences['']

        ticket = Ticket(ticket_id, info[0], info[1], preferences)

        # Our match maker assumes there is a price
        if ticket.preferences['price'] < 0:
            ticket.preferences['price'] = abs(ticket.preferences['price'])
            self.sellers.append(ticket)
        else:
            self.buyers.append(ticket)

        self.process()
Beispiel #46
0
    def encode_function_call(self, function_name, args):
        """ Return the encoded function call.

        Args:
            function_name (str): One of the existing functions described in the
                contract interface.
            args (List[object]): The function arguments that wll be encoded and
                used in the contract execution in the vm.

        Return:
            bin: The encoded function name and arguments so that it can be used
                 with the evm to execute a funcion call, the binary string follows
                 the Ethereum Contract ABI.
        """
        if function_name not in self.function_data:
            raise ValueError('Unkown function {}'.format(function_name))

        description = self.function_data[function_name]

        function_selector = zpad(encode_int(description['prefix']), 4)
        arguments = encode_abi(description['encode_types'], args)

        return function_selector + arguments
Beispiel #47
0
 def encode(self, name, args):
     fdata = self.function_data[name]
     o = zpad(encode_int(fdata['prefix']), 4) + \
         encode_abi(fdata['encode_types'], args)
     return o
Beispiel #48
0
 def OP_SUICIDE():
     to = utils.encode_int(stk.pop())
     to = encode_hex((('\x00' * (32 - len(to))) + to)[12:])
     block.transfer_value(msgtop.to, to, block.get_balance(msgtop.to))
     block.suicides.append(msgtop.to)
     drop([])
Beispiel #49
0
def hash_value(x):
    if isinstance(x, (int, long)):
        x = utils.zpad(utils.encode_int(x), 32)
    return utils.big_endian_to_int(utils.sha3(x))
Beispiel #50
0
def abi_encode_args(method, args):
    "encode args for method: method_id|data"
    assert issubclass(method.im_class, NativeABIContract), method.im_class
    m_abi = method.im_class._get_method_abi(method)
    return zpad(encode_int(m_abi['id']), 4) + abi.encode_abi(m_abi['arg_types'], args)
Beispiel #51
0
else:
    from functools import lru_cache


log = get_logger('eth.block')
log_state = get_logger('eth.msg.state')
Log = processblock.Log

# Genesis block difficulty
GENESIS_DIFFICULTY = 2**34
# Genesis block gas limit
GENESIS_GAS_LIMIT = 3141592
# Genesis block prevhash, coinbase, nonce
GENESIS_PREVHASH = b'\x00' * 32
GENESIS_COINBASE = b'\x00' * 20
GENESIS_NONCE = utils.zpad(utils.encode_int(42), 8)
GENESIS_MIXHASH = b'\x00' * 32
# Minimum gas limit
MIN_GAS_LIMIT = 125000
# Gas limit adjustment algo:
# block.gas_limit = block.parent.gas_limit * 1023/1024 +
#                   (block.gas_used * 6 / 5) / 1024
GASLIMIT_EMA_FACTOR = 1024
GASLIMIT_ADJMAX_FACTOR = 1024
BLKLIM_FACTOR_NOM = 3
BLKLIM_FACTOR_DEN = 2
# Block reward
BLOCK_REWARD = 5000 * utils.denoms.finney
# GHOST constants
UNCLE_DEPTH_PENALTY_FACTOR = 8
NEPHEW_REWARD = BLOCK_REWARD / 32
Beispiel #52
0
def encode_single(typ, arg):
    base, sub, _ = typ
    # Unsigned integers: uint<sz>
    if base == 'uint':
        sub = int(sub)
        i = decint(arg)

        if not 0 <= i < 2**sub:
            raise ValueOutOfBounds(repr(arg))
        return zpad(encode_int(i), 32)
    # bool: int<sz>
    elif base == 'bool':
        assert isinstance(arg, bool)
        return zpad(encode_int(int(arg)), 32)
    # Signed integers: int<sz>
    elif base == 'int':
        sub = int(sub)
        i = decint(arg)
        if not -2**(sub - 1) <= i < 2**sub:
            raise ValueOutOfBounds(repr(arg))
        return zpad(encode_int(i % 2**sub), 32)
    # Unsigned reals: ureal<high>x<low>
    elif base == 'ureal':
        high, low = [int(x) for x in sub.split('x')]
        if not 0 <= arg < 2**high:
            raise ValueOutOfBounds(repr(arg))
        return zpad(encode_int(arg * 2**low), 32)
    # Signed reals: real<high>x<low>
    elif base == 'real':
        high, low = [int(x) for x in sub.split('x')]
        if not -2**(high - 1) <= arg < 2**(high - 1):
            raise ValueOutOfBounds(repr(arg))
        return zpad(encode_int((arg % 2**high) * 2**low), 32)
    # Strings
    elif base == 'string' or base == 'bytes':
        if not is_string(arg):
            raise EncodingError("Expecting string: %r" % arg)
        # Fixed length: string<sz>
        if len(sub):
            assert int(sub) <= 32
            assert len(arg) <= int(sub)
            return arg + b'\x00' * (32 - len(arg))
        # Variable length: string
        else:
            return zpad(encode_int(len(arg)), 32) + \
                arg + \
                b'\x00' * (utils.ceil32(len(arg)) - len(arg))
    # Hashes: hash<sz>
    elif base == 'hash':
        if not (int(sub) and int(sub) <= 32):
            raise EncodingError("too long: %r" % arg)
        if isnumeric(arg):
            return zpad(encode_int(arg), 32)
        elif len(arg) == len(sub):
            return zpad(arg, 32)
        elif len(arg) == len(sub) * 2:
            return zpad(decode_hex(arg), 32)
        else:
            raise EncodingError("Could not parse hash: %r" % arg)
    # Addresses: address (== hash160)
    elif base == 'address':
        assert sub == ''
        if isnumeric(arg):
            return zpad(encode_int(arg), 32)
        elif len(arg) == 20:
            return zpad(arg, 32)
        elif len(arg) == 40:
            return zpad(decode_hex(arg), 32)
        else:
            raise EncodingError("Could not parse address: %r" % arg)
    raise EncodingError("Unhandled type: %r %r" % (base, sub))
Beispiel #53
0
 def encoded_abi_signature(self):
     return ethereum_utils.zpad(ethereum_utils.encode_int(self.abi_signature), 4)
Beispiel #54
0
def vm_execute(ext, msg, code):
    # precompute trace flag
    # if we trace vm, we're in slow mode anyway
    trace_vm = log_vm_op.is_active('trace')

    compustate = Compustate(gas=msg.gas)
    stk = compustate.stack
    mem = compustate.memory

    if code in code_cache:
        processed_code = code_cache[code]
    else:
        processed_code = preprocess_code(code)
        code_cache[code] = processed_code

    codelen = len(processed_code)

    s = time.time()
    op = None
    steps = 0
    _prevop = None  # for trace only

    while 1:
        # print('op: ', op, time.time() - s)
        # s = time.time()
        # stack size limit error
        if compustate.pc >= codelen:
            return peaceful_exit('CODE OUT OF RANGE', compustate.gas, [])

        op, in_args, out_args, fee, opcode, pushval = \
            processed_code[compustate.pc]

        # out of gas error
        if fee > compustate.gas:
            return vm_exception('OUT OF GAS')

        # empty stack error
        if in_args > len(compustate.stack):
            return vm_exception('INSUFFICIENT STACK',
                                op=op, needed=to_string(in_args),
                                available=to_string(len(compustate.stack)))

        if len(compustate.stack) - in_args + out_args > 1024:
            return vm_exception('STACK SIZE LIMIT EXCEEDED',
                                op=op,
                                pre_height=to_string(len(compustate.stack)))

        # Apply operation
        compustate.gas -= fee
        compustate.pc += 1

        if trace_vm:
            """
            This diverges from normal logging, as we use the logging namespace
            only to decide which features get logged in 'eth.vm.op'
            i.e. tracing can not be activated by activating a sub
            like 'eth.vm.op.stack'
            """
            trace_data = {}
            trace_data['stack'] = list(map(to_string, list(compustate.stack)))
            if _prevop in ('MLOAD', 'MSTORE', 'MSTORE8', 'SHA3', 'CALL',
                           'CALLCODE', 'CREATE', 'CALLDATACOPY', 'CODECOPY',
                           'EXTCODECOPY'):
                if len(compustate.memory) < 1024:
                    trace_data['memory'] = \
                        b''.join([encode_hex(ascii_chr(x)) for x
                                  in compustate.memory])
                else:
                    trace_data['sha3memory'] = \
                        encode_hex(utils.sha3(''.join([ascii_chr(x) for
                                              x in compustate.memory])))
            if _prevop in ('SSTORE', 'SLOAD') or steps == 0:
                trace_data['storage'] = ext.log_storage(msg.to)
            trace_data['gas'] = to_string(compustate.gas + fee)
            trace_data['inst'] = opcode
            trace_data['pc'] = to_string(compustate.pc - 1)
            if steps == 0:
                trace_data['depth'] = msg.depth
                trace_data['address'] = msg.to
            trace_data['op'] = op
            trace_data['steps'] = steps
            if op[:4] == 'PUSH':
                trace_data['pushvalue'] = pushval
            log_vm_op.trace('vm', **trace_data)
            steps += 1
            _prevop = op

        # Invalid operation
        if op == 'INVALID':
            return vm_exception('INVALID OP', opcode=opcode)

        # Valid operations
        if opcode < 0x10:
            if op == 'STOP':
                return peaceful_exit('STOP', compustate.gas, [])
            elif op == 'ADD':
                stk.append((stk.pop() + stk.pop()) & TT256M1)
            elif op == 'SUB':
                stk.append((stk.pop() - stk.pop()) & TT256M1)
            elif op == 'MUL':
                stk.append((stk.pop() * stk.pop()) & TT256M1)
            elif op == 'DIV':
                s0, s1 = stk.pop(), stk.pop()
                stk.append(0 if s1 == 0 else s0 // s1)
            elif op == 'MOD':
                s0, s1 = stk.pop(), stk.pop()
                stk.append(0 if s1 == 0 else s0 % s1)
            elif op == 'SDIV':
                s0, s1 = utils.to_signed(stk.pop()), utils.to_signed(stk.pop())
                stk.append(0 if s1 == 0 else (abs(s0) // abs(s1) *
                                              (-1 if s0 * s1 < 0 else 1)) & TT256M1)
            elif op == 'SMOD':
                s0, s1 = utils.to_signed(stk.pop()), utils.to_signed(stk.pop())
                stk.append(0 if s1 == 0 else (abs(s0) % abs(s1) *
                                              (-1 if s0 < 0 else 1)) & TT256M1)
            elif op == 'ADDMOD':
                s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
                stk.append((s0 + s1) % s2 if s2 else 0)
            elif op == 'MULMOD':
                s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
                stk.append((s0 * s1) % s2 if s2 else 0)
            elif op == 'EXP':
                base, exponent = stk.pop(), stk.pop()
                # fee for exponent is dependent on its bytes
                # calc n bytes to represent exponent
                nbytes = len(utils.encode_int(exponent))
                expfee = nbytes * opcodes.GEXPONENTBYTE
                if compustate.gas < expfee:
                    compustate.gas = 0
                    return vm_exception('OOG EXPONENT')
                compustate.gas -= expfee
                stk.append(pow(base, exponent, TT256))
            elif op == 'SIGNEXTEND':
                s0, s1 = stk.pop(), stk.pop()
                if s0 <= 31:
                    testbit = s0 * 8 + 7
                    if s1 & (1 << testbit):
                        stk.append(s1 | (TT256 - (1 << testbit)))
                    else:
                        stk.append(s1 & ((1 << testbit) - 1))
                else:
                    stk.append(s1)
        elif opcode < 0x20:
            if op == 'LT':
                stk.append(1 if stk.pop() < stk.pop() else 0)
            elif op == 'GT':
                stk.append(1 if stk.pop() > stk.pop() else 0)
            elif op == 'SLT':
                s0, s1 = utils.to_signed(stk.pop()), utils.to_signed(stk.pop())
                stk.append(1 if s0 < s1 else 0)
            elif op == 'SGT':
                s0, s1 = utils.to_signed(stk.pop()), utils.to_signed(stk.pop())
                stk.append(1 if s0 > s1 else 0)
            elif op == 'EQ':
                stk.append(1 if stk.pop() == stk.pop() else 0)
            elif op == 'ISZERO':
                stk.append(0 if stk.pop() else 1)
            elif op == 'AND':
                stk.append(stk.pop() & stk.pop())
            elif op == 'OR':
                stk.append(stk.pop() | stk.pop())
            elif op == 'XOR':
                stk.append(stk.pop() ^ stk.pop())
            elif op == 'NOT':
                stk.append(TT256M1 - stk.pop())
            elif op == 'BYTE':
                s0, s1 = stk.pop(), stk.pop()
                if s0 >= 32:
                    stk.append(0)
                else:
                    stk.append((s1 // 256 ** (31 - s0)) % 256)
        elif opcode < 0x40:
            if op == 'SHA3':
                s0, s1 = stk.pop(), stk.pop()
                compustate.gas -= opcodes.GSHA3WORD * (utils.ceil32(s1) // 32)
                if compustate.gas < 0:
                    return vm_exception('OOG PAYING FOR SHA3')
                if not mem_extend(mem, compustate, op, s0, s1):
                    return vm_exception('OOG EXTENDING MEMORY')
                data = b''.join(map(ascii_chr, mem[s0: s0 + s1]))
                stk.append(utils.big_endian_to_int(utils.sha3(data)))
            elif op == 'ADDRESS':
                stk.append(utils.coerce_to_int(msg.to))
            elif op == 'BALANCE':
                addr = utils.coerce_addr_to_hex(stk.pop() % 2**160)
                stk.append(ext.get_balance(addr))
            elif op == 'ORIGIN':
                stk.append(utils.coerce_to_int(ext.tx_origin))
            elif op == 'CALLER':
                stk.append(utils.coerce_to_int(msg.sender))
            elif op == 'CALLVALUE':
                stk.append(msg.value)
            elif op == 'CALLDATALOAD':
                stk.append(msg.data.extract32(stk.pop()))
            elif op == 'CALLDATASIZE':
                stk.append(msg.data.size)
            elif op == 'CALLDATACOPY':
                mstart, dstart, size = stk.pop(), stk.pop(), stk.pop()
                if not mem_extend(mem, compustate, op, mstart, size):
                    return vm_exception('OOG EXTENDING MEMORY')
                if not data_copy(compustate, size):
                    return vm_exception('OOG COPY DATA')
                msg.data.extract_copy(mem, mstart, dstart, size)
            elif op == 'CODESIZE':
                stk.append(len(processed_code))
            elif op == 'CODECOPY':
                start, s1, size = stk.pop(), stk.pop(), stk.pop()
                if not mem_extend(mem, compustate, op, start, size):
                    return vm_exception('OOG EXTENDING MEMORY')
                if not data_copy(compustate, size):
                    return vm_exception('OOG COPY DATA')
                for i in range(size):
                    if s1 + i < len(processed_code):
                        mem[start + i] = processed_code[s1 + i][4]
                    else:
                        mem[start + i] = 0
            elif op == 'GASPRICE':
                stk.append(ext.tx_gasprice)
            elif op == 'EXTCODESIZE':
                addr = utils.coerce_addr_to_hex(stk.pop() % 2**160)
                stk.append(len(ext.get_code(addr) or b''))
            elif op == 'EXTCODECOPY':
                addr = utils.coerce_addr_to_hex(stk.pop() % 2**160)
                start, s2, size = stk.pop(), stk.pop(), stk.pop()
                extcode = ext.get_code(addr) or b''
                assert utils.is_string(extcode)
                if not mem_extend(mem, compustate, op, start, size):
                    return vm_exception('OOG EXTENDING MEMORY')
                if not data_copy(compustate, size):
                    return vm_exception('OOG COPY DATA')
                for i in range(size):
                    if s2 + i < len(extcode):
                        mem[start + i] = utils.safe_ord(extcode[s2 + i])
                    else:
                        mem[start + i] = 0
        elif opcode < 0x50:
            if op == 'BLOCKHASH':
                stk.append(utils.big_endian_to_int(ext.block_hash(stk.pop())))
            elif op == 'COINBASE':
                stk.append(utils.big_endian_to_int(ext.block_coinbase))
            elif op == 'TIMESTAMP':
                stk.append(ext.block_timestamp)
            elif op == 'NUMBER':
                stk.append(ext.block_number)
            elif op == 'DIFFICULTY':
                stk.append(ext.block_difficulty)
            elif op == 'GASLIMIT':
                stk.append(ext.block_gas_limit)
        elif opcode < 0x60:
            if op == 'POP':
                stk.pop()
            elif op == 'MLOAD':
                s0 = stk.pop()
                if not mem_extend(mem, compustate, op, s0, 32):
                    return vm_exception('OOG EXTENDING MEMORY')
                data = b''.join(map(ascii_chr, mem[s0: s0 + 32]))
                stk.append(utils.big_endian_to_int(data))
            elif op == 'MSTORE':
                s0, s1 = stk.pop(), stk.pop()
                if not mem_extend(mem, compustate, op, s0, 32):
                    return vm_exception('OOG EXTENDING MEMORY')
                v = s1
                for i in range(31, -1, -1):
                    mem[s0 + i] = v % 256
                    v //= 256
            elif op == 'MSTORE8':
                s0, s1 = stk.pop(), stk.pop()
                if not mem_extend(mem, compustate, op, s0, 1):
                    return vm_exception('OOG EXTENDING MEMORY')
                mem[s0] = s1 % 256
            elif op == 'SLOAD':
                stk.append(ext.get_storage_data(msg.to, stk.pop()))
            elif op == 'SSTORE':
                s0, s1 = stk.pop(), stk.pop()
                if ext.get_storage_data(msg.to, s0):
                    gascost = opcodes.GSTORAGEMOD if s1 else opcodes.GSTORAGEKILL
                    refund = 0 if s1 else opcodes.GSTORAGEREFUND
                else:
                    gascost = opcodes.GSTORAGEADD if s1 else opcodes.GSTORAGEMOD
                    refund = 0
                if compustate.gas < gascost:
                    return vm_exception('OUT OF GAS')
                compustate.gas -= gascost
                ext.add_refund(refund)  # adds neg gascost as a refund if below zero
                ext.set_storage_data(msg.to, s0, s1)
            elif op == 'JUMP':
                compustate.pc = stk.pop()
                opnew = processed_code[compustate.pc][0] if \
                    compustate.pc < len(processed_code) else 'STOP'
                if opnew != 'JUMPDEST':
                    return vm_exception('BAD JUMPDEST')
            elif op == 'JUMPI':
                s0, s1 = stk.pop(), stk.pop()
                if s1:
                    compustate.pc = s0
                    opnew = processed_code[compustate.pc][0] if \
                        compustate.pc < len(processed_code) else 'STOP'
                    if opnew != 'JUMPDEST':
                        return vm_exception('BAD JUMPDEST')
            elif op == 'PC':
                stk.append(compustate.pc - 1)
            elif op == 'MSIZE':
                stk.append(len(mem))
            elif op == 'GAS':
                stk.append(compustate.gas)  # AFTER subtracting cost 1
        elif op[:4] == 'PUSH':
            pushnum = int(op[4:])
            compustate.pc += pushnum
            stk.append(pushval)
        elif op[:3] == 'DUP':
            depth = int(op[3:])
            stk.append(stk[-depth])
        elif op[:4] == 'SWAP':
            depth = int(op[4:])
            temp = stk[-depth - 1]
            stk[-depth - 1] = stk[-1]
            stk[-1] = temp

        elif op[:3] == 'LOG':
            """
            0xa0 ... 0xa4, 32/64/96/128/160 + len(data) gas
            a. Opcodes LOG0...LOG4 are added, takes 2-6 stack arguments
                    MEMSTART MEMSZ (TOPIC1) (TOPIC2) (TOPIC3) (TOPIC4)
            b. Logs are kept track of during tx execution exactly the same way as suicides
               (except as an ordered list, not a set).
               Each log is in the form [address, [topic1, ... ], data] where:
               * address is what the ADDRESS opcode would output
               * data is mem[MEMSTART: MEMSTART + MEMSZ]
               * topics are as provided by the opcode
            c. The ordered list of logs in the transaction are expressed as [log0, log1, ..., logN].
            """
            depth = int(op[3:])
            mstart, msz = stk.pop(), stk.pop()
            topics = [stk.pop() for x in range(depth)]
            compustate.gas -= msz * opcodes.GLOGBYTE
            if not mem_extend(mem, compustate, op, mstart, msz):
                return vm_exception('OOG EXTENDING MEMORY')
            data = b''.join(map(ascii_chr, mem[mstart: mstart + msz]))
            ext.log(msg.to, topics, data)
            log_log.trace('LOG', to=msg.to, topics=topics, data=list(map(utils.safe_ord, data)))
            # print('LOG', msg.to, topics, list(map(ord, data)))

        elif op == 'CREATE':
            value, mstart, msz = stk.pop(), stk.pop(), stk.pop()
            if not mem_extend(mem, compustate, op, mstart, msz):
                return vm_exception('OOG EXTENDING MEMORY')
            if ext.get_balance(msg.to) >= value and msg.depth < 1024:
                cd = CallData(mem, mstart, msz)
                create_msg = Message(msg.to, b'', value, compustate.gas, cd, msg.depth + 1)
                o, gas, addr = ext.create(create_msg)
                if o:
                    stk.append(utils.coerce_to_int(addr))
                    compustate.gas = gas
                else:
                    stk.append(0)
                    compustate.gas = 0
            else:
                stk.append(0)
        elif op == 'CALL':
            gas, to, value, meminstart, meminsz, memoutstart, memoutsz = \
                stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
            if not mem_extend(mem, compustate, op, meminstart, meminsz) or \
                    not mem_extend(mem, compustate, op, memoutstart, memoutsz):
                return vm_exception('OOG EXTENDING MEMORY')
            to = utils.encode_int(to)
            to = ((b'\x00' * (32 - len(to))) + to)[12:]
            extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \
                (value > 0) * opcodes.GCALLVALUETRANSFER
            submsg_gas = gas + opcodes.GSTIPEND * (value > 0)
            if compustate.gas < gas + extra_gas:
                return vm_exception('OUT OF GAS', needed=gas+extra_gas)
            if ext.get_balance(msg.to) >= value and msg.depth < 1024:
                compustate.gas -= (gas + extra_gas)
                cd = CallData(mem, meminstart, meminsz)
                call_msg = Message(msg.to, to, value, submsg_gas, cd,
                                   msg.depth + 1, code_address=to)
                result, gas, data = ext.msg(call_msg)
                if result == 0:
                    stk.append(0)
                else:
                    stk.append(1)
                    compustate.gas += gas
                    for i in range(min(len(data), memoutsz)):
                        mem[memoutstart + i] = data[i]
            else:
                compustate.gas -= (gas + extra_gas - submsg_gas)
                stk.append(0)
        elif op == 'CALLCODE' or op == 'DELEGATECALL':
            if op == 'CALLCODE':
                gas, to, value, meminstart, meminsz, memoutstart, memoutsz = \
                    stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
            else:
                gas, to, meminstart, meminsz, memoutstart, memoutsz = \
                    stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
                value = 0
            if not mem_extend(mem, compustate, op, meminstart, meminsz) or \
                    not mem_extend(mem, compustate, op, memoutstart, memoutsz):
                return vm_exception('OOG EXTENDING MEMORY')
            extra_gas = (value > 0) * opcodes.GCALLVALUETRANSFER
            submsg_gas = gas + opcodes.GSTIPEND * (value > 0)
            if compustate.gas < gas + extra_gas:
                return vm_exception('OUT OF GAS', needed=gas+extra_gas)
            if ext.get_balance(msg.to) >= value and msg.depth < 1024:
                compustate.gas -= (gas + extra_gas)
                to = utils.encode_int(to)
                to = ((b'\x00' * (32 - len(to))) + to)[12:]
                cd = CallData(mem, meminstart, meminsz)
                if ext.post_homestead_hardfork() and op == 'DELEGATECALL':
                    call_msg = Message(msg.sender, msg.to, msg.value, submsg_gas, cd,
                                       msg.depth + 1, code_address=to, transfers_value=False)
                elif op == 'DELEGATECALL':
                    return vm_exception('OPCODE INACTIVE')
                else:
                    call_msg = Message(msg.to, msg.to, value, submsg_gas, cd,
                                       msg.depth + 1, code_address=to)
                result, gas, data = ext.msg(call_msg)
                if result == 0:
                    stk.append(0)
                else:
                    stk.append(1)
                    compustate.gas += gas
                    for i in range(min(len(data), memoutsz)):
                        mem[memoutstart + i] = data[i]
            else:
                compustate.gas -= (gas + extra_gas - submsg_gas)
                stk.append(0)
        elif op == 'RETURN':
            s0, s1 = stk.pop(), stk.pop()
            if not mem_extend(mem, compustate, op, s0, s1):
                return vm_exception('OOG EXTENDING MEMORY')
            return peaceful_exit('RETURN', compustate.gas, mem[s0: s0 + s1])
        elif op == 'SUICIDE':
            to = utils.encode_int(stk.pop())
            to = ((b'\x00' * (32 - len(to))) + to)[12:]
            xfer = ext.get_balance(msg.to)
            ext.set_balance(to, ext.get_balance(to) + xfer)
            ext.set_balance(msg.to, 0)
            ext.add_suicide(msg.to)
            # print('suiciding %s %s %d' % (msg.to, to, xfer))
            return 1, compustate.gas, []
Beispiel #55
0
import rlp
import ethereum.utils as utils
import sys
from db import BaseDB

DEATH_ROW_OFFSET = 2**62
ZERO_ENCODED = utils.encode_int(0)
ONE_ENCODED = utils.encode_int(1)


class RefcountDB(BaseDB):

    def __init__(self, db):
        self.db = db
        self.journal = []
        self.death_row = []
        try:
            self.kv = self.db.kv
        except:
            self.kv = None
        self.ttl = 500
        self.logging = False

    # Increase the reference count associated with a key
    def inc_refcount(self, k, v):
        # raise Exception("WHY AM I CHANGING A REFCOUNT?!:?")
        try:
            node_object = rlp.decode(self.db.get(b'r:'+k))
            refcount = utils.decode_int(node_object[0])
            self.journal.append([node_object[0], k])
            if refcount >= DEATH_ROW_OFFSET: