Exemplo n.º 1
0
    def add_block(self, block):

        blockhash = block.hash()
        if blockhash == GENESIS_H:
            parent_score = 0
        else:
            try:
                parent = rlp.decode(self.blockchain.get(block.prevhash))
            except:
                raise Exception("Parent of block not found")
            parent_score = utils.big_endian_to_int(parent[1])
        total_score = utils.int_to_big_endian(block.difficulty + parent_score)
        self.blockchain.put(
            blockhash, rlp.encode([block.serialize(), total_score]))
        try:
            head = self.blockchain.get('head')
            head_data = rlp.decode(self.blockchain.get(head))
            head_score = utils.big_endian_to_int(head_data[1])
        except:
            head_score = 0
        if total_score > head_score:
            self.head = blockhash
            self.blockchain.put('head', blockhash)
            return True
        return False
Exemplo n.º 2
0
def __decode(s, pos=0):
    assert pos < len(s), "read beyond end of string in __decode"

    fchar = ord(s[pos])
    if fchar < 128:
        return (s[pos], pos + 1)
    elif fchar < 184:
        b = fchar - 128
        return (s[pos + 1:pos + 1 + b], pos + 1 + b)
    elif fchar < 192:
        b = fchar - 183
        b2 = big_endian_to_int(s[pos + 1:pos + 1 + b])
        return (s[pos + 1 + b:pos + 1 + b + b2], pos + 1 + b + b2)
    elif fchar < 248:
        o = []
        pos += 1
        pos_end = pos + fchar - 192

        while pos < pos_end:
            obj, pos = __decode(s, pos)
            o.append(obj)
        assert pos == pos_end, "read beyond list boundary in __decode"
        return (o, pos)
    else:
        b = fchar - 247
        b2 = big_endian_to_int(s[pos + 1:pos + 1 + b])
        o = []
        pos += 1 + b
        pos_end = pos + b2
        while pos < pos_end:
            obj, pos = __decode(s, pos)
            o.append(obj)
        assert pos == pos_end, "read beyond list boundary in __decode"
        return (o, pos)
Exemplo n.º 3
0
def __decode(s, pos=0):
    assert pos < len(s), "read beyond end of string in __decode"

    fchar = ord(s[pos])
    if fchar < 128:
        return (s[pos], pos + 1)
    elif fchar < 184:
        b = fchar - 128
        return (s[pos + 1:pos + 1 + b], pos + 1 + b)
    elif fchar < 192:
        b = fchar - 183
        b2 = big_endian_to_int(s[pos + 1:pos + 1 + b])
        return (s[pos + 1 + b:pos + 1 + b + b2], pos + 1 + b + b2)
    elif fchar < 248:
        o = []
        pos += 1
        pos_end = pos + fchar - 192

        while pos < pos_end:
            obj, pos = __decode(s, pos)
            o.append(obj)
        assert pos == pos_end, "read beyond list boundary in __decode"
        return (o, pos)
    else:
        b = fchar - 247
        b2 = big_endian_to_int(s[pos + 1:pos + 1 + b])
        o = []
        pos += 1 + b
        pos_end = pos + b2
        while pos < pos_end:
            obj, pos = __decode(s, pos)
            o.append(obj)
        assert pos == pos_end, "read beyond list boundary in __decode"
        return (o, pos)
Exemplo n.º 4
0
def decode_single(typ, data):
    base, sub, _ = typ
    if base == 'address':
        return encode_hex(data[12:])
    elif base == 'hash':
        return data[32 - int(sub):]
    elif base == 'string' or base == 'bytes':
        if len(sub):
            return data[:int(sub)]
        else:
            l = big_endian_to_int(data[0:32])
            return data[32:][:l]
    elif base == 'uint':
        return big_endian_to_int(data)
    elif base == 'int':
        o = big_endian_to_int(data)
        return (o - 2**int(sub)) if o >= 2**(int(sub) - 1) else o
    elif base == 'ureal':
        high, low = [int(x) for x in sub.split('x')]
        return big_endian_to_int(data) * 1.0 // 2**low
    elif base == 'real':
        high, low = [int(x) for x in sub.split('x')]
        o = big_endian_to_int(data)
        i = (o - 2**(high + low)) if o >= 2**(high + low - 1) else o
        return (i * 1.0 // 2**low)
    elif base == 'bool':
        return bool(int(encode_hex(data), 16))
Exemplo n.º 5
0
def decode_single(typ, data):
    base, sub, _ = typ
    if base == 'address':
        return encode_hex(data[12:])
    elif base == 'hash':
        return data[32 - int(sub):]
    elif base == 'string' or base == 'bytes':
        if len(sub):
            return data[:int(sub)]
        else:
            l = big_endian_to_int(data[0:32])
            return data[32:][:l]
    elif base == 'uint':
        return big_endian_to_int(data)
    elif base == 'int':
        o = big_endian_to_int(data)
        return (o - 2 ** int(sub)) if o >= 2 ** (int(sub) - 1) else o
    elif base == 'ureal':
        high, low = [int(x) for x in sub.split('x')]
        return big_endian_to_int(data) * 1.0 // 2 ** low
    elif base == 'real':
        high, low = [int(x) for x in sub.split('x')]
        o = big_endian_to_int(data)
        i = (o - 2 ** (high + low)) if o >= 2 ** (high + low - 1) else o
        return (i * 1.0 // 2 ** low)
    elif base == 'bool':
        return bool(int(encode_hex(data), 16))
Exemplo n.º 6
0
 def __init__(self, pubkey):
     assert len(pubkey) == 64 and isinstance(pubkey, str)
     self.pubkey = pubkey
     if k_id_size == 512:
         self.id = big_endian_to_int(pubkey)
     else:
         assert k_id_size == 256
         self.id = big_endian_to_int(sha3(pubkey))
Exemplo n.º 7
0
 def __init__(self, pubkey):
     assert len(pubkey) == 64 and isinstance(pubkey, str)
     self.pubkey = pubkey
     if k_id_size == 512:
         self.id = big_endian_to_int(pubkey)
     else:
         assert k_id_size == 256
         self.id = big_endian_to_int(sha3(pubkey))
Exemplo n.º 8
0
 def get_tx_position(self, tx):
     if isinstance(tx,str):
         tx = tx.decode("HEX")
     elif not isinstance(tx, bytes):
         tx = tx.hash
     if b'txindex:' + tx in self.db:
         data = rlp.decode(self.db.get(b'txindex:' + tx))
         return big_endian_to_int(data[0]), big_endian_to_int(data[1])
     else:
         return None
Exemplo n.º 9
0
    def mine(self, steps=1000):
        """
        It is formally defined as PoW: PoW(H, n) = BE(SHA3(SHA3(RLP(Hn)) o n))
        where:
        RLP(Hn) is the RLP encoding of the block header H, not including the
            final nonce component;
        SHA3 is the SHA3 hash function accepting an arbitrary length series of
            bytes and evaluating to a series of 32 bytes (i.e. 256-bit);
        n is the nonce, a series of 32 bytes;
        o is the series concatenation operator;
        BE(X) evaluates to the value equal to X when interpreted as a
            big-endian-encoded integer.
        """

        nonce_bin_prefix = '\x00' * (32 - len(struct.pack('>q', 0)))
        target = 2**256 / self.block.difficulty
        rlp_Hn = self.block.serialize_header_without_nonce()

        for nonce in range(self.nonce, self.nonce + steps):
            nonce_bin = nonce_bin_prefix + struct.pack('>q', nonce)
            # BE(SHA3(SHA3(RLP(Hn)) o n))
            h = utils.sha3(utils.sha3(rlp_Hn) + nonce_bin)
            l256 = utils.big_endian_to_int(h)
            if l256 < target:
                self.block.nonce = nonce_bin
                assert self.block.check_proof_of_work(self.block.nonce) is True
                assert self.block.get_parent()
                logger.debug('Nonce found %d %r', nonce, self.block)
                return self.block

        self.nonce = nonce
        return False
Exemplo n.º 10
0
 def account_to_dict(self, address, with_storage_root=False):
     if with_storage_root:
         assert len(self.journal) == 0
     med_dict = {}
     for i, val in enumerate(self.get_acct(address)):
         name, typ, default = acct_structure[i]
         key = acct_structure[i][0]
         if name == 'storage':
             strie = trie.Trie(utils.get_db_path(), val)
             if with_storage_root:
                 med_dict['storage_root'] = strie.get_root_hash().encode('hex')
         else:
             med_dict[key] = self.caches[key].get(address, utils.printers[typ](val))
     med_dict['storage'] = {}
     d = strie.to_dict()
     for k in d.keys() + self.caches['all'].keys():
         v = d.get(k, None)
         subcache = self.caches.get('storage:'+address, {})
         v2 = subcache.get(utils.big_endian_to_int(k), None)
         hexkey = '0x'+k.encode('hex')
         if v2 is not None:
             if v2 != 0:
                 med_dict['storage'][hexkey] = '0x'+utils.int_to_big_endian(v2).encode('hex')
         elif v is not None:
             med_dict['storage'][hexkey] = '0x'+rlp.decode(v).encode('hex')
     return med_dict
Exemplo n.º 11
0
 def account_to_dict(self, address, with_storage_root=False,
                     with_storage=True, for_vmtest=False):
     if with_storage_root:
         assert len(self.journal) == 0
     med_dict = {}
     for i, val in enumerate(self.get_acct(address)):
         name, typ, default = acct_structure[i]
         key = acct_structure[i][0]
         if name == 'storage':
             strie = trie.Trie(self.db, val)
             if with_storage_root:
                 med_dict['storage_root'] = strie.get_root_hash().encode('hex')
         else:
             med_dict[key] = utils.printers[typ](self.caches[key].get(address, val))
     if with_storage:
         med_dict['storage'] = {}
         d = strie.to_dict()
         subcache = self.caches.get('storage:' + address, {})
         subkeys = [utils.zpad(utils.coerce_to_bytes(kk), 32) for kk in subcache.keys()]
         for k in d.keys() + subkeys:
             v = d.get(k, None)
             v2 = subcache.get(utils.big_endian_to_int(k), None)
             hexkey = '0x' + utils.zunpad(k).encode('hex')
             if v2 is not None:
                 if v2 != 0:
                     med_dict['storage'][hexkey] = \
                         '0x' + utils.int_to_big_endian(v2).encode('hex')
             elif v is not None:
                 med_dict['storage'][hexkey] = '0x' + rlp.decode(v).encode('hex')
     return med_dict
Exemplo n.º 12
0
def check_header_pow(header):
    rlp_Hn = rlp.encode(header[:-1])
    nonce = header[-1]
    assert len(nonce) == 32
    diff = utils.decoders['int'](header[block_structure_rev['difficulty'][0]])
    h = utils.sha3(utils.sha3(rlp_Hn) + nonce)
    return utils.big_endian_to_int(h) < 2 ** 256 / diff
Exemplo n.º 13
0
 def account_to_dict(self, address, with_storage_root=False,
                     with_storage=True, for_vmtest=False):
     if with_storage_root:
         assert len(self.journal) == 0
     med_dict = {}
     for i, val in enumerate(self.get_acct(address)):
         name, typ, default = acct_structure[i]
         key = acct_structure[i][0]
         if name == 'storage':
             strie = trie.Trie(self.db, val)
             if with_storage_root:
                 med_dict['storage_root'] = strie.get_root_hash().encode('hex')
         else:
             med_dict[key] = utils.printers[typ](self.caches[key].get(address, val))
     if with_storage:
         med_dict['storage'] = {}
         d = strie.to_dict()
         subcache = self.caches.get('storage:' + address, {})
         subkeys = [utils.zpad(utils.coerce_to_bytes(kk), 32) for kk in subcache.keys()]
         for k in d.keys() + subkeys:
             v = d.get(k, None)
             v2 = subcache.get(utils.big_endian_to_int(k), None)
             hexkey = '0x' + utils.zunpad(k).encode('hex')
             if v2 is not None:
                 if v2 != 0:
                     med_dict['storage'][hexkey] = \
                         '0x' + utils.int_to_big_endian(v2).encode('hex')
             elif v is not None:
                 med_dict['storage'][hexkey] = '0x' + rlp.decode(v).encode('hex')
     return med_dict
Exemplo n.º 14
0
 def check_proof_of_work(self, nonce):
     assert len(nonce) == 32
     rlp_Hn = self.serialize_header_without_nonce()
     # BE(SHA3(SHA3(RLP(Hn)) o n))
     h = utils.sha3(utils.sha3(rlp_Hn) + nonce)
     l256 = utils.big_endian_to_int(h)
     return l256 < 2 ** 256 / self.difficulty
Exemplo n.º 15
0
def decode_datalist(arr):
    if isinstance(arr, list):
        arr = ''.join(map(chr, arr))
    o = []
    for i in range(0, len(arr), 32):
        o.append(utils.big_endian_to_int(arr[i:i + 32]))
    return o
Exemplo n.º 16
0
    def mine(self, steps=1000):
        """
        It is formally defined as PoW: PoW(H, n) = BE(SHA3(SHA3(RLP(Hn)) o n))
        where:
        RLP(Hn) is the RLP encoding of the block header H, not including the
            final nonce component;
        SHA3 is the SHA3 hash function accepting an arbitrary length series of
            bytes and evaluating to a series of 32 bytes (i.e. 256-bit);
        n is the nonce, a series of 32 bytes;
        o is the series concatenation operator;
        BE(X) evaluates to the value equal to X when interpreted as a
            big-endian-encoded integer.
        """

        nonce_bin_prefix = '\x00' * (32 - len(struct.pack('>q', 0)))
        target = 2 ** 256 / self.block.difficulty
        rlp_Hn = self.block.serialize_header_without_nonce()

        for nonce in range(self.nonce, self.nonce + steps):
            nonce_bin = nonce_bin_prefix + struct.pack('>q', nonce)
            # BE(SHA3(SHA3(RLP(Hn)) o n))
            h = utils.sha3(utils.sha3(rlp_Hn) + nonce_bin)
            l256 = utils.big_endian_to_int(h)
            if l256 < target:
                self.block.nonce = nonce_bin
                assert self.block.check_proof_of_work(self.block.nonce) is True
                assert self.block.get_parent()
                logger.debug(
                    'Nonce found %d %r', nonce, self.block)
                return self.block

        self.nonce = nonce
        return False
Exemplo n.º 17
0
def check_header_pow(header):
    assert len(header[-1]) == 32
    rlp_Hn = rlp.encode(header[:-1])
    nonce = header[-1]
    diff = utils.decoders['int'](header[block_structure_rev['difficulty'][0]])
    h = utils.sha3(utils.sha3(rlp_Hn) + nonce)
    return utils.big_endian_to_int(h) < 2 ** 256 / diff
Exemplo n.º 18
0
def decode_datalist(arr):
    if isinstance(arr, list):
        arr = ''.join(map(chr, arr))
    o = []
    for i in range(0, len(arr), 32):
        o.append(utils.big_endian_to_int(arr[i:i + 32]))
    return o
Exemplo n.º 19
0
 def check_proof_of_work(self, nonce):
     assert len(nonce) == 32
     rlp_Hn = self.serialize_header_without_nonce()
     # BE(SHA3(SHA3(RLP(Hn)) o n))
     h = utils.sha3(utils.sha3(rlp_Hn) + nonce)
     l256 = utils.big_endian_to_int(h)
     return l256 < 2**256 / self.difficulty
Exemplo n.º 20
0
 def account_to_dict(self, address, with_storage_root=False):
     if with_storage_root:
         assert len(self.journal) == 0
     med_dict = {}
     for i, val in enumerate(self.get_acct(address)):
         name, typ, default = acct_structure[i]
         key = acct_structure[i][0]
         if name == 'storage':
             strie = trie.Trie(utils.get_db_path(), val)
             if with_storage_root:
                 med_dict['storage_root'] = strie.get_root_hash().encode(
                     'hex')
         else:
             med_dict[key] = self.caches[key].get(address,
                                                  utils.printers[typ](val))
     med_dict['storage'] = {}
     d = strie.to_dict()
     for k in d.keys() + self.caches['all'].keys():
         v = d.get(k, None)
         subcache = self.caches.get('storage:' + address, {})
         v2 = subcache.get(utils.big_endian_to_int(k), None)
         hexkey = '0x' + k.encode('hex')
         if v2 is not None:
             if v2 != 0:
                 med_dict['storage'][
                     hexkey] = '0x' + utils.int_to_big_endian(v2).encode(
                         'hex')
         elif v is not None:
             med_dict['storage'][hexkey] = '0x' + rlp.decode(v).encode(
                 'hex')
     return med_dict
Exemplo n.º 21
0
def dec(typ, arg):
    base, sub, arrlist = typ
    sz = get_size(typ)
    # Dynamic-sized strings are encoded as <len(str)> + <str>
    if base in ('string', 'bytes') and not sub:
        L = big_endian_to_int(arg[:32])
        assert len(
            arg[32:]) == ceil32(L), "Wrong data size for string/bytes object"
        return arg[32:][:L]
    # Dynamic-sized arrays
    elif sz is None:
        L = big_endian_to_int(arg[:32])
        subtyp = base, sub, arrlist[:-1]
        subsize = get_size(subtyp)
        # If children are dynamic, use the head/tail mechanism. Fortunately,
        # here the code is simpler since we do not have to worry about
        # mixed dynamic and static children, as we do in the top-level multi-arg
        # case
        if subsize is None:
            assert len(arg) >= 32 + 32 * L, "Not enough data for head"
            start_positions = [
                big_endian_to_int(arg[32 + 32 * i:64 + 32 * i])
                for i in range(L)
            ] + [len(arg)]
            outs = [
                arg[start_positions[i]:start_positions[i + 1]]
                for i in range(L)
            ]
            return [dec(subtyp, out) for out in outs]
        # If children are static, then grab the data slice for each one and
        # sequentially decode them manually
        else:
            return [
                dec(subtyp, arg[32 + subsize * i:32 + subsize * (i + 1)])
                for i in range(L)
            ]
    # Static-sized arrays: decode piece-by-piece
    elif len(arrlist):
        L = arrlist[-1][0]
        subtyp = base, sub, arrlist[:-1]
        subsize = get_size(subtyp)
        return [
            dec(subtyp, arg[subsize * i:subsize * (i + 1)]) for i in range(L)
        ]
    else:
        return decode_single(typ, arg)
Exemplo n.º 22
0
 def get_storage_data(self, address, index):
     CACHE_KEY = 'storage:'+address
     if CACHE_KEY in self.caches:
         if index in self.caches[CACHE_KEY]:
             return self.caches[CACHE_KEY][index]
     key = utils.zpad(utils.coerce_to_bytes(index), 32)
     val = rlp.decode(self.get_storage(address).get(key))
     return utils.big_endian_to_int(val) if val else 0
Exemplo n.º 23
0
 def get_storage_data(self, address, index):
     if address in self.caches['storage']:
         if index in self.caches['storage'][address]:
             return self.caches['storage'][address][index]
     t = self.get_storage(address)
     key = utils.zpad(utils.coerce_to_bytes(index), 32)
     val = rlp.decode(t.get(key))
     return utils.big_endian_to_int(val) if val else 0
Exemplo n.º 24
0
 def get_storage_data(self, address, index):
     if address in self.caches['storage']:
         if index in self.caches['storage'][address]:
             return self.caches['storage'][address][index]
     t = self.get_storage(address)
     key = utils.zpad(utils.coerce_to_bytes(index), 32)
     val = rlp.decode(t.get(key))
     return utils.big_endian_to_int(val) if val else 0
Exemplo n.º 25
0
 def get_storage_data(self, address, index):
     CACHE_KEY = 'storage:'+address
     if CACHE_KEY in self.caches:
         if index in self.caches[CACHE_KEY]:
             return self.caches[CACHE_KEY][index]
     key = utils.zpad(utils.coerce_to_bytes(index), 32)
     val = rlp.decode(self.get_storage(address).get(key))
     return utils.big_endian_to_int(val) if val else 0
Exemplo n.º 26
0
def next(data, pos):
    fchar = ord(data[pos])
    if fchar < 128:
        return pos + 1
    elif (fchar % 64) < 56:
        return pos + 1 + (fchar % 64)
    else:
        b = (fchar % 64) - 55
        b2 = big_endian_to_int(data[pos + 1:pos + 1 + b])
        return pos + 1 + b + b2
Exemplo n.º 27
0
 def get_storage_data(self, address, index):
     if 'storage:'+address in self.caches:
         if index in self.caches['storage:'+address]:
             return self.caches['storage:'+address][index]
     t = self.get_storage(address)
     t.proof_mode = self.proof_mode
     t.proof_nodes = self.proof_nodes
     key = utils.zpad(utils.coerce_to_bytes(index), 32)
     val = rlp.decode(t.get(key))
     if self.proof_mode == RECORDING:
         self.proof_nodes.extend(t.proof_nodes)
     return utils.big_endian_to_int(val) if val else 0
Exemplo n.º 28
0
 def get_storage_data(self, address, index):
     if 'storage:' + address in self.caches:
         if index in self.caches['storage:' + address]:
             return self.caches['storage:' + address][index]
     t = self.get_storage(address)
     t.proof_mode = self.proof_mode
     t.proof_nodes = self.proof_nodes
     key = utils.zpad(utils.coerce_to_bytes(index), 32)
     val = rlp.decode(t.get(key))
     if self.proof_mode == RECORDING:
         self.proof_nodes.extend(t.proof_nodes)
     return utils.big_endian_to_int(val) if val else 0
Exemplo n.º 29
0
def dec(typ, arg):
    base, sub, arrlist = typ
    sz = get_size(typ)
    # Dynamic-sized strings are encoded as <len(str)> + <str>
    if base in ('string', 'bytes') and not sub:
        L = big_endian_to_int(arg[:32])
        assert len(arg[32:]) == ceil32(L), "Wrong data size for string/bytes object"
        return arg[32:][:L]
    # Dynamic-sized arrays
    elif sz is None:
        L = big_endian_to_int(arg[:32])
        subtyp = base, sub, arrlist[:-1]
        subsize = get_size(subtyp)
        # If children are dynamic, use the head/tail mechanism. Fortunately,
        # here the code is simpler since we do not have to worry about
        # mixed dynamic and static children, as we do in the top-level multi-arg
        # case
        if subsize is None:
            assert len(arg) >= 32 + 32 * L, "Not enough data for head"
            start_positions = [big_endian_to_int(arg[32 + 32 * i: 64 + 32 * i])
                               for i in range(L)] + [len(arg)]
            outs = [arg[start_positions[i]: start_positions[i + 1]]
                    for i in range(L)]
            return [dec(subtyp, out) for out in outs]
        # If children are static, then grab the data slice for each one and
        # sequentially decode them manually
        else:
            return [dec(subtyp, arg[32 + subsize * i: 32 + subsize * (i + 1)])
                    for i in range(L)]
    # Static-sized arrays: decode piece-by-piece
    elif len(arrlist):
        L = arrlist[-1][0]
        subtyp = base, sub, arrlist[:-1]
        subsize = get_size(subtyp)
        return [dec(subtyp, arg[subsize * i:subsize * (i + 1)])
                for i in range(L)]
    else:
        return decode_single(typ, arg)
Exemplo n.º 30
0
def event_id(name, encode_types):
    """ Return the event id.

    Defined as:

        `keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")`

    Where `canonical_type_of` is a function that simply returns the canonical
    type of a given argument, e.g. for uint indexed foo, it would return
    uint256). Note the lack of spaces.
    """

    event_types = [_canonical_name(type_) for type_ in encode_types]

    event_signature = '{event_name}({canonical_types})'.format(
        event_name=name,
        canonical_types=','.join(event_types),
    )

    return big_endian_to_int(utils.sha3(event_signature))
Exemplo n.º 31
0
def method_id(name, encode_types):
    """ Return the unique method id.

    The signature is defined as the canonical expression of the basic
    prototype, i.e. the function name with the parenthesised list of parameter
    types. Parameter types are split by a single comma - no spaces are used.

    The method id is defined as the first four bytes (left, high-order in
    big-endian) of the Keccak (SHA-3) hash of the signature of the function.
    """
    function_types = [_canonical_name(type_) for type_ in encode_types]

    function_signature = '{function_name}({canonical_types})'.format(
        function_name=name,
        canonical_types=','.join(function_types),
    )

    function_keccak = utils.sha3(function_signature)
    first_bytes = function_keccak[:4]

    return big_endian_to_int(first_bytes)
Exemplo n.º 32
0
def decode_abi(types, data):
    # Process types
    proctypes = [process_type(typ) for typ in types]
    # Get sizes of everything
    sizes = [get_size(typ) for typ in proctypes]
    # Initialize array of outputs
    outs = [None] * len(types)
    # Initialize array of start positions
    start_positions = [None] * len(types) + [len(data)]
    # If a type is static, grab the data directly, otherwise record
    # its start position
    pos = 0
    for i, typ in enumerate(types):
        if sizes[i] is None:
            start_positions[i] = big_endian_to_int(data[pos:pos + 32])
            j = i - 1
            while j >= 0 and start_positions[j] is None:
                start_positions[j] = start_positions[i]
                j -= 1
            pos += 32
        else:
            outs[i] = data[pos:pos + sizes[i]]
            pos += sizes[i]
    # We add a start position equal to the length of the entire data
    # for convenience.
    j = len(types) - 1
    while j >= 0 and start_positions[j] is None:
        start_positions[j] = start_positions[len(types)]
        j -= 1
    assert pos <= len(data), "Not enough data for head"
    # Grab the data for tail arguments using the start positions
    # calculated above
    for i, typ in enumerate(types):
        if sizes[i] is None:
            offset = start_positions[i]
            next_offset = start_positions[i + 1]
            outs[i] = data[offset:next_offset]
    # Recursively decode them all
    return [dec(proctypes[i], outs[i]) for i in range(len(outs))]
Exemplo n.º 33
0
def decode_abi(types, data):
    # Process types
    proctypes = [process_type(typ) for typ in types]
    # Get sizes of everything
    sizes = [get_size(typ) for typ in proctypes]
    # Initialize array of outputs
    outs = [None] * len(types)
    # Initialize array of start positions
    start_positions = [None] * len(types) + [len(data)]
    # If a type is static, grab the data directly, otherwise record
    # its start position
    pos = 0
    for i, typ in enumerate(types):
        if sizes[i] is None:
            start_positions[i] = big_endian_to_int(data[pos:pos + 32])
            j = i - 1
            while j >= 0 and start_positions[j] is None:
                start_positions[j] = start_positions[i]
                j -= 1
            pos += 32
        else:
            outs[i] = data[pos:pos + sizes[i]]
            pos += sizes[i]
    # We add a start position equal to the length of the entire data
    # for convenience.
    j = len(types) - 1
    while j >= 0 and start_positions[j] is None:
        start_positions[j] = start_positions[len(types)]
        j -= 1
    assert pos <= len(data), "Not enough data for head"
    # Grab the data for tail arguments using the start positions
    # calculated above
    for i, typ in enumerate(types):
        if sizes[i] is None:
            offset = start_positions[i]
            next_offset = start_positions[i + 1]
            outs[i] = data[offset:next_offset]
    # Recursively decode them all
    return [dec(proctypes[i], outs[i]) for i in range(len(outs))]
Exemplo n.º 34
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)
Exemplo n.º 35
0
 def account_to_dict(self, address, with_storage_root=False):
     if with_storage_root:
         assert len(self.journal) == 0
     med_dict = {}
     for i, val in enumerate(self.get_acct(address)):
         name, typ, default = acct_structure[i]
         key = acct_structure[i][0]
         if name == "storage":
             strie = trie.Trie(utils.get_db_path(), val)
             if with_storage_root:
                 med_dict["storage_root"] = strie.get_root_hash().encode("hex")
         else:
             med_dict[key] = self.caches[key].get(address, utils.printers[typ](val))
     med_dict["storage"] = {}
     for k, v in strie.to_dict().iteritems():
         subcache = self.caches.get("storage:" + address, {})
         v2 = subcache.get(utils.big_endian_to_int(k), None)
         hexkey = "0x" + k.encode("hex")
         if v2 is not None:
             med_dict["storage"][hexkey] = "0x" + utils.int_to_big_endian(v2).encode("hex")
         else:
             med_dict["storage"][hexkey] = "0x" + v.encode("hex")
     return med_dict
Exemplo n.º 36
0
def event_id(name, encode_types):
    """ Return the event id.

    Defined as:

        `keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")`

    Where `canonical_type_of` is a function that simply returns the canonical
    type of a given argument, e.g. for uint indexed foo, it would return
    uint256). Note the lack of spaces.
    """

    event_types = [
        _canonical_name(type_)
        for type_ in encode_types
    ]

    event_signature = '{event_name}({canonical_types})'.format(
        event_name=name,
        canonical_types=','.join(event_types),
    )

    return big_endian_to_int(utils.sha3(event_signature))
Exemplo n.º 37
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)
Exemplo n.º 38
0
def method_id(name, encode_types):
    """ Return the unique method id.

    The signature is defined as the canonical expression of the basic
    prototype, i.e. the function name with the parenthesised list of parameter
    types. Parameter types are split by a single comma - no spaces are used.

    The method id is defined as the first four bytes (left, high-order in
    big-endian) of the Keccak (SHA-3) hash of the signature of the function.
    """
    function_types = [
        _canonical_name(type_)
        for type_ in encode_types
    ]

    function_signature = '{function_name}({canonical_types})'.format(
        function_name=name,
        canonical_types=','.join(function_types),
    )

    function_keccak = utils.sha3(function_signature)
    first_bytes = function_keccak[:4]

    return big_endian_to_int(first_bytes)
Exemplo n.º 39
0
def apply_op(block, tx, msg, code, compustate):
    op, in_args, out_args = get_op_data(code, compustate.pc)
    # empty stack error
    if in_args > len(compustate.stack):
        return []
    # out of gas error
    fee = calcfee(block, tx, msg, compustate, op)
    if fee > compustate.gas:
        logger.debug("Out of gas %s need %s", compustate.gas, fee)
        logger.debug('%s %s', op, list(reversed(compustate.stack)))
        return OUT_OF_GAS
    stackargs = []
    for i in range(in_args):
        stackargs.append(compustate.stack.pop())
    if op[:4] == 'PUSH':
        ind = compustate.pc + 1
        v = utils.big_endian_to_int(code[ind: ind + int(op[4:])])
        logger.debug('%s %x %s', compustate.pc, op, v)
        # print '%s %s %s' % (compustate.pc, op, v)
    else:
        logger.debug('%s %s %s', compustate.pc, op, stackargs)
        # print '%s %s %s' % (compustate.pc, op, stackargs)
    # Apply operation
    oldgas = compustate.gas
    oldpc = compustate.pc
    compustate.gas -= fee
    compustate.pc += 1
    stk = compustate.stack
    mem = compustate.memory
    if op == 'STOP':
        return []
    elif op == 'ADD':
        stk.append((stackargs[0] + stackargs[1]) % 2 ** 256)
    elif op == 'SUB':
        stk.append((stackargs[0] - stackargs[1]) % 2 ** 256)
    elif op == 'MUL':
        stk.append((stackargs[0] * stackargs[1]) % 2 ** 256)
    elif op == 'DIV':
        if stackargs[1] == 0:
            return []
        stk.append(stackargs[0] / stackargs[1])
    elif op == 'MOD':
        if stackargs[1] == 0:
            return []
        stk.append(stackargs[0] % stackargs[1])
    elif op == 'SDIV':
        if stackargs[1] == 0:
            return []
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append((stackargs[0] / stackargs[1]) % 2 ** 256)
    elif op == 'SMOD':
        if stackargs[1] == 0:
            return []
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append((stackargs[0] % stackargs[1]) % 2 ** 256)
    elif op == 'EXP':
        stk.append(pow(stackargs[0], stackargs[1], 2 ** 256))
    elif op == 'NEG':
        stk.append(2 ** 256 - stackargs[0])
    elif op == 'LT':
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'GT':
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'SLT':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'SGT':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'EQ':
        stk.append(1 if stackargs[0] == stackargs[1] else 0)
    elif op == 'NOT':
        stk.append(0 if stackargs[0] else 1)
    elif op == 'AND':
        stk.append(stackargs[0] & stackargs[1])
    elif op == 'OR':
        stk.append(stackargs[0] | stackargs[1])
    elif op == 'XOR':
        stk.append(stackargs[0] ^ stackargs[1])
    elif op == 'BYTE':
        if stackargs[0] >= 32:
            stk.append(0)
        else:
            stk.append((stackargs[1] / 256 ** stackargs[0]) % 256)
    elif op == 'SHA3':
        if len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + stackargs[1]]))
        stk.append(utils.big_endian_to_int(utils.sha3(data)))
    elif op == 'ADDRESS':
        stk.append(msg.to)
    elif op == 'BALANCE':
        stk.append(block.get_balance(msg.to))
    elif op == 'ORIGIN':
        stk.append(tx.sender)
    elif op == 'CALLER':
        stk.append(utils.coerce_to_int(msg.sender))
    elif op == 'CALLVALUE':
        stk.append(msg.value)
    elif op == 'CALLDATALOAD':
        if stackargs[0] >= len(msg.data):
            stk.append(0)
        else:
            dat = msg.data[stackargs[0]:stackargs[0] + 32]
            stk.append(utils.big_endian_to_int(dat + '\x00' * (32 - len(dat))))
    elif op == 'CALLDATASIZE':
        stk.append(len(msg.data))
    elif op == 'CALLDATACOPY':
        if len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[0] + i < len(msg.data):
                mem[stackargs[1] + i] = ord(msg.data[stackargs[0] + i])
            else:
                mem[stackargs[1] + i] = 0
    elif op == 'GASPRICE':
        stk.append(tx.gasprice)
    elif op == 'CODECOPY':
        if len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[0] + i < len(code):
                mem[stackargs[1] + i] = ord(code[stackargs[0] + i])
            else:
                mem[stackargs[1] + i] = 0
    elif op == 'PREVHASH':
        stk.append(utils.big_endian_to_int(block.prevhash))
    elif op == 'COINBASE':
        stk.append(utils.big_endian_to_int(block.coinbase.decode('hex')))
    elif op == 'TIMESTAMP':
        stk.append(block.timestamp)
    elif op == 'NUMBER':
        stk.append(block.number)
    elif op == 'DIFFICULTY':
        stk.append(block.difficulty)
    elif op == 'GASLIMIT':
        stk.append(block.gaslimit)
    elif op == 'POP':
        pass
    elif op == 'DUP':
        stk.append(stackargs[0])
        stk.append(stackargs[0])
    elif op == 'SWAP':
        stk.append(stackargs[0])
        stk.append(stackargs[1])
    elif op == 'MLOAD':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + 32]))
        stk.append(utils.big_endian_to_int(data))
    elif op == 'MSTORE':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        v = stackargs[1]
        for i in range(31, -1, -1):
            mem[stackargs[0] + i] = v % 256
            v /= 256
    elif op == 'MSTORE8':
        if len(mem) < ceil32(stackargs[0] + 1):
            mem.extend([0] * (ceil32(stackargs[0] + 1) - len(mem)))
        mem[stackargs[0]] = stackargs[1] % 256
    elif op == 'SLOAD':
        stk.append(block.get_storage_data(msg.to, stackargs[0]))
    elif op == 'SSTORE':
        block.set_storage_data(msg.to, stackargs[0], stackargs[1])
    elif op == 'JUMP':
        compustate.pc = stackargs[0]
    elif op == 'JUMPI':
        if stackargs[1]:
            compustate.pc = stackargs[0]
    elif op == 'PC':
        stk.append(compustate.pc)
    elif op == 'MSIZE':
        stk.append(len(mem))
    elif op == 'GAS':
        stk.append(oldgas)
    elif op[:4] == 'PUSH':
        pushnum = int(op[4:])
        compustate.pc = oldpc + 1 + pushnum
        dat = code[oldpc + 1: oldpc + 1 + pushnum]
        stk.append(utils.big_endian_to_int(dat))
    elif op == 'CREATE':
        if len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        value = stackargs[0]
        data = ''.join(map(chr, mem[stackargs[1]:stackargs[1] + stackargs[2]]))
        logger.debug("Sub-contract: %s %s %s ", msg.to, value, data)
        addr, gas, code = create_contract(
            block, tx, Message(msg.to, '', value, compustate.gas, data))
        logger.debug("Output of contract creation: %s  %s ", addr, code)
        if addr:
            stk.append(utils.coerce_to_int(addr))
            compustate.gas = gas
        else:
            stk.append(0)
            compustate.gas = 0
    elif op == 'CALL':
        if len(mem) < ceil32(stackargs[3] + stackargs[4]):
            mem.extend([0] * (ceil32(stackargs[3] + stackargs[4]) - len(mem)))
        if len(mem) < ceil32(stackargs[5] + stackargs[6]):
            mem.extend([0] * (ceil32(stackargs[5] + stackargs[6]) - len(mem)))
        gas = stackargs[0]
        to = utils.encode_int(stackargs[1])
        to = (('\x00' * (32 - len(to))) + to)[12:]
        value = stackargs[2]
        data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]]))
        logger.debug(
            "Sub-call: %s %s %s %s %s ", utils.coerce_addr_to_hex(msg.to),
            utils.coerce_addr_to_hex(to), value, gas, data)
        result, gas, data = apply_msg(
            block, tx, Message(msg.to, to, value, gas, data))
        logger.debug(
            "Output of sub-call: %s %s length %s expected %s", result, data, len(data),
            stackargs[6])
        for i in range(stackargs[6]):
            mem[stackargs[5] + i] = 0
        if result == 0:
            stk.append(0)
        else:
            stk.append(1)
            compustate.gas += gas
            for i in range(len(data)):
                mem[stackargs[5] + i] = data[i]
    elif op == 'RETURN':
        if len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        return mem[stackargs[0]:stackargs[0] + stackargs[1]]
    elif op == 'SUICIDE':
        to = utils.encode_int(stackargs[0])
        to = (('\x00' * (32 - len(to))) + to)[12:]
        block.transfer_value(msg.to, to, block.get_balance(msg.to))
        compustate.suicides.append(msg.to)
        return []
Exemplo n.º 40
0
def apply_op(block, tx, msg, processed_code, compustate):
    if compustate.pc >= len(processed_code):
        return []
    op, in_args, out_args, mem_grabs, fee, opcode = processed_code[compustate.pc]
    # empty stack error
    if in_args > len(compustate.stack):
        pblogger.log("INSUFFICIENT STACK ERROR", op=op, needed=in_args, available=len(compustate.stack))
        return []

    # out of gas error
    if fee > compustate.gas:
        return out_of_gas_exception("base_gas", fee, compustate, op)

    if pblogger.log_apply_op:
        if pblogger.log_stack:
            pblogger.log("STK", stk=list(reversed(compustate.stack)))

        if pblogger.log_memory:
            for i in range(0, len(compustate.memory), 16):
                memblk = compustate.memory[i : i + 16]
                memline = " ".join([chr(x).encode("hex") for x in memblk])
                pblogger.log("MEM", mem=memline)

        if pblogger.log_storage:
            pblogger.log("STORAGE", storage=block.account_to_dict(msg.to)["storage"])

        if pblogger.log_op:
            log_args = dict(
                pc=compustate.pc, op=op, stackargs=compustate.stack[-1 : -in_args - 1 : -1], gas=compustate.gas
            )
            if op[:4] == "PUSH":
                ind = compustate.pc + 1
                log_args["value"] = utils.bytearray_to_int([x[-1] for x in processed_code[ind : ind + int(op[4:])]])
            elif op == "CALLDATACOPY":
                log_args["data"] = msg.data.encode("hex")
            pblogger.log("OP", **log_args)

    # Apply operation
    compustate.gas -= fee
    compustate.pc += 1
    stk = compustate.stack
    mem = compustate.memory
    if op == "STOP" or op == "INVALID":
        return []
    elif op == "ADD":
        stk.append((stk.pop() + stk.pop()) % TT256)
    elif op == "SUB":
        stk.append((stk.pop() - stk.pop()) % TT256)
    elif op == "MUL":
        stk.append((stk.pop() * stk.pop()) % TT256)
    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 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(0 if s1 == 0 else (s0 / s1) % TT256)
    elif op == "SMOD":
        s0, s1 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(0 if s1 == 0 else (s0 % s1) % TT256)
    elif op == "EXP":
        stk.append(pow(stk.pop(), stk.pop(), TT256))
    elif op == "NEG":
        stk.append(-stk.pop() % TT256)
    elif 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 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(1 if s0 < s1 else 0)
    elif op == "SGT":
        s0, s1 = to_signed(stk.pop()), 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 == "NOT":
        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 == "BYTE":
        s0, s1 = stk.pop(), stk.pop()
        if s0 >= 32:
            stk.append(0)
        else:
            stk.append((s1 / 256 ** (31 - s0)) % 256)
    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 == "SHA3":
        s0, s1 = stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s1):
            return OUT_OF_GAS
        data = "".join(map(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":
        stk.append(block.get_balance(utils.coerce_addr_to_hex(stk.pop())))
    elif op == "ORIGIN":
        stk.append(utils.coerce_to_int(tx.sender))
    elif op == "CALLER":
        stk.append(utils.coerce_to_int(msg.sender))
    elif op == "CALLVALUE":
        stk.append(msg.value)
    elif op == "CALLDATALOAD":
        s0 = stk.pop()
        if s0 >= len(msg.data):
            stk.append(0)
        else:
            dat = msg.data[s0 : s0 + 32]
            stk.append(utils.big_endian_to_int(dat + "\x00" * (32 - len(dat))))
    elif op == "CALLDATASIZE":
        stk.append(len(msg.data))
    elif op == "CALLDATACOPY":
        s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s2):
            return OUT_OF_GAS
        for i in range(s2):
            if s1 + i < len(msg.data):
                mem[s0 + i] = ord(msg.data[s1 + i])
            else:
                mem[s0 + i] = 0
    elif op == "GASPRICE":
        stk.append(tx.gasprice)
    elif op == "CODECOPY":
        s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s2):
            return OUT_OF_GAS
        for i in range(s2):
            if s1 + i < len(processed_code):
                mem[s0 + i] = processed_code[s1 + i][-1]
            else:
                mem[s0 + i] = 0
    elif op == "EXTCODESIZE":
        stk.append(len(block.get_code(stk.pop()) or ""))
    elif op == "EXTCODECOPY":
        addr, s1, s2, s3 = stk.pop(), stk.pop(), stk.pop(), stk.pop()
        extcode = block.get_code(addr) or ""
        if not mem_extend(mem, compustate, op, s1 + s3):
            return OUT_OF_GAS
        for i in range(s3):
            if s2 + i < len(extcode):
                mem[s1 + i] = ord(extcode[s2 + i])
            else:
                mem[s1 + i] = 0
    elif op == "PREVHASH":
        stk.append(utils.big_endian_to_int(block.prevhash))
    elif op == "COINBASE":
        stk.append(utils.big_endian_to_int(block.coinbase.decode("hex")))
    elif op == "TIMESTAMP":
        stk.append(block.timestamp)
    elif op == "NUMBER":
        stk.append(block.number)
    elif op == "DIFFICULTY":
        stk.append(block.difficulty)
    elif op == "GASLIMIT":
        stk.append(block.gas_limit)
    elif op == "POP":
        stk.pop()
    elif op == "MLOAD":
        s0 = stk.pop()
        if not mem_extend(mem, compustate, op, s0 + 32):
            return OUT_OF_GAS
        data = "".join(map(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 OUT_OF_GAS
        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 OUT_OF_GAS
        mem[s0] = s1 % 256
    elif op == "SLOAD":
        stk.append(block.get_storage_data(msg.to, stk.pop()))
    elif op == "SSTORE":
        s0, s1 = stk.pop(), stk.pop()
        pre_occupied = GSTORAGE if block.get_storage_data(msg.to, s0) else 0
        post_occupied = GSTORAGE if s1 else 0
        gascost = GSTORAGE + post_occupied - pre_occupied
        if compustate.gas < gascost:
            out_of_gas_exception("sstore trie expansion", gascost, compustate, op)
        compustate.gas -= gascost
        block.set_storage_data(msg.to, s0, s1)
    elif op == "JUMP":
        compustate.pc = stk.pop()
    elif op == "JUMPI":
        s0, s1 = stk.pop(), stk.pop()
        if s1:
            compustate.pc = s0
    elif op == "PC":
        stk.append(compustate.pc)
    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:])
        dat = [x[-1] for x in processed_code[compustate.pc : compustate.pc + pushnum]]
        compustate.pc += pushnum
        stk.append(utils.bytearray_to_int(dat))
    elif op[:3] == "DUP":
        depth = int(op[3:])
        # DUP POP POP Debug hint
        is_debug = 1
        for i in range(depth):
            if compustate.pc + i < len(processed_code) and processed_code[compustate.pc + i][0] != "POP":
                is_debug = 0
                break
        if is_debug:
            stackargs = [stk.pop() for i in range(depth)]
            print (" ".join(map(repr, stackargs)))
            stk.extend(reversed(stackargs))
            stk.append(stackargs[-1])
        else:
            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 == "CREATE":
        value, mstart, msz = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, mstart + msz):
            return OUT_OF_GAS
        data = "".join(map(chr, mem[mstart : mstart + msz]))
        pblogger.log("SUB CONTRACT NEW", sender=msg.to, value=value, data=data.encode("hex"))
        create_msg = Message(msg.to, "", value, compustate.gas, data)
        addr, gas, code = create_contract(block, tx, create_msg)
        pblogger.log("SUB CONTRACT OUT", address=addr, code=code)
        if addr:
            stk.append(addr)
            compustate.gas = gas
        else:
            stk.append(0)
            compustate.gas = 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(),
        )
        new_memsize = max(meminstart + meminsz, memoutstart + memoutsz)
        if not mem_extend(mem, compustate, op, new_memsize):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception("subcall gas", gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (("\x00" * (32 - len(to))) + to)[12:].encode("hex")
        data = "".join(map(chr, mem[meminstart : meminstart + meminsz]))
        pblogger.log("SUB CALL NEW", sender=msg.to, to=to, value=value, gas=gas, data=data.encode("hex"))
        call_msg = Message(msg.to, to, value, gas, data)
        result, gas, data = apply_msg_send(block, tx, call_msg)
        pblogger.log("SUB CALL OUT", result=result, data=data, length=len(data), expected=memoutsz)
        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]
    elif op == "RETURN":
        s0, s1 = stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s1):
            return OUT_OF_GAS
        return mem[s0 : s0 + s1]
    elif op == "POST":
        gas, to, value, meminstart, meminsz = stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, meminstart + meminsz):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception("subcall gas", gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (("\x00" * (32 - len(to))) + to)[12:].encode("hex")
        data = "".join(map(chr, mem[meminstart : meminstart + meminsz]))
        pblogger.log("POST NEW", sender=msg.to, to=to, value=value, gas=gas, data=data.encode("hex"))
        post_msg = Message(msg.to, to, value, gas, data)
        block.postqueue.append(post_msg)
    elif op == "CALL_STATELESS":
        gas, to, value, meminstart, meminsz, memoutstart, memoutsz = (
            stk.pop(),
            stk.pop(),
            stk.pop(),
            stk.pop(),
            stk.pop(),
            stk.pop(),
            stk.pop(),
        )
        new_memsize = max(meminstart + meminsz, memoutstart + memoutsz)
        if not mem_extend(mem, compustate, op, new_memsize):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception("subcall gas", gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (("\x00" * (32 - len(to))) + to)[12:].encode("hex")
        data = "".join(map(chr, mem[meminstart : meminstart + meminsz]))
        pblogger.log("SUB CALL NEW", sender=msg.to, to=to, value=value, gas=gas, data=data.encode("hex"))
        call_msg = Message(msg.to, msg.to, value, gas, data)
        result, gas, data = apply_msg(block, tx, call_msg, block.get_code(to))
        pblogger.log("SUB CALL OUT", result=result, data=data, length=len(data), expected=memoutsz)
        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]
    elif op == "SUICIDE":
        to = utils.encode_int(stk.pop())
        to = (("\x00" * (32 - len(to))) + to)[12:].encode("hex")
        block.transfer_value(msg.to, to, block.get_balance(msg.to))
        block.suicides.append(msg.to)
        return []
    for a in stk:
        assert isinstance(a, (int, long))
Exemplo n.º 41
0
 def check_proof_of_work(self, nonce):
     prefix = self.serialize_header_without_nonce()
     h = utils.sha3(utils.sha3(prefix + nonce))
     l256 = utils.big_endian_to_int(h)
     return l256 < 2 ** 256 / self.difficulty
Exemplo n.º 42
0
def apply_op(block, tx, msg, processed_code, compustate):
    if compustate.pc >= len(processed_code):
        return []
    op, in_args, out_args, mem_grabs, fee, opcode = processed_code[
        compustate.pc]
    # empty stack error
    if in_args > len(compustate.stack):
        pblogger.log('INSUFFICIENT STACK ERROR',
                     op=op,
                     needed=in_args,
                     available=len(compustate.stack))
        return []

    # out of gas error
    if fee > compustate.gas:
        return out_of_gas_exception('base_gas', fee, compustate, op)

    if pblogger.log_apply_op:
        if pblogger.log_stack:
            pblogger.log('STK', stk=list(reversed(compustate.stack)))

        if pblogger.log_memory:
            for i in range(0, len(compustate.memory), 16):
                memblk = compustate.memory[i:i + 16]
                memline = ' '.join([chr(x).encode('hex') for x in memblk])
                pblogger.log('MEM', mem=memline)

        if pblogger.log_storage:
            pblogger.log('STORAGE',
                         storage=block.account_to_dict(msg.to)['storage'])

        if pblogger.log_op:
            log_args = dict(pc=compustate.pc,
                            op=op,
                            stackargs=compustate.stack[-1:-in_args - 1:-1],
                            gas=compustate.gas)
            if op[:4] == 'PUSH':
                ind = compustate.pc + 1
                log_args['value'] = \
                    utils.bytearray_to_int([x[-1] for x in processed_code[ind: ind + int(op[4:])]])
            elif op == 'CALLDATACOPY':
                log_args['data'] = msg.data.encode('hex')
            pblogger.log('OP', **log_args)

    # Apply operation
    compustate.gas -= fee
    compustate.pc += 1
    stk = compustate.stack
    mem = compustate.memory
    if op == 'STOP' or op == 'INVALID':
        return []
    elif op == 'ADD':
        stk.append((stk.pop() + stk.pop()) % TT256)
    elif op == 'SUB':
        stk.append((stk.pop() - stk.pop()) % TT256)
    elif op == 'MUL':
        stk.append((stk.pop() * stk.pop()) % TT256)
    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 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(0 if s1 == 0 else (s0 / s1) % TT256)
    elif op == 'SMOD':
        s0, s1 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(0 if s1 == 0 else (s0 % s1) % TT256)
    elif op == 'EXP':
        stk.append(pow(stk.pop(), stk.pop(), TT256))
    elif op == 'NEG':
        stk.append(-stk.pop() % TT256)
    elif 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 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(1 if s0 < s1 else 0)
    elif op == 'SGT':
        s0, s1 = to_signed(stk.pop()), 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 == 'NOT':
        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 == 'BYTE':
        s0, s1 = stk.pop(), stk.pop()
        if s0 >= 32:
            stk.append(0)
        else:
            stk.append((s1 / 256**(31 - s0)) % 256)
    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 == 'SHA3':
        s0, s1 = stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s1):
            return OUT_OF_GAS
        data = ''.join(map(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':
        stk.append(block.get_balance(utils.coerce_addr_to_hex(stk.pop())))
    elif op == 'ORIGIN':
        stk.append(utils.coerce_to_int(tx.sender))
    elif op == 'CALLER':
        stk.append(utils.coerce_to_int(msg.sender))
    elif op == 'CALLVALUE':
        stk.append(msg.value)
    elif op == 'CALLDATALOAD':
        s0 = stk.pop()
        if s0 >= len(msg.data):
            stk.append(0)
        else:
            dat = msg.data[s0:s0 + 32]
            stk.append(utils.big_endian_to_int(dat + '\x00' * (32 - len(dat))))
    elif op == 'CALLDATASIZE':
        stk.append(len(msg.data))
    elif op == 'CALLDATACOPY':
        s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s2):
            return OUT_OF_GAS
        for i in range(s2):
            if s1 + i < len(msg.data):
                mem[s0 + i] = ord(msg.data[s1 + i])
            else:
                mem[s0 + i] = 0
    elif op == 'GASPRICE':
        stk.append(tx.gasprice)
    elif op == 'CODECOPY':
        s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s2):
            return OUT_OF_GAS
        for i in range(s2):
            if s1 + i < len(processed_code):
                mem[s0 + i] = processed_code[s1 + i][-1]
            else:
                mem[s0 + i] = 0
    elif op == 'EXTCODESIZE':
        stk.append(len(block.get_code(stk.pop()) or ''))
    elif op == 'EXTCODECOPY':
        addr, s1, s2, s3 = stk.pop(), stk.pop(), stk.pop(), stk.pop()
        extcode = block.get_code(addr) or ''
        if not mem_extend(mem, compustate, op, s1 + s3):
            return OUT_OF_GAS
        for i in range(s3):
            if s2 + i < len(extcode):
                mem[s1 + i] = ord(extcode[s2 + i])
            else:
                mem[s1 + i] = 0
    elif op == 'PREVHASH':
        stk.append(utils.big_endian_to_int(block.prevhash))
    elif op == 'COINBASE':
        stk.append(utils.big_endian_to_int(block.coinbase.decode('hex')))
    elif op == 'TIMESTAMP':
        stk.append(block.timestamp)
    elif op == 'NUMBER':
        stk.append(block.number)
    elif op == 'DIFFICULTY':
        stk.append(block.difficulty)
    elif op == 'GASLIMIT':
        stk.append(block.gas_limit)
    elif op == 'POP':
        stk.pop()
    elif op == 'MLOAD':
        s0 = stk.pop()
        if not mem_extend(mem, compustate, op, s0 + 32):
            return OUT_OF_GAS
        data = ''.join(map(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 OUT_OF_GAS
        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 OUT_OF_GAS
        mem[s0] = s1 % 256
    elif op == 'SLOAD':
        stk.append(block.get_storage_data(msg.to, stk.pop()))
    elif op == 'SSTORE':
        s0, s1 = stk.pop(), stk.pop()
        pre_occupied = GSTORAGE if block.get_storage_data(msg.to, s0) else 0
        post_occupied = GSTORAGE if s1 else 0
        gascost = GSTORAGE + post_occupied - pre_occupied
        if compustate.gas < gascost:
            out_of_gas_exception('sstore trie expansion', gascost, compustate,
                                 op)
        compustate.gas -= gascost
        block.set_storage_data(msg.to, s0, s1)
    elif op == 'JUMP':
        compustate.pc = stk.pop()
    elif op == 'JUMPI':
        s0, s1 = stk.pop(), stk.pop()
        if s1:
            compustate.pc = s0
    elif op == 'PC':
        stk.append(compustate.pc)
    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:])
        dat = [
            x[-1]
            for x in processed_code[compustate.pc:compustate.pc + pushnum]
        ]
        compustate.pc += pushnum
        stk.append(utils.bytearray_to_int(dat))
    elif op[:3] == 'DUP':
        depth = int(op[3:])
        # DUP POP POP Debug hint
        is_debug = 1
        for i in range(depth):
            if compustate.pc + i < len(processed_code) and \
                    processed_code[compustate.pc + i][0] != 'POP':
                is_debug = 0
                break
        if is_debug:
            stackargs = [stk.pop() for i in range(depth)]
            print(' '.join(map(repr, stackargs)))
            stk.extend(reversed(stackargs))
            stk.append(stackargs[-1])
        else:
            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 == 'CREATE':
        value, mstart, msz = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, mstart + msz):
            return OUT_OF_GAS
        data = ''.join(map(chr, mem[mstart:mstart + msz]))
        pblogger.log('SUB CONTRACT NEW',
                     sender=msg.to,
                     value=value,
                     data=data.encode('hex'))
        create_msg = Message(msg.to, '', value, compustate.gas, data)
        addr, gas, code = create_contract(block, tx, create_msg)
        pblogger.log('SUB CONTRACT OUT', address=addr, code=code)
        if addr:
            stk.append(addr)
            compustate.gas = gas
        else:
            stk.append(0)
            compustate.gas = 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()
        new_memsize = max(meminstart + meminsz, memoutstart + memoutsz)
        if not mem_extend(mem, compustate, op, new_memsize):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception('subcall gas', gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        data = ''.join(map(chr, mem[meminstart:meminstart + meminsz]))
        pblogger.log('SUB CALL NEW',
                     sender=msg.to,
                     to=to,
                     value=value,
                     gas=gas,
                     data=data.encode('hex'))
        call_msg = Message(msg.to, to, value, gas, data)
        result, gas, data = apply_msg_send(block, tx, call_msg)
        pblogger.log('SUB CALL OUT',
                     result=result,
                     data=data,
                     length=len(data),
                     expected=memoutsz)
        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]
    elif op == 'RETURN':
        s0, s1 = stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s1):
            return OUT_OF_GAS
        return mem[s0:s0 + s1]
    elif op == 'POST':
        gas, to, value, meminstart, meminsz = \
            stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, meminstart + meminsz):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception('subcall gas', gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        data = ''.join(map(chr, mem[meminstart:meminstart + meminsz]))
        pblogger.log('POST NEW',
                     sender=msg.to,
                     to=to,
                     value=value,
                     gas=gas,
                     data=data.encode('hex'))
        post_msg = Message(msg.to, to, value, gas, data)
        block.postqueue.append(post_msg)
    elif op == 'CALL_STATELESS':
        gas, to, value, meminstart, meminsz, memoutstart, memoutsz = \
            stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
        new_memsize = max(meminstart + meminsz, memoutstart + memoutsz)
        if not mem_extend(mem, compustate, op, new_memsize):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception('subcall gas', gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        data = ''.join(map(chr, mem[meminstart:meminstart + meminsz]))
        pblogger.log('SUB CALL NEW',
                     sender=msg.to,
                     to=to,
                     value=value,
                     gas=gas,
                     data=data.encode('hex'))
        call_msg = Message(msg.to, msg.to, value, gas, data)
        result, gas, data = apply_msg(block, tx, call_msg, block.get_code(to))
        pblogger.log('SUB CALL OUT',
                     result=result,
                     data=data,
                     length=len(data),
                     expected=memoutsz)
        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]
    elif op == 'SUICIDE':
        to = utils.encode_int(stk.pop())
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        block.transfer_value(msg.to, to, block.get_balance(msg.to))
        block.suicides.append(msg.to)
        return []
    for a in stk:
        assert isinstance(a, (int, long))
Exemplo n.º 43
0
 def __hash__(self):
     return utils.big_endian_to_int(str_to_bytes(self.__repr__()))
Exemplo n.º 44
0
 def OP_PREVHASH():
     stk.append(utils.big_endian_to_int(block.prevhash))
Exemplo n.º 45
0
 def get_refcount(self, key):
     try:
         return utils.big_endian_to_int(self.db.get(key)[:4])
     except KeyError:
         return 0
Exemplo n.º 46
0
def apply_op(block, tx, msg, code, compustate):
    op, in_args, out_args = get_op_data(code, compustate.pc)
    # empty stack error
    if in_args > len(compustate.stack):
        return []
    # out of gas error
    fee = calcfee(block, tx, msg, compustate, op)
    if fee > compustate.gas:
        if debug:
            print("Out of gas", compustate.gas, "need", fee)
            print(op, list(reversed(compustate.stack)))
        return OUT_OF_GAS
    stackargs = []
    for i in range(in_args):
        stackargs.append(compustate.stack.pop())
    if debug:
        import serpent
        if op[:4] == 'PUSH':
            start, n = compustate.pc + 1, int(op[4:])
            print(op, utils.big_endian_to_int(code[start:start + n]))
        else:
            print(op, ' '.join(map(str, stackargs)),
                  serpent.decode_datalist(compustate.memory))
    # Apply operation
    oldgas = compustate.gas
    oldpc = compustate.pc
    compustate.gas -= fee
    compustate.pc += 1
    stk = compustate.stack
    mem = compustate.memory
    if op == 'STOP':
        return []
    elif op == 'ADD':
        stk.append((stackargs[0] + stackargs[1]) % 2 ** 256)
    elif op == 'SUB':
        stk.append((stackargs[0] - stackargs[1]) % 2 ** 256)
    elif op == 'MUL':
        stk.append((stackargs[0] * stackargs[1]) % 2 ** 256)
    elif op == 'DIV':
        if stackargs[1] == 0:
            return []
        stk.append(stackargs[0] / stackargs[1])
    elif op == 'MOD':
        if stackargs[1] == 0:
            return []
        stk.append(stackargs[0] % stackargs[1])
    elif op == 'SDIV':
        if stackargs[1] == 0:
            return []
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append((stackargs[0] / stackargs[1]) % 2 ** 256)
    elif op == 'SMOD':
        if stackargs[1] == 0:
            return []
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append((stackargs[0] % stackargs[1]) % 2 ** 256)
    elif op == 'EXP':
        stk.append(pow(stackargs[0], stackargs[1], 2 ** 256))
    elif op == 'NEG':
        stk.append(2 ** 256 - stackargs[0])
    elif op == 'LT':
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'GT':
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'SLT':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'SGT':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'EQ':
        stk.append(1 if stackargs[0] == stackargs[1] else 0)
    elif op == 'NOT':
        stk.append(0 if stackargs[0] else 1)
    elif op == 'AND':
        stk.append(stackargs[0] & stackargs[1])
    elif op == 'OR':
        stk.append(stackargs[0] | stackargs[1])
    elif op == 'XOR':
        stk.append(stackargs[0] ^ stackargs[1])
    elif op == 'BYTE':
        if stackargs[0] >= 32:
            stk.append(0)
        else:
            stk.append((stackargs[1] / 256 ** stackargs[0]) % 256)
    elif op == 'SHA3':
        if len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + stackargs[1]]))
        print 'data time!'
        print data
        print data.encode('hex')
        stk.append(int(utils.sha3(data).encode('hex'), 16))
    elif op == 'ECVERIFY':
        # parameters: msg_hash (32), v (32), r (32), s (32), pubX (32), pubY (32)
        # stack should have all args
        msg_hash, v, r, s, pubX, pubY = stackargs
        pubX = utils.int_to_big_endian(pubX).encode('hex')
        pubY = utils.int_to_big_endian(pubY).encode('hex')
        msg_hash = utils.int_to_big_endian(msg_hash)
        pub = ('04' + pubX + pubY).decode('hex')
        verified = ecdsa_raw_verify(msg_hash, (v, r, s), pub)
        print 'verified: ', verified
        stk.append(verified)
    elif op == 'ECRECOVER':
        # parameters: msg_hash (32), v (32), r (32), s (32), p (64 - empty array to hold pubkey)
        # stack should have all args
        msg_hash, v, r, s = stackargs
        msg_hash = utils.int_to_big_endian(msg_hash)
        pubX, pubY = ecdsa_raw_recover(msg_hash, (v, r, s))
        stk.append(pubX)
        stk.append(pubY)
    elif op == 'PUB2ADDR':
        pubX, pubY = stackargs
        pubX = utils.int_to_big_endian(pubX).encode('hex')
        pubY = utils.int_to_big_endian(pubY).encode('hex')
        pub = pubX + pubY
        pub = pub.decode('hex')
        addr = utils.sha3(pub)[12:]
        stk.append(addr)
    elif op == 'ADDRESS':
        stk.append(msg.to)
    elif op == 'BALANCE':
        stk.append(block.get_balance(msg.to))
    elif op == 'ORIGIN':
        stk.append(tx.sender)
    elif op == 'CALLER':
        stk.append(utils.coerce_to_int(msg.sender))
    elif op == 'CALLVALUE':
        stk.append(msg.value)
    elif op == 'CALLDATALOAD':
        if stackargs[0] >= len(msg.data):
            stk.append(0)
        else:
            dat = msg.data[stackargs[0]:stackargs[0] + 32]
            stk.append(utils.big_endian_to_int(dat + '\x00' * (32 - len(dat))))
    elif op == 'CALLDATASIZE':
        stk.append(len(msg.data))
    elif op == 'CALLDATACOPY':
        if len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[0] + i < len(msg.data):
                mem[stackargs[1] + i] = ord(msg.data[stackargs[0] + i])
            else:
                mem[stackargs[1] + i] = 0
    elif op == 'GASPRICE':
        stk.append(tx.gasprice)
    elif op == 'CODECOPY':
        if len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[0] + i < len(code):
                mem[stackargs[1] + i] = ord(code[stackargs[0] + i])
            else:
                mem[stackargs[1] + i] = 0
    elif op == 'PREVHASH':
        stk.append(utils.big_endian_to_int(block.prevhash))
    elif op == 'COINBASE':
        stk.append(utils.big_endian_to_int(block.coinbase.decode('hex')))
    elif op == 'TIMESTAMP':
        stk.append(block.timestamp)
    elif op == 'NUMBER':
        stk.append(block.number)
    elif op == 'DIFFICULTY':
        stk.append(block.difficulty)
    elif op == 'GASLIMIT':
        stk.append(block.gaslimit)
    elif op == 'POP':
        pass
    elif op == 'DUP':
        stk.append(stackargs[0])
        stk.append(stackargs[0])
    elif op == 'SWAP':
        stk.append(stackargs[0])
        stk.append(stackargs[1])
    elif op == 'MLOAD':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + 32]))
        stk.append(utils.big_endian_to_int(data))
    elif op == 'MSTORE':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        v = stackargs[1]
        #if isinstance(v, str):
        #    v = int(v.encode('hex'), 16)
        for i in range(31, -1, -1):
            mem[stackargs[0] + i] = v % 256
            v /= 256
    elif op == 'MSTORE8':
        if len(mem) < ceil32(stackargs[0] + 1):
            mem.extend([0] * (ceil32(stackargs[0] + 1) - len(mem)))
        mem[stackargs[0]] = stackargs[1] % 256
    elif op == 'SLOAD':
        stk.append(block.get_storage_data(msg.to, stackargs[0]))
    elif op == 'SSTORE':
        block.set_storage_data(msg.to, stackargs[0], stackargs[1])
    elif op == 'JUMP':
        compustate.pc = stackargs[0]
    elif op == 'JUMPI':
        if stackargs[1]:
            compustate.pc = stackargs[0]
    elif op == 'PC':
        stk.append(compustate.pc)
    elif op == 'MSIZE':
        stk.append(len(mem))
    elif op == 'GAS':
        stk.append(oldgas)
    elif op[:4] == 'PUSH':
        pushnum = int(op[4:])
        compustate.pc = oldpc + 1 + pushnum
        dat = code[oldpc + 1: oldpc + 1 + pushnum]
        stk.append(utils.big_endian_to_int(dat))
    elif op == 'CREATE':
        if len(mem) < ceil32(stackargs[2] + stackargs[3]):
            mem.extend([0] * (ceil32(stackargs[2] + stackargs[3]) - len(mem)))
        gas = stackargs[0]
        value = stackargs[1]
        data = ''.join(map(chr, mem[stackargs[2]:stackargs[2] + stackargs[3]]))
        if debug:
            print("Sub-contract:", msg.to, value, gas, data)
        addr, gas, code = create_contract(
            block, tx, Message(msg.to, '', value, gas, data))
        if debug:
            print("Output of contract creation:", addr, code)
        if addr:
            stk.append(utils.coerce_to_int(addr))
        else:
            stk.append(0)
    elif op == 'CALL':
        if len(mem) < ceil32(stackargs[3] + stackargs[4]):
            mem.extend([0] * (ceil32(stackargs[3] + stackargs[4]) - len(mem)))
        if len(mem) < ceil32(stackargs[5] + stackargs[6]):
            mem.extend([0] * (ceil32(stackargs[5] + stackargs[6]) - len(mem)))
        gas = stackargs[0]
        to = utils.encode_int(stackargs[1])
        to = (('\x00' * (32 - len(to))) + to)[12:]
        value = stackargs[2]
        data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]]))
        if debug:
            print("Sub-call:", utils.coerce_addr_to_hex(msg.to),
                  utils.coerce_addr_to_hex(to), value, gas, data)
        result, gas, data = apply_msg(
            block, tx, Message(msg.to, to, value, gas, data))
        if debug:
            print("Output of sub-call:", result, data, "length", len(data),
                  "expected", stackargs[6])
        for i in range(stackargs[6]):
            mem[stackargs[5] + i] = 0
        if result == 0:
            stk.append(0)
        else:
            stk.append(1)
            compustate.gas += gas
            for i in range(len(data)):
                mem[stackargs[5] + i] = data[i]
    elif op == 'RETURN':
        if len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        return mem[stackargs[0]:stackargs[0] + stackargs[1]]
    elif op == 'SUICIDE':
        to = utils.encode_int(stackargs[0])
        to = (('\x00' * (32 - len(to))) + to)[12:]
        block.delta_balance(to, block.get_balance(msg.to))
        block.state.update(msg.to, '')
        return []
Exemplo n.º 47
0
def sub1(b):
    v = utils.big_endian_to_int(b)
    return utils.zpad(utils.encode_int(v - 1), 4)
Exemplo n.º 48
0
def add1(b):
    v = utils.big_endian_to_int(b)
    return utils.zpad(utils.encode_int(v + 1), 4)
Exemplo n.º 49
0
def apply_op(block, tx, msg, code, compustate):
    op, in_args, out_args, mem_grabs, base_gas = opdata = get_op_data(code, compustate.pc)
    # empty stack error
    if in_args > len(compustate.stack):
        pblogger.log('INSUFFICIENT STACK ERROR', op=op, needed=in_args,
                     available=len(compustate.stack))
        return []
    # out of gas error
    fee = calcfee(block, tx, msg, compustate, opdata)
    if fee > compustate.gas:
        pblogger.log('OUT OF GAS', needed=fee, available=compustate.gas,
                            op=op, stack=list(reversed(compustate.stack)))
        return OUT_OF_GAS
    stackargs = []
    for i in range(in_args):
        stackargs.append(compustate.stack.pop())

    if pblogger.log_op:
        log_args = dict(pc=compustate.pc, op=op, stackargs=stackargs, gas=compustate.gas)
        if op[:4] == 'PUSH':
            ind = compustate.pc + 1
            log_args['value'] = utils.big_endian_to_int(code[ind: ind + int(op[4:])])
        elif op == 'CALLDATACOPY':
            log_args['data'] = msg.data.encode('hex')
        pblogger.log('OP', **log_args)

    if pblogger.log_memory:
        for i in range(0, len(compustate.memory), 16):
            memblk = compustate.memory[i:i+16]
            memline = ' '.join([chr(x).encode('hex') for x in memblk])
            pblogger.log('MEM', mem=memline)

    # Apply operation
    oldpc = compustate.pc
    compustate.gas -= fee
    compustate.pc += 1
    stk = compustate.stack
    mem = compustate.memory
    if op == 'STOP' or op == 'INVALID':
        return []
    elif op == 'ADD':
        stk.append((stackargs[0] + stackargs[1]) % 2 ** 256)
    elif op == 'SUB':
        stk.append((stackargs[0] - stackargs[1]) % 2 ** 256)
    elif op == 'MUL':
        stk.append((stackargs[0] * stackargs[1]) % 2 ** 256)
    elif op == 'DIV':
        stk.append(0 if stackargs[1] == 0 else stackargs[0] / stackargs[1])
    elif op == 'MOD':
        stk.append(0 if stackargs[1] == 0 else stackargs[0] % stackargs[1])
    elif op == 'SDIV':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(0 if stackargs[1] == 0 else
                   (stackargs[0] / stackargs[1]) % 2 ** 256)
    elif op == 'SMOD':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(0 if stackargs[1] == 0 else
                   (stackargs[0] % stackargs[1]) % 2 ** 256)
    elif op == 'EXP':
        stk.append(pow(stackargs[0], stackargs[1], 2 ** 256))
    elif op == 'NEG':
        stk.append(-stackargs[0] % 2**256)
    elif op == 'LT':
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'GT':
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'SLT':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'SGT':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'EQ':
        stk.append(1 if stackargs[0] == stackargs[1] else 0)
    elif op == 'NOT':
        stk.append(0 if stackargs[0] else 1)
    elif op == 'AND':
        stk.append(stackargs[0] & stackargs[1])
    elif op == 'OR':
        stk.append(stackargs[0] | stackargs[1])
    elif op == 'XOR':
        stk.append(stackargs[0] ^ stackargs[1])
    elif op == 'BYTE':
        if stackargs[0] >= 32:
            stk.append(0)
        else:
            stk.append((stackargs[1] / 256 ** (31 - stackargs[0])) % 256)
    elif op == 'ADDMOD':
        stk.append((stackargs[0] + stackargs[1]) % stackargs[2]
                   if stackargs[2] else 0)
    elif op == 'MULMOD':
        stk.append((stackargs[0] * stackargs[1]) % stackargs[2]
                   if stackargs[2] else 0)
    elif op == 'SHA3':
        if stackargs[1] and len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + stackargs[1]]))
        stk.append(utils.big_endian_to_int(utils.sha3(data)))
    elif op == 'ADDRESS':
        stk.append(utils.coerce_to_int(msg.to))
    elif op == 'BALANCE':
        stk.append(block.get_balance(utils.coerce_addr_to_hex(stackargs[0])))
    elif op == 'ORIGIN':
        stk.append(utils.coerce_to_int(tx.sender))
    elif op == 'CALLER':
        stk.append(utils.coerce_to_int(msg.sender))
    elif op == 'CALLVALUE':
        stk.append(msg.value)
    elif op == 'CALLDATALOAD':
        if stackargs[0] >= len(msg.data):
            stk.append(0)
        else:
            dat = msg.data[stackargs[0]:stackargs[0] + 32]
            stk.append(utils.big_endian_to_int(dat + '\x00' * (32 - len(dat))))
    elif op == 'CALLDATASIZE':
        stk.append(len(msg.data))
    elif op == 'CALLDATACOPY':
        if stackargs[2] and len(mem) < ceil32(stackargs[0] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[1] + i < len(msg.data):
                mem[stackargs[0] + i] = ord(msg.data[stackargs[1] + i])
            else:
                mem[stackargs[0] + i] = 0
    elif op == 'GASPRICE':
        stk.append(tx.gasprice)
    elif op == 'CODECOPY':
        if stackargs[2] and len(mem) < ceil32(stackargs[0] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[1] + i < len(code):
                mem[stackargs[0] + i] = ord(code[stackargs[1] + i])
            else:
                mem[stackargs[0] + i] = 0
    elif op == 'PREVHASH':
        stk.append(utils.big_endian_to_int(block.prevhash))
    elif op == 'COINBASE':
        stk.append(utils.big_endian_to_int(block.coinbase.decode('hex')))
    elif op == 'TIMESTAMP':
        stk.append(block.timestamp)
    elif op == 'NUMBER':
        stk.append(block.number)
    elif op == 'DIFFICULTY':
        stk.append(block.difficulty)
    elif op == 'GASLIMIT':
        stk.append(block.gas_limit)
    elif op == 'POP':
        pass
    elif op == 'SWAP':
        stk.append(stackargs[0])
        stk.append(stackargs[1])
    elif op == 'MLOAD':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + 32]))
        stk.append(utils.big_endian_to_int(data))
    elif op == 'MSTORE':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        v = stackargs[1]
        for i in range(31, -1, -1):
            mem[stackargs[0] + i] = v % 256
            v /= 256
    elif op == 'MSTORE8':
        if len(mem) < ceil32(stackargs[0] + 1):
            mem.extend([0] * (ceil32(stackargs[0] + 1) - len(mem)))
        mem[stackargs[0]] = stackargs[1] % 256
    elif op == 'SLOAD':
        stk.append(block.get_storage_data(msg.to, stackargs[0]))
    elif op == 'SSTORE':
        block.set_storage_data(msg.to, stackargs[0], stackargs[1])
    elif op == 'JUMP':
        compustate.pc = stackargs[0]
    elif op == 'JUMPI':
        if stackargs[1]:
            compustate.pc = stackargs[0]
    elif op == 'PC':
        stk.append(compustate.pc)
    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 = oldpc + 1 + pushnum
        dat = code[oldpc + 1: oldpc + 1 + pushnum]
        stk.append(utils.big_endian_to_int(dat))
    elif op[:3] == 'DUP':
        # DUP POP POP Debug hint
        is_debug = 1
        for i in range(len(stackargs)):
            if get_op_data(code, oldpc + i + 1)[0] != 'POP':
                is_debug = 0
                break
        if is_debug:
            print(' '.join(map(repr, stackargs)))
            pblogger.log('DEBUG', vals=stackargs)
            compustate.pc = oldpc + 2 + len(stackargs)
        else:
            stk.extend(reversed(stackargs))
            stk.append(stackargs[-1])
    elif op[:4] == 'SWAP':
        stk.append(stackargs[0])
        stk.extend(reversed(stackargs[1:-1]))
        stk.append(stackargs[-1])
    elif op == 'CREATE':
        if stackargs[2] and len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        value = stackargs[0]
        data = ''.join(map(chr, mem[stackargs[1]:stackargs[1] + stackargs[2]]))
        pblogger.log('SUB CONTRACT NEW', sender=msg.to, value=value, data=data.encode('hex'))
        create_msg = Message(msg.to, '', value, compustate.gas, data)
        addr, gas, code = create_contract(block, tx, create_msg)
        pblogger.log('SUB CONTRACT OUT', address=addr, code=code)
        if addr:
            stk.append(addr)
            compustate.gas = gas
        else:
            stk.append(0)
            compustate.gas = 0
    elif op == 'CALL':
        if stackargs[4] and len(mem) < ceil32(stackargs[3] + stackargs[4]):
            mem.extend([0] * (ceil32(stackargs[3] + stackargs[4]) - len(mem)))
        if stackargs[6] and len(mem) < ceil32(stackargs[5] + stackargs[6]):
            mem.extend([0] * (ceil32(stackargs[5] + stackargs[6]) - len(mem)))
        gas = stackargs[0]
        to = utils.encode_int(stackargs[1])
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        value = stackargs[2]
        data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]]))
        pblogger.log('SUB CALL NEW', sender=msg.to, to=to, value=value, gas=gas, data=data.encode('hex'))
        call_msg = Message(msg.to, to, value, gas, data)
        result, gas, data = apply_msg_send(block, tx, call_msg)
        pblogger.log('SUB CALL OUT', result=result, data=data, length=len(data), expected=stackargs[6])
        if result == 0:
            stk.append(0)
        else:
            stk.append(1)
            compustate.gas += gas
            for i in range(min(len(data), stackargs[6])):
                mem[stackargs[5] + i] = data[i]
    elif op == 'RETURN':
        if stackargs[1] and len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        return mem[stackargs[0]:stackargs[0] + stackargs[1]]
    elif op == 'POST':
        if stackargs[4] and len(mem) < ceil32(stackargs[3] + stackargs[4]):
            mem.extend([0] * (ceil32(stackargs[3] + stackargs[4]) - len(mem)))
        gas = stackargs[0]
        to = utils.encode_int(stackargs[1])
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        value = stackargs[2]
        data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]]))
        pblogger.log('POST NEW', sender=msg.to, to=to, value=value, gas=gas, data=data.encode('hex'))
        post_msg = Message(msg.to, to, value, gas, data)
        block.postqueue.append(post_msg)
    elif op == 'CALL_STATELESS':
        if stackargs[4] and len(mem) < ceil32(stackargs[3] + stackargs[4]):
            mem.extend([0] * (ceil32(stackargs[3] + stackargs[4]) - len(mem)))
        if stackargs[6] and len(mem) < ceil32(stackargs[5] + stackargs[6]):
            mem.extend([0] * (ceil32(stackargs[5] + stackargs[6]) - len(mem)))
        gas = stackargs[0]
        to = utils.encode_int(stackargs[1])
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        value = stackargs[2]
        data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]]))
        pblogger.log('SUB CALL NEW', sender=msg.to, to=to, value=value, gas=gas, data=data.encode('hex'))
        call_msg = Message(msg.to, msg.to, value, gas, data)
        result, gas, data = apply_msg(block, tx, call_msg, block.get_code(to))
        pblogger.log('SUB CALL OUT', result=result, data=data, length=len(data), expected=stackargs[6])
        if result == 0:
            stk.append(0)
        else:
            stk.append(1)
            compustate.gas += gas
            for i in range(min(len(data), stackargs[6])):
                mem[stackargs[5] + i] = data[i]

    elif op == 'SUICIDE':
        to = utils.encode_int(stackargs[0])
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        block.transfer_value(msg.to, to, block.get_balance(msg.to))
        block.suicides.append(msg.to)
        return []
    for a in stk:
        assert isinstance(a, (int, long))
Exemplo n.º 50
0
def apply_op(block, tx, msg, processed_code, compustate):
    if compustate.pc >= len(processed_code):
        return []
    op, in_args, out_args, mem_grabs, fee, opcode = processed_code[compustate.pc]
    # empty stack error
    if in_args > len(compustate.stack):
        pblogger.log('INSUFFICIENT STACK ERROR', op=op, needed=in_args,
                     available=len(compustate.stack))
        return []

    # out of gas error
    if fee > compustate.gas:
        return out_of_gas_exception('base_gas', fee, compustate, op)

    if pblogger.log_apply_op:
        if pblogger.log_stack:
            pblogger.log('STK', stk=list(reversed(compustate.stack)))

        if pblogger.log_op:
            log_args = dict(pc=compustate.pc,
                            op=op,
                            stackargs=compustate.stack[-1:-in_args-1:-1],
                            gas=compustate.gas)
            if op[:4] == 'PUSH':
                ind = compustate.pc + 1
                log_args['value'] = \
                    utils.bytearray_to_int([x[-1] for x in processed_code[ind: ind + int(op[4:])]])
            elif op == 'CALLDATACOPY':
                log_args['data'] = msg.data.encode('hex')
            pblogger.log('OP', **log_args)

        if pblogger.log_memory:
            for i in range(0, len(compustate.memory), 16):
                memblk = compustate.memory[i:i+16]
                memline = ' '.join([chr(x).encode('hex') for x in memblk])
                pblogger.log('MEM', mem=memline)

    # Apply operation
    compustate.gas -= fee
    compustate.pc += 1
    stk = compustate.stack
    mem = compustate.memory
    if op == 'STOP' or op == 'INVALID':
        return []
    elif op == 'ADD':
        stk.append((stk.pop() + stk.pop()) % TT256)
    elif op == 'SUB':
        stk.append((stk.pop() - stk.pop()) % TT256)
    elif op == 'MUL':
        stk.append((stk.pop() * stk.pop()) % TT256)
    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 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(0 if s1 == 0 else (s0 / s1) % TT256)
    elif op == 'SMOD':
        s0, s1 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(0 if s1 == 0 else (s0 % s1) % TT256)
    elif op == 'EXP':
        stk.append(pow(stk.pop(), stk.pop(), TT256))
    elif op == 'NEG':
        stk.append(-stk.pop() % TT256)
    elif 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 = to_signed(stk.pop()), to_signed(stk.pop())
        stk.append(1 if s0 < s1 else 0)
    elif op == 'SGT':
        s0, s1 = to_signed(stk.pop()), 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 == 'NOT':
        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 == 'BYTE':
        s0, s1 = stk.pop(), stk.pop()
        if s0 >= 32:
            stk.append(0)
        else:
            stk.append((s1 / 256 ** (31 - s0)) % 256)
    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 == 'SHA3':
        s0, s1 = stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s1):
            return OUT_OF_GAS
        data = ''.join(map(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':
        stk.append(block.get_balance(utils.coerce_addr_to_hex(stk.pop())))
    elif op == 'ORIGIN':
        stk.append(utils.coerce_to_int(tx.sender))
    elif op == 'CALLER':
        stk.append(utils.coerce_to_int(msg.sender))
    elif op == 'CALLVALUE':
        stk.append(msg.value)
    elif op == 'CALLDATALOAD':
        s0 = stk.pop()
        if s0 >= len(msg.data):
            stk.append(0)
        else:
            dat = msg.data[s0: s0 + 32]
            stk.append(utils.big_endian_to_int(dat + '\x00' * (32 - len(dat))))
    elif op == 'CALLDATASIZE':
        stk.append(len(msg.data))
    elif op == 'CALLDATACOPY':
        s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s2):
            return OUT_OF_GAS
        for i in range(s2):
            if s1 + i < len(msg.data):
                mem[s0 + i] = ord(msg.data[s1 + i])
            else:
                mem[s0 + i] = 0
    elif op == 'GASPRICE':
        stk.append(tx.gasprice)
    elif op == 'CODECOPY':
        s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s2):
            return OUT_OF_GAS
        for i in range(s2):
            if s1 + i < len(processed_code):
                mem[s0 + i] = processed_code[s1 + i][-1]
            else:
                mem[s0 + i] = 0
    elif op == 'EXTCODESIZE':
        stk.append(len(block.get_code(stk.pop()) or ''))
    elif op == 'EXTCODECOPY':
        addr, s1, s2, s3 = stk.pop(), stk.pop(), stk.pop(), stk.pop()
        extcode = block.get_code(addr) or ''
        if not mem_extend(mem, compustate, op, s1 + s3):
            return OUT_OF_GAS
        for i in range(s3):
            if s2 + i < len(extcode):
                mem[s1 + i] = ord(extcode[s2 + i])
            else:
                mem[s1 + i] = 0
    elif op == 'PREVHASH':
        stk.append(utils.big_endian_to_int(block.prevhash))
    elif op == 'COINBASE':
        stk.append(utils.big_endian_to_int(block.coinbase.decode('hex')))
    elif op == 'TIMESTAMP':
        stk.append(block.timestamp)
    elif op == 'NUMBER':
        stk.append(block.number)
    elif op == 'DIFFICULTY':
        stk.append(block.difficulty)
    elif op == 'GASLIMIT':
        stk.append(block.gas_limit)
    elif op == 'POP':
        stk.pop()
    elif op == 'MLOAD':
        s0 = stk.pop()
        if not mem_extend(mem, compustate, op, s0 + 32):
            return OUT_OF_GAS
        data = ''.join(map(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 OUT_OF_GAS
        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 OUT_OF_GAS
        mem[s0] = s1 % 256
    elif op == 'SLOAD':
        stk.append(block.get_storage_data(msg.to, stk.pop()))
    elif op == 'SSTORE':
        s0, s1 = stk.pop(), stk.pop()
        pre_occupied = GSTORAGE if block.get_storage_data(msg.to, s0) else 0
        post_occupied = GSTORAGE if s1 else 0
        gascost = GSTORAGE + post_occupied - pre_occupied
        if compustate.gas < gascost:
            out_of_gas_exception('sstore trie expansion', gascost, compustate, op)
        compustate.gas -= gascost
        block.set_storage_data(msg.to, s0, s1)
    elif op == 'JUMP':
        compustate.pc = stk.pop()
    elif op == 'JUMPI':
        s0, s1 = stk.pop(), stk.pop()
        if s1:
            compustate.pc = s0
    elif op == 'PC':
        stk.append(compustate.pc)
    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:])
        dat = [x[-1] for x in processed_code[compustate.pc: compustate.pc + pushnum]]
        compustate.pc += pushnum
        stk.append(utils.bytearray_to_int(dat))
    elif op[:3] == 'DUP':
        depth = int(op[3:])
        # DUP POP POP Debug hint
        is_debug = 1
        for i in range(depth):
            if compustate.pc + i < len(processed_code) and \
                    processed_code[compustate.pc + i][0] != 'POP':
                is_debug = 0
                break
        if is_debug:
            stackargs = [stk.pop() for i in range(depth)]
            print(' '.join(map(repr, stackargs)))
            stk.extend(reversed(stackargs))
            stk.append(stackargs[-1])
        else:
            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 == 'CREATE':
        value, mstart, msz = stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, mstart + msz):
            return OUT_OF_GAS
        data = ''.join(map(chr, mem[mstart: mstart + msz]))
        pblogger.log('SUB CONTRACT NEW', sender=msg.to, value=value, data=data.encode('hex'))
        create_msg = Message(msg.to, '', value, compustate.gas, data)
        addr, gas, code = create_contract(block, tx, create_msg)
        pblogger.log('SUB CONTRACT OUT', address=addr, code=code)
        if addr:
            stk.append(addr)
            compustate.gas = gas
        else:
            stk.append(0)
            compustate.gas = 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()
        new_memsize = max(meminstart + meminsz, memoutstart + memoutsz)
        if not mem_extend(mem, compustate, op, new_memsize):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception('subcall gas', gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        data = ''.join(map(chr, mem[meminstart: meminstart + meminsz]))
        pblogger.log('SUB CALL NEW', sender=msg.to, to=to, value=value, gas=gas, data=data.encode('hex'))
        call_msg = Message(msg.to, to, value, gas, data)
        result, gas, data = apply_msg_send(block, tx, call_msg)
        pblogger.log('SUB CALL OUT', result=result, data=data, length=len(data), expected=memoutsz)
        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]
    elif op == 'RETURN':
        s0, s1 = stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, s0 + s1):
            return OUT_OF_GAS
        return mem[s0: s0 + s1]
    elif op == 'POST':
        gas, to, value, meminstart, meminsz = \
            stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
        if not mem_extend(mem, compustate, op, meminstart + meminsz):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception('subcall gas', gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        data = ''.join(map(chr, mem[meminstart: meminstart + meminsz]))
        pblogger.log('POST NEW', sender=msg.to, to=to, value=value, gas=gas, data=data.encode('hex'))
        post_msg = Message(msg.to, to, value, gas, data)
        block.postqueue.append(post_msg)
    elif op == 'CALL_STATELESS':
        gas, to, value, meminstart, meminsz, memoutstart, memoutsz = \
            stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
        new_memsize = max(meminstart + meminsz, memoutstart + memoutsz)
        if not mem_extend(mem, compustate, op, new_memsize):
            return OUT_OF_GAS
        if compustate.gas < gas:
            return out_of_gas_exception('subcall gas', gas, compustate, op)
        compustate.gas -= gas
        to = utils.encode_int(to)
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        data = ''.join(map(chr, mem[meminstart: meminstart + meminsz]))
        pblogger.log('SUB CALL NEW', sender=msg.to, to=to, value=value, gas=gas, data=data.encode('hex'))
        call_msg = Message(msg.to, msg.to, value, gas, data)
        result, gas, data = apply_msg(block, tx, call_msg, block.get_code(to))
        pblogger.log('SUB CALL OUT', result=result, data=data, length=len(data), expected=memoutsz)
        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]
    elif op == 'SUICIDE':
        to = utils.encode_int(stk.pop())
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        block.transfer_value(msg.to, to, block.get_balance(msg.to))
        block.suicides.append(msg.to)
        return []
    for a in stk:
        assert isinstance(a, (int, long))
Exemplo n.º 51
0
 def deserialize(cls, s):
     return big_endian_to_int(s)
Exemplo n.º 52
0
 def __hash__(self):
     return big_endian_to_int(self.hash)
Exemplo n.º 53
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)

    while 1:
        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=str(in_args),
                                available=str(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 = {}
            if log_vm_op_stack.is_active():
                trace_data['stack'] = map(str, list(compustate.stack))
            if log_vm_op_memory.is_active():
                trace_data['memory'] = \
                    ''.join([chr(x).encode('hex') for x in compustate.memory])
            if log_vm_op_storage.is_active():
                trace_data['storage'] = ext.log_storage(msg.to)
            trace_data['gas'] = str(compustate.gas + fee)
            trace_data['pc'] = str(compustate.pc - 1)
            trace_data['op'] = op
            if op[:4] == 'PUSH':
                trace_data['pushvalue'] = pushval

            log_vm_op.trace('vm', **trace_data)

        # 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 -= 10 * (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 = ''.join(map(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 ''))
            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 ''
                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] = 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.decode('hex')))
            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 = ''.join(map(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
                else:
                    gascost = opcodes.GSTORAGEADD if s1 else opcodes.GSTORAGEMOD
                if compustate.gas < gascost:
                    return vm_exception('OUT OF GAS')
                compustate.gas -= max(gascost, 0)
                ext.add_refund(max(
                    -gascost, 0))  # 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
            if not mem_extend(mem, compustate, op, mstart, msz):
                return vm_exception('OOG EXTENDING MEMORY')
            data = ''.join(map(chr, mem[mstart:mstart + msz]))
            ext.log(msg.to, topics, data)
            log_log.trace('LOG', to=msg.to, topics=topics, data=map(ord, data))
            print('LOG', msg.to, topics, 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, '', 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')
            if compustate.gas < gas:
                return vm_exception('OUT OF GAS')
            if ext.get_balance(msg.to) >= value and msg.depth < 1024:
                compustate.gas -= gas
                to = utils.encode_int(to)
                to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
                cd = CallData(mem, meminstart, meminsz)
                call_msg = Message(msg.to, to, value, gas, cd, msg.depth + 1)
                result, gas, data = ext.call(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:
                stk.append(0)
        elif op == 'CALLCODE':
            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')
            if compustate.gas < gas:
                return vm_exception('OUT OF GAS')
            if ext.get_balance(msg.to) >= value and msg.depth < 1024:
                compustate.gas -= gas
                to = utils.encode_int(to)
                to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
                cd = CallData(mem, meminstart, meminsz)
                call_msg = Message(msg.to, msg.to, value, gas, cd,
                                   msg.depth + 1)
                result, gas, data = ext.sendmsg(call_msg, ext.get_code(to))
                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:
                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 = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
            xfer = ext.get_balance(msg.to)
            ext.set_balance(msg.to, 0)
            ext.set_balance(to, ext.get_balance(to) + xfer)
            ext.add_suicide(msg.to)
            return 1, compustate.gas, []
Exemplo n.º 54
0
 def OP_SHA3():
     s0, s1 = stk.pop(), stk.pop()
     if not mem_extend(mem, msgtop.compustate, '', s0, s1):
         return drop(OUT_OF_GAS)
     data = ''.join([chr(x) for x in mem[s0:s0 + s1]])
     stk.append(utils.big_endian_to_int(utils.sha3(data)))
Exemplo n.º 55
0
def apply_op(block, tx, msg, code, compustate):
    op, in_args, out_args = get_op_data(code, compustate.pc)
    # empty stack error
    if in_args > len(compustate.stack):
        return []
    # out of gas error
    fee = calcfee(block, tx, msg, compustate, op)
    if fee > compustate.gas:
        logger.debug("Out of gas %s need %s", compustate.gas, fee)
        logger.debug('%s %s', op, list(reversed(compustate.stack)))
        return OUT_OF_GAS
    stackargs = []
    for i in range(in_args):
        stackargs.append(compustate.stack.pop())
    if expensive_debug:
        import serpent
        if op[:4] == 'PUSH':
            start, n = compustate.pc + 1, int(op[4:])
            logger.debug('%s %s ', op,
                         utils.big_endian_to_int(code[start:start + n]))
        else:
            logger.debug('%s %s %s', op, ' '.join(map(str, stackargs)),
                         serpent.decode_datalist(compustate.memory))
    # Apply operation
    oldgas = compustate.gas
    oldpc = compustate.pc
    compustate.gas -= fee
    compustate.pc += 1
    stk = compustate.stack
    mem = compustate.memory
    if op == 'STOP':
        return []
    elif op == 'ADD':
        stk.append((stackargs[0] + stackargs[1]) % 2 ** 256)
    elif op == 'SUB':
        stk.append((stackargs[0] - stackargs[1]) % 2 ** 256)
    elif op == 'MUL':
        stk.append((stackargs[0] * stackargs[1]) % 2 ** 256)
    elif op == 'DIV':
        if stackargs[1] == 0:
            return []
        stk.append(stackargs[0] / stackargs[1])
    elif op == 'MOD':
        if stackargs[1] == 0:
            return []
        stk.append(stackargs[0] % stackargs[1])
    elif op == 'SDIV':
        if stackargs[1] == 0:
            return []
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append((stackargs[0] / stackargs[1]) % 2 ** 256)
    elif op == 'SMOD':
        if stackargs[1] == 0:
            return []
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append((stackargs[0] % stackargs[1]) % 2 ** 256)
    elif op == 'EXP':
        stk.append(pow(stackargs[0], stackargs[1], 2 ** 256))
    elif op == 'NEG':
        stk.append(2 ** 256 - stackargs[0])
    elif op == 'LT':
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'GT':
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'SLT':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'SGT':
        if stackargs[0] >= 2 ** 255:
            stackargs[0] -= 2 ** 256
        if stackargs[1] >= 2 ** 255:
            stackargs[1] -= 2 ** 256
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'EQ':
        stk.append(1 if stackargs[0] == stackargs[1] else 0)
    elif op == 'NOT':
        stk.append(0 if stackargs[0] else 1)
    elif op == 'AND':
        stk.append(stackargs[0] & stackargs[1])
    elif op == 'OR':
        stk.append(stackargs[0] | stackargs[1])
    elif op == 'XOR':
        stk.append(stackargs[0] ^ stackargs[1])
    elif op == 'BYTE':
        if stackargs[0] >= 32:
            stk.append(0)
        else:
            stk.append((stackargs[1] / 256 ** stackargs[0]) % 256)
    elif op == 'SHA3':
        if len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + stackargs[1]]))
        stk.append(utils.big_endian_to_int(utils.sha3(data)))
    elif op == 'ADDRESS':
        stk.append(msg.to)
    elif op == 'BALANCE':
        stk.append(block.get_balance(msg.to))
    elif op == 'ORIGIN':
        stk.append(tx.sender)
    elif op == 'CALLER':
        stk.append(utils.coerce_to_int(msg.sender))
    elif op == 'CALLVALUE':
        stk.append(msg.value)
    elif op == 'CALLDATALOAD':
        if stackargs[0] >= len(msg.data):
            stk.append(0)
        else:
            dat = msg.data[stackargs[0]:stackargs[0] + 32]
            stk.append(utils.big_endian_to_int(dat + '\x00' * (32 - len(dat))))
    elif op == 'CALLDATASIZE':
        stk.append(len(msg.data))
    elif op == 'CALLDATACOPY':
        if len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[0] + i < len(msg.data):
                mem[stackargs[1] + i] = ord(msg.data[stackargs[0] + i])
            else:
                mem[stackargs[1] + i] = 0
    elif op == 'GASPRICE':
        stk.append(tx.gasprice)
    elif op == 'CODECOPY':
        if len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[0] + i < len(code):
                mem[stackargs[1] + i] = ord(code[stackargs[0] + i])
            else:
                mem[stackargs[1] + i] = 0
    elif op == 'PREVHASH':
        stk.append(utils.big_endian_to_int(block.prevhash))
    elif op == 'COINBASE':
        stk.append(utils.big_endian_to_int(block.coinbase.decode('hex')))
    elif op == 'TIMESTAMP':
        stk.append(block.timestamp)
    elif op == 'NUMBER':
        stk.append(block.number)
    elif op == 'DIFFICULTY':
        stk.append(block.difficulty)
    elif op == 'GASLIMIT':
        stk.append(block.gaslimit)
    elif op == 'POP':
        pass
    elif op == 'DUP':
        stk.append(stackargs[0])
        stk.append(stackargs[0])
    elif op == 'SWAP':
        stk.append(stackargs[0])
        stk.append(stackargs[1])
    elif op == 'MLOAD':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + 32]))
        stk.append(utils.big_endian_to_int(data))
    elif op == 'MSTORE':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        v = stackargs[1]
        for i in range(31, -1, -1):
            mem[stackargs[0] + i] = v % 256
            v /= 256
    elif op == 'MSTORE8':
        if len(mem) < ceil32(stackargs[0] + 1):
            mem.extend([0] * (ceil32(stackargs[0] + 1) - len(mem)))
        mem[stackargs[0]] = stackargs[1] % 256
    elif op == 'SLOAD':
        stk.append(block.get_storage_data(msg.to, stackargs[0]))
    elif op == 'SSTORE':
        block.set_storage_data(msg.to, stackargs[0], stackargs[1])
    elif op == 'JUMP':
        compustate.pc = stackargs[0]
    elif op == 'JUMPI':
        if stackargs[1]:
            compustate.pc = stackargs[0]
    elif op == 'PC':
        stk.append(compustate.pc)
    elif op == 'MSIZE':
        stk.append(len(mem))
    elif op == 'GAS':
        stk.append(oldgas)
    elif op[:4] == 'PUSH':
        pushnum = int(op[4:])
        compustate.pc = oldpc + 1 + pushnum
        dat = code[oldpc + 1: oldpc + 1 + pushnum]
        stk.append(utils.big_endian_to_int(dat))
    elif op == 'CREATE':
        if len(mem) < ceil32(stackargs[2] + stackargs[3]):
            mem.extend([0] * (ceil32(stackargs[2] + stackargs[3]) - len(mem)))
        gas = stackargs[0]
        value = stackargs[1]
        data = ''.join(map(chr, mem[stackargs[2]:stackargs[2] + stackargs[3]]))
        logger.debug("Sub-contract: %s %s %s %s ", msg.to, value, gas, data)
        addr, gas, code = create_contract(
            block, tx, Message(msg.to, '', value, gas, data))
        logger.debug("Output of contract creation: %s  %s ", addr, code)
        if addr:
            stk.append(utils.coerce_to_int(addr))
        else:
            stk.append(0)
    elif op == 'CALL':
        if len(mem) < ceil32(stackargs[3] + stackargs[4]):
            mem.extend([0] * (ceil32(stackargs[3] + stackargs[4]) - len(mem)))
        if len(mem) < ceil32(stackargs[5] + stackargs[6]):
            mem.extend([0] * (ceil32(stackargs[5] + stackargs[6]) - len(mem)))
        gas = stackargs[0]
        to = utils.encode_int(stackargs[1])
        to = (('\x00' * (32 - len(to))) + to)[12:]
        value = stackargs[2]
        data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]]))
        logger.debug(
            "Sub-call: %s %s %s %s %s ", utils.coerce_addr_to_hex(msg.to),
            utils.coerce_addr_to_hex(to), value, gas, data)
        result, gas, data = apply_msg(
            block, tx, Message(msg.to, to, value, gas, data))
        logger.debug(
            "Output of sub-call: %s %s length %s expected %s", result, data, len(data),
            stackargs[6])
        for i in range(stackargs[6]):
            mem[stackargs[5] + i] = 0
        if result == 0:
            stk.append(0)
        else:
            stk.append(1)
            compustate.gas += gas
            for i in range(len(data)):
                mem[stackargs[5] + i] = data[i]
    elif op == 'RETURN':
        if len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        return mem[stackargs[0]:stackargs[0] + stackargs[1]]
    elif op == 'SUICIDE':
        to = utils.encode_int(stackargs[0])
        to = (('\x00' * (32 - len(to))) + to)[12:]
        block.delta_balance(to, block.get_balance(msg.to))
        block.state.delete(msg.to)
        return []
Exemplo n.º 56
0
 def OP_COINBASE():
     stk.append(utils.big_endian_to_int(block.coinbase.decode('hex')))
Exemplo n.º 57
0
def apply_op(block, tx, msg, code, compustate):
    op, in_args, out_args, mem_grabs, base_gas = opdata = get_op_data(
        code, compustate.pc)
    # empty stack error
    if in_args > len(compustate.stack):
        return []
    # out of gas error
    fee = calcfee(block, tx, msg, compustate, opdata)
    if fee > compustate.gas:
        pblogger.log('OUT OF GAS',
                     needed=fee,
                     available=compustate.gas,
                     op=op,
                     stack=list(reversed(compustate.stack)))
        return OUT_OF_GAS
    stackargs = []
    for i in range(in_args):
        stackargs.append(compustate.stack.pop())

    if pblogger.log_op:
        log_args = dict(pc=compustate.pc,
                        op=op,
                        stackargs=stackargs,
                        gas=compustate.gas)
        if op[:4] == 'PUSH':
            ind = compustate.pc + 1
            log_args['value'] = utils.big_endian_to_int(code[ind:ind +
                                                             int(op[4:])])
        elif op == 'CALLDATACOPY':
            log_args['data'] = msg.data.encode('hex')
        elif op == 'SSTORE':
            log_args['key'] = stackargs[0]
            log_args['value'] = stackargs[1]

        pblogger.log('OP', **log_args)

    if pblogger.log_memory:
        for i in range(0, len(compustate.memory), 16):
            memblk = compustate.memory[i:i + 16]
            memline = ' '.join([chr(x).encode('hex') for x in memblk])
            pblogger.log('MEM', mem=memline)

    # Apply operation
    oldpc = compustate.pc
    compustate.gas -= fee
    compustate.pc += 1
    stk = compustate.stack
    mem = compustate.memory
    if op == 'STOP' or op == 'INVALID':
        return []
    elif op == 'ADD':
        stk.append((stackargs[0] + stackargs[1]) % 2**256)
    elif op == 'SUB':
        stk.append((stackargs[0] - stackargs[1]) % 2**256)
    elif op == 'MUL':
        stk.append((stackargs[0] * stackargs[1]) % 2**256)
    elif op == 'DIV':
        stk.append(0 if stackargs[1] == 0 else stackargs[0] / stackargs[1])
    elif op == 'MOD':
        stk.append(0 if stackargs[1] == 0 else stackargs[0] % stackargs[1])
    elif op == 'SDIV':
        if stackargs[0] >= 2**255:
            stackargs[0] -= 2**256
        if stackargs[1] >= 2**255:
            stackargs[1] -= 2**256
        stk.append(0 if stackargs[1] == 0 else (stackargs[0] / stackargs[1]) %
                   2**256)
    elif op == 'SMOD':
        if stackargs[0] >= 2**255:
            stackargs[0] -= 2**256
        if stackargs[1] >= 2**255:
            stackargs[1] -= 2**256
        stk.append(0 if stackargs[1] == 0 else (stackargs[0] % stackargs[1]) %
                   2**256)
    elif op == 'EXP':
        stk.append(pow(stackargs[0], stackargs[1], 2**256))
    elif op == 'NEG':
        stk.append(-stackargs[0] % 2**256)
    elif op == 'LT':
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'GT':
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'SLT':
        if stackargs[0] >= 2**255:
            stackargs[0] -= 2**256
        if stackargs[1] >= 2**255:
            stackargs[1] -= 2**256
        stk.append(1 if stackargs[0] < stackargs[1] else 0)
    elif op == 'SGT':
        if stackargs[0] >= 2**255:
            stackargs[0] -= 2**256
        if stackargs[1] >= 2**255:
            stackargs[1] -= 2**256
        stk.append(1 if stackargs[0] > stackargs[1] else 0)
    elif op == 'EQ':
        stk.append(1 if stackargs[0] == stackargs[1] else 0)
    elif op == 'NOT':
        stk.append(0 if stackargs[0] else 1)
    elif op == 'AND':
        stk.append(stackargs[0] & stackargs[1])
    elif op == 'OR':
        stk.append(stackargs[0] | stackargs[1])
    elif op == 'XOR':
        stk.append(stackargs[0] ^ stackargs[1])
    elif op == 'BYTE':
        if stackargs[0] >= 32:
            stk.append(0)
        else:
            stk.append((stackargs[1] / 256**(31 - stackargs[0])) % 256)
    elif op == 'ADDMOD':
        stk.append((stackargs[2] + stackargs[1]) % stackargs[0])
    elif op == 'MULMOD':
        stk.append((stackargs[2] * stackargs[1]) % stackargs[0])
    elif op == 'SHA3':
        if len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + stackargs[1]]))
        stk.append(utils.big_endian_to_int(utils.sha3(data)))
    elif op == 'ADDRESS':
        stk.append(utils.coerce_to_int(msg.to))
    elif op == 'BALANCE':
        stk.append(block.get_balance(utils.coerce_addr_to_hex(stackargs[0])))
    elif op == 'ORIGIN':
        stk.append(utils.coerce_to_int(tx.sender))
    elif op == 'CALLER':
        stk.append(utils.coerce_to_int(msg.sender))
    elif op == 'CALLVALUE':
        stk.append(msg.value)
    elif op == 'CALLDATALOAD':
        if stackargs[0] >= len(msg.data):
            stk.append(0)
        else:
            dat = msg.data[stackargs[0]:stackargs[0] + 32]
            stk.append(utils.big_endian_to_int(dat + '\x00' * (32 - len(dat))))
    elif op == 'CALLDATASIZE':
        stk.append(len(msg.data))
    elif op == 'CALLDATACOPY':
        if len(mem) < ceil32(stackargs[0] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[1] + i < len(msg.data):
                mem[stackargs[0] + i] = ord(msg.data[stackargs[1] + i])
            else:
                mem[stackargs[0] + i] = 0
    elif op == 'GASPRICE':
        stk.append(tx.gasprice)
    elif op == 'CODECOPY':
        if len(mem) < ceil32(stackargs[0] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[2]) - len(mem)))
        for i in range(stackargs[2]):
            if stackargs[1] + i < len(code):
                mem[stackargs[0] + i] = ord(code[stackargs[1] + i])
            else:
                mem[stackargs[0] + i] = 0
    elif op == 'PREVHASH':
        stk.append(utils.big_endian_to_int(block.prevhash))
    elif op == 'COINBASE':
        stk.append(utils.big_endian_to_int(block.coinbase.decode('hex')))
    elif op == 'TIMESTAMP':
        stk.append(block.timestamp)
    elif op == 'NUMBER':
        stk.append(block.number)
    elif op == 'DIFFICULTY':
        stk.append(block.difficulty)
    elif op == 'GASLIMIT':
        stk.append(block.gas_limit)
    elif op == 'POP':
        pass
    elif op == 'DUP':
        # DUP POP POP Debug hint
        if get_op_data(code, oldpc + 1)[0] == 'POP' and \
           get_op_data(code, oldpc + 2)[0] == 'POP':
            compustate.pc = oldpc + 3
        else:
            stk.append(stackargs[0])
            stk.append(stackargs[0])
    elif op == 'SWAP':
        stk.append(stackargs[0])
        stk.append(stackargs[1])
    elif op == 'MLOAD':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        data = ''.join(map(chr, mem[stackargs[0]:stackargs[0] + 32]))
        stk.append(utils.big_endian_to_int(data))
    elif op == 'MSTORE':
        if len(mem) < ceil32(stackargs[0] + 32):
            mem.extend([0] * (ceil32(stackargs[0] + 32) - len(mem)))
        v = stackargs[1]
        for i in range(31, -1, -1):
            mem[stackargs[0] + i] = v % 256
            v /= 256
    elif op == 'MSTORE8':
        if len(mem) < ceil32(stackargs[0] + 1):
            mem.extend([0] * (ceil32(stackargs[0] + 1) - len(mem)))
        mem[stackargs[0]] = stackargs[1] % 256
    elif op == 'SLOAD':
        stk.append(block.get_storage_data(msg.to, stackargs[0]))
    elif op == 'SSTORE':
        block.set_storage_data(msg.to, stackargs[0], stackargs[1])
    elif op == 'JUMP':
        compustate.pc = stackargs[0]
    elif op == 'JUMPI':
        if stackargs[1]:
            compustate.pc = stackargs[0]
    elif op == 'PC':
        stk.append(compustate.pc)
    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 = oldpc + 1 + pushnum
        dat = code[oldpc + 1:oldpc + 1 + pushnum]
        stk.append(utils.big_endian_to_int(dat))
    elif op[:4] == 'DUP':
        dupnum = int(op[4:]) - 1
        stk.extend(reversed(stackargs))
        stk.append(stackargs[dupnum])
    elif op[:4] == 'SWAP':
        swapnum = int(op[4:])
        stk.append(stackargs[0])
        stk.extend(reversed(stackargs[1:-1]))
        stk.append(stackargs[-1])
    elif op == 'CREATE':
        if len(mem) < ceil32(stackargs[1] + stackargs[2]):
            mem.extend([0] * (ceil32(stackargs[1] + stackargs[2]) - len(mem)))
        value = stackargs[0]
        data = ''.join(map(chr, mem[stackargs[1]:stackargs[1] + stackargs[2]]))
        pblogger.log('SUB CONTRACT NEW',
                     sender=msg.to,
                     value=value,
                     data=data.encode('hex'))
        create_msg = Message(msg.to, '', value, compustate.gas, data)
        addr, gas, code = create_contract(block, tx, create_msg)
        pblogger.log('SUB CONTRACT OUT', address=addr, code=code)
        if addr:
            stk.append(addr)
            compustate.gas = gas
        else:
            stk.append(0)
            compustate.gas = 0
    elif op == 'CALL':
        if len(mem) < ceil32(stackargs[3] + stackargs[4]):
            mem.extend([0] * (ceil32(stackargs[3] + stackargs[4]) - len(mem)))
        if len(mem) < ceil32(stackargs[5] + stackargs[6]):
            mem.extend([0] * (ceil32(stackargs[5] + stackargs[6]) - len(mem)))
        gas = stackargs[0]
        to = utils.encode_int(stackargs[1])
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        value = stackargs[2]
        data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]]))
        pblogger.log('SUB CALL NEW',
                     sender=msg.to,
                     to=to,
                     value=value,
                     gas=gas,
                     data=data.encode('hex'))
        call_msg = Message(msg.to, to, value, gas, data)
        result, gas, data = apply_msg_send(block, tx, call_msg)
        pblogger.log('SUB CALL OUT',
                     result=result,
                     data=data,
                     length=len(data),
                     expected=stackargs[6])
        if result == 0:
            stk.append(0)
        else:
            stk.append(1)
            compustate.gas += gas
            for i in range(min(len(data), stackargs[6])):
                mem[stackargs[5] + i] = data[i]
    elif op == 'RETURN':
        if len(mem) < ceil32(stackargs[0] + stackargs[1]):
            mem.extend([0] * (ceil32(stackargs[0] + stackargs[1]) - len(mem)))
        return mem[stackargs[0]:stackargs[0] + stackargs[1]]
    elif op == 'POST':
        if len(mem) < ceil32(stackargs[3] + stackargs[4]):
            mem.extend([0] * (ceil32(stackargs[3] + stackargs[4]) - len(mem)))
        gas = stackargs[0]
        to = utils.encode_int(stackargs[1])
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        value = stackargs[2]
        data = ''.join(map(chr, mem[stackargs[3]:stackargs[3] + stackargs[4]]))
        pblogger.log('POST NEW',
                     sender=msg.to,
                     to=to,
                     value=value,
                     gas=gas,
                     data=data.encode('hex'))
        post_msg = Message(msg.to, to, vaue, gas, data)
        block.postqueue.append(post_msg)
    elif op == 'SUICIDE':
        to = utils.encode_int(stackargs[0])
        to = (('\x00' * (32 - len(to))) + to)[12:].encode('hex')
        block.transfer_value(msg.to, to, block.get_balance(msg.to))
        block.suicides.append(msg.to)
        return []
    for a in stk:
        assert isinstance(a, (int, long))