Example #1
0
def mk_transaction_spv_proof(block, tx):
    trie.proof.push(trie.RECORDING)
    processblock.apply_transaction(block, tx)
    o = trie.proof.get_nodelist()
    trie.proof.pop()
    o2 = list(map(rlp.decode, list(set(map(rlp.encode, o)))))
    return o2
Example #2
0
def mk_transaction_spv_proof(block, tx):
    trie.proof.push(trie.RECORDING)
    processblock.apply_transaction(block, tx)
    o = trie.proof.get_nodelist()
    trie.proof.pop()
    o2 = list(map(rlp.decode, list(set(map(rlp.encode, o)))))
    return o2
Example #3
0
def test_call(block, sender, to, data='', gasprice=0, value=0):
    state_root_before = block.state_root
    assert block.has_parent()
    # rebuild block state before finalization
    parent = block.get_parent()
    test_block = block.init_from_parent(parent,
                                        block.coinbase,
                                        timestamp=block.timestamp)
    for _tx in block.get_transactions():
        success, output = processblock.apply_transaction(test_block, _tx)
        assert success
    # apply transaction
    startgas = block.gas_limit - block.gas_used
    gasprice = 0
    nonce = test_block.get_nonce(sender)
    tx = Transaction(nonce, gasprice, startgas, to, value, data)
    tx.sender = sender

    try:
        success, output = processblock.apply_transaction(test_block, tx)
    except processblock.InvalidTransaction as e:
        success = False
    assert block.state_root == state_root_before
    if success:
        return output
    else:
        log.debug('test_call failed', error=e)
        return None
Example #4
0
            def call(this, to, value=0, data='',  sender=None,
                     startgas=25000, gasprice=10*denoms.szabo):
                sender = address20(sender or this.coinbase)
                to = address20(to)
                block = this.head_candidate
                state_root_before = block.state_root
                assert block.has_parent()
                # rebuild block state before finalization
                parent = block.get_parent()
                test_block = block.init_from_parent(parent, block.coinbase,
                                                    timestamp=block.timestamp)
                for tx in block.get_transactions():
                    success, output = processblock.apply_transaction(test_block, tx)
                    assert success

                # apply transaction
                nonce = test_block.get_nonce(sender)
                tx = Transaction(nonce, gasprice, startgas, to, value, data)
                tx.sender = sender
                try:
                    success, output = processblock.apply_transaction(test_block, tx)
                except processblock.InvalidTransaction as e:
                    success = False
                assert block.state_root == state_root_before
                if success:
                    return output
                else:
                    return False
Example #5
0
            def call(this, to, value=0, data='', sender=None,
                     startgas=25000, gasprice=60 * denoms.shannon):
                sender = normalize_address(sender or this.coinbase)
                to = normalize_address(to, allow_blank=True)
                block = this.head_candidate
                state_root_before = block.state_root
                assert block.has_parent()
                # rebuild block state before finalization
                parent = block.get_parent()
                test_block = block.init_from_parent(parent, block.coinbase,
                                                    timestamp=block.timestamp)
                for tx in block.get_transactions():
                    success, output = processblock.apply_transaction(test_block, tx)
                    assert success

                # apply transaction
                nonce = test_block.get_nonce(sender)
                tx = Transaction(nonce, gasprice, startgas, to, value, data)
                tx.sender = sender

                try:
                    success, output = processblock.apply_transaction(test_block, tx)
                except InvalidTransaction:
                    success = False

                assert block.state_root == state_root_before

                if success:
                    return output
                else:
                    return False
Example #6
0
def test_call(block, sender, to, data='', gasprice=0, value=0):
    state_root_before = block.state_root
    assert block.has_parent()
    # rebuild block state before finalization
    parent = block.get_parent()
    test_block = block.init_from_parent(parent, block.coinbase,
                                        timestamp=block.timestamp)
    for _tx in block.get_transactions():
        success, output = processblock.apply_transaction(test_block, _tx)
        assert success
    # apply transaction
    startgas = block.gas_limit - block.gas_used
    gasprice = 0
    nonce = test_block.get_nonce(sender)
    tx = Transaction(nonce, gasprice, startgas, to, value, data)
    tx.sender = sender

    try:
        success, output = processblock.apply_transaction(test_block, tx)
    except processblock.InvalidTransaction as e:
        success = False
    assert block.state_root == state_root_before
    if success:
        return output
    else:
        log.debug('test_call failed', error=e)
        return None
Example #7
0
    def call(self, data, block_id=None):
        block = self.json_rpc_server.get_block(block_id)
        state_root_before = block.state_root

        # rebuild block state before finalization
        if block.has_parent():
            parent = block.get_parent()
            test_block = block.init_from_parent(parent, block.coinbase,
                                                timestamp=block.timestamp)
            for tx in block.get_transactions():
                success, output = processblock.apply_transaction(test_block, tx)
                assert success
        else:
            original = block.snapshot()
            original['journal'] = deepcopy(original['journal'])  # do not alter original journal
            test_block = ethereum.blocks.genesis(block.db)
            test_block.revert(original)

        # validate transaction
        if not isinstance(data, dict):
            raise BadRequestError('Transaction must be an object')
        to = address_decoder(data['to'])
        try:
            startgas = quantity_decoder(data['gas'])
        except KeyError:
            startgas = block.gas_limit - block.gas_used
        try:
            gasprice = quantity_decoder(data['gasPrice'])
        except KeyError:
            gasprice = 0
        try:
            value = quantity_decoder(data['value'])
        except KeyError:
            value = 0
        try:
            data_ = data_decoder(data['data'])
        except KeyError:
            data_ = b''
        try:
            sender = address_decoder(data['from'])
        except KeyError:
            sender = '\x00' * 20

        # apply transaction
        nonce = test_block.get_nonce(sender)
        tx = Transaction(nonce, gasprice, startgas, to, value, data_)
        tx.sender = sender

        try:
            success, output = processblock.apply_transaction(test_block, tx)
        except processblock.InvalidTransaction as e:
            success = False
        assert block.state_root == state_root_before

        if success:
            return output
        else:
            return False
Example #8
0
def verify_transaction_spv_proof(block, tx, proof):
    trie.proof.push(trie.VERIFYING, proof)
    try:
        processblock.apply_transaction(block, tx)
        trie.proof.pop()
        return True
    except Exception as e:
        print(e)
        trie.proof.pop()
        return False
Example #9
0
def verify_transaction_spv_proof(block, tx, proof):
    trie.proof.push(trie.VERIFYING, proof)
    try:
        processblock.apply_transaction(block, tx)
        trie.proof.pop()
        return True
    except Exception as e:
        print(e)
        trie.proof.pop()
        return False
Example #10
0
    def call(self, data, block_id=None):
        block = self.json_rpc_server.get_block(block_id)
        state_root_before = block.state_root

        # rebuild block state before finalization
        if block.has_parent():
            parent = block.get_parent()
            test_block = block.init_from_parent(parent, block.coinbase,
                                                timestamp=block.timestamp)
            for tx in block.get_transactions():
                success, output = processblock.apply_transaction(test_block, tx)
                assert success
        else:
            original = block.snapshot()
            original['journal'] = deepcopy(original['journal'])  # do not alter original journal
            test_block = ethereum.blocks.genesis(block.db)
            test_block.revert(original)

        # validate transaction
        if not isinstance(data, dict):
            raise BadRequestError('Transaction must be an object')
        to = address_decoder(data['to'])
        try:
            startgas = quantity_decoder(data['gas'])
        except KeyError:
            startgas = block.gas_limit - block.gas_used
        try:
            gasprice = quantity_decoder(data['gasPrice'])
        except KeyError:
            gasprice = 0
        try:
            value = quantity_decoder(data['value'])
        except KeyError:
            value = 0
        try:
            data_ = data_decoder(data['data'])
        except KeyError:
            data_ = b''
        try:
            sender = address_decoder(data['from'])
        except KeyError:
            sender = '\x00' * 20
        # apply transaction
        nonce = test_block.get_nonce(sender)
        tx = Transaction(nonce, gasprice, startgas, to, value, data_)
        tx.sender = sender
        try:
            success, output = processblock.apply_transaction(test_block, tx)
        except processblock.InvalidTransaction:
            success = False
        assert block.state_root == state_root_before
        if success:
            return output
        else:
            return False
Example #11
0
    def _get_trace(self, txhash):
        try:  # index
            test_blk, tx, i = self._get_block_before_tx(txhash)
        except (KeyError, TypeError):
            raise Exception('Unknown Transaction  %s' % txhash)

        # collect debug output FIXME set loglevel trace???
        recorder = LogRecorder()
        # apply tx (thread? we don't want logs from other invocations)
        self.app.services.chain.add_transaction_lock.acquire()
        processblock.apply_transaction(test_blk, tx)  # FIXME deactivate tx context switch or lock
        self.app.services.chain.add_transaction_lock.release()
        return dict(tx=txhash, trace=recorder.pop_records())
Example #12
0
    def _get_trace(self, txhash):
        try:  # index
            test_blk, tx, i = self._get_block_before_tx(txhash)
        except (KeyError, TypeError):
            raise Exception('Unknown Transaction  %s' % txhash)

        # collect debug output FIXME set loglevel trace???
        recorder = LogRecorder()
        # apply tx (thread? we don't want logs from other invocations)
        self.app.services.chain.add_transaction_lock.acquire()
        processblock.apply_transaction(
            test_blk, tx)  # FIXME deactivate tx context switch or lock
        self.app.services.chain.add_transaction_lock.release()
        return dict(tx=txhash, trace=recorder.pop_records())
Example #13
0
    def deliver(self, enc_num, to):
        # nonce = number of transactions already sent by that account
        head = self.app.services.chain.chain.head
        nonce = head.get_nonce(self.my_addr)

        # Took from buterin example:
        # https://blog.ethereum.org/2014/04/10/pyethereum-and-serpent-programming-guide/
        gasprice = 10**12

        # Took from buterin example:
        # https://blog.ethereum.org/2014/04/10/pyethereum-and-serpent-programming-guide/
        startgas = 10000
        value = 0  # It's just a message, don't need to send any value (TODO: confirm that info)

        # data is a json formatted message but has to be 'binary'
        unix_now = int(round(time()))
        payload = {}
        payload['when'] = unix_now
        payload['number'] = enc_num
        payload['publish_on'] = unix_now + 86400  # in 24 hours
        payload['published_at'] = 'http://www.example.com/foo'
        data = json.dumps(payload)

        deliver_tx = Transaction(nonce, gasprice, startgas, to, value, data)
        signed_deliver_tx = deliver_tx.sign(self.privkey_hex)
        success, output = apply_transaction(head, signed_deliver_tx)
Example #14
0
    def deliver(self, enc_num, to):
        # nonce = number of transactions already sent by that account
        head = self.app.services.chain.chain.head
        nonce = head.get_nonce(self.my_addr)

        # Took from buterin example:
        # https://blog.ethereum.org/2014/04/10/pyethereum-and-serpent-programming-guide/
        gasprice = 10**12

        # Took from buterin example:
        # https://blog.ethereum.org/2014/04/10/pyethereum-and-serpent-programming-guide/
        startgas = 10000
        value = 0  # It's just a message, don't need to send any value (TODO: confirm that info)

        # data is a json formatted message but has to be 'binary'
        unix_now = int(round(time()))
        payload = {}
        payload['when'] = unix_now
        payload['number'] = enc_num
        payload['publish_on'] = unix_now + 86400  # in 24 hours
        payload['published_at'] = 'http://www.example.com/foo'
        data = json.dumps(payload)

        deliver_tx = Transaction(nonce, gasprice, startgas, to, value, data)
        signed_deliver_tx = deliver_tx.sign(self.privkey_hex)
        success, output = apply_transaction(head, signed_deliver_tx)
Example #15
0
    def call(self, data, block_id=None):
        block = self.json_rpc_server.get_block(block_id)
        # rebuild block state before finalization
        parent = block.get_parent()
        test_block = block.init_from_parent(parent, block.coinbase,
                                            timestamp=block.timestamp)
        for tx in block.get_transactions():
            success, output = processblock.apply_transaction(test_block, tx)
            assert success

        # validate transaction
        if not isinstance(data, dict):
            raise BadRequestError('Transaction must be an object')
        to = address_decoder(data['to'])
        try:
            startgas = quantity_decoder(data['gas'])
        except KeyError:
            startgas = block.gas_limit - block.gas_used
        try:
            gasprice = quantity_decoder(data['gasPrice'])
        except KeyError:
            gasprice = 0
        try:
            value = quantity_decoder(data['value'])
        except KeyError:
            value = 0
        try:
            data_ = data_decoder(data['data'])
        except KeyError:
            data_ = b''
        try:
            sender = address_decoder(data['from'])
        except KeyError:
            sender = '\x00' * 20
        # initialize transaction
        nonce = block.get_nonce(sender)
        tx = Transaction(nonce, gasprice, startgas, to, value, data_)
        tx.sender = sender
        # apply transaction
        try:
            success, output = processblock.apply_transaction(test_block, tx)
        except processblock.InvalidTransaction:
            success = False
        if success:
            return output
        else:
            return False
Example #16
0
def test_transaction(db):
    k, v, k2, v2 = accounts()
    blk = mkquickgenesis({v: {"balance": utils.denoms.ether * 1}}, db=db)
    store_block(blk)
    blk = mine_next_block(blk)
    tx = get_transaction()
    assert tx not in blk.get_transactions()
    success, res = processblock.apply_transaction(blk, tx)
    assert tx in blk.get_transactions()
    assert blk.get_balance(v) == utils.denoms.finney * 990
    assert blk.get_balance(v2) == utils.denoms.finney * 10
Example #17
0
def test_transaction(db):
    k, v, k2, v2 = accounts()
    blk = mkquickgenesis({v: {"balance": utils.denoms.ether * 1}}, db=db)
    store_block(blk)
    blk = mine_next_block(blk)
    tx = get_transaction()
    assert tx not in blk.get_transactions()
    success, res = processblock.apply_transaction(blk, tx)
    assert tx in blk.get_transactions()
    assert blk.get_balance(v) == utils.denoms.finney * 990
    assert blk.get_balance(v2) == utils.denoms.finney * 10
Example #18
0
 def send_raw_transaction(self, raw_transaction):
     from ethereum import (
         processblock,
         tester,
     )
     from ethereum.transactions import Transaction
     rlp_transaction = rlp.decode(raw_transaction, Transaction)
     # Manipulate `tester.state` directly
     success, _ = processblock.apply_transaction(self.evm.block, rlp_transaction)
     if not success:
         raise tester.TransactionFailed
     self.evm.last_tx = rlp_transaction
     return rlp_transaction.hash
Example #19
0
    def evm(self, code, sender=DEFAULT_KEY, endowment=0, gas=None):
        sendnonce = self.block.get_nonce(privtoaddr(sender))

        transaction = transactions.contract(sendnonce, gas_price, gas_limit, endowment, code)
        transaction.sign(sender)

        if gas is not None:
            transaction.startgas = gas

        (success, output) = processblock.apply_transaction(self.block, transaction)

        if not success:
            raise ContractCreationFailed()

        return output
Example #20
0
    def evm(self, code, sender=DEFAULT_KEY, endowment=0, gas=None):
        sendnonce = self.block.get_nonce(privtoaddr(sender))

        transaction = transactions.contract(sendnonce, gas_price, gas_limit,
                                            endowment, code)
        transaction.sign(sender)

        if gas is not None:
            transaction.startgas = gas

        (success,
         output) = processblock.apply_transaction(self.block, transaction)

        if not success:
            raise ContractCreationFailed()

        return output
 def call(_from, to, data, **kw):
     # pyethereum does not have direct support for non-mutating calls.
     # The implemenation just copies the state and discards it after.
     # Here we apply real transaction, but with gas price 0.
     # We assume the transaction does not modify the state, but nonce
     # will be bumped no matter what.
     _from = _from[2:].decode('hex')
     data = data[2:].decode('hex')
     nonce = self.state.block.get_nonce(_from)
     value = kw.get('value', 0)
     tx = Transaction(nonce, 0, 100000, to, value, data)
     assert _from == tester.a1
     tx.sign(tester.k1)
     block = kw['block']
     assert block == 'pending'
     success, output = apply_transaction(self.state.block, tx)
     assert success
     return '0x' + output.encode('hex')
Example #22
0
    def add_transaction(self, transaction):
        """Add a transaction to the :attr:`head_candidate` block.

        If the transaction is invalid, the block will not be changed.

        :returns: `True` is the transaction was successfully added or `False`
                  if the transaction was invalid
        """
        assert self.head_candidate is not None
        head_candidate = self.head_candidate
        log.debug('add tx',
                  num_txs=self.num_transactions(),
                  tx=transaction,
                  on=head_candidate)
        if self.head_candidate.includes_transaction(transaction.hash):
            log.debug('known tx')
            return
        old_state_root = head_candidate.state_root
        # revert finalization
        head_candidate.state_root = self.pre_finalize_state_root
        try:
            success, output = processblock.apply_transaction(
                head_candidate, transaction)
        except InvalidTransaction as e:
            # if unsuccessful the prerequisites were not fullfilled
            # and the tx is invalid, state must not have changed
            log.debug('invalid tx', error=e)
            head_candidate.state_root = old_state_root  # reset
            return False

        log.debug('valid tx')

        # we might have a new head_candidate (due to ctx switches in pyethapp)
        if self.head_candidate != head_candidate:
            log.debug('head_candidate changed during validation, trying again')
            return self.add_transaction(transaction)

        self.pre_finalize_state_root = head_candidate.state_root
        head_candidate.finalize()
        log.debug('tx applied', result=output)
        assert old_state_root != head_candidate.state_root
        return True
Example #23
0
    def add_transaction(self, transaction):
        """Add a transaction to the :attr:`head_candidate` block.

        If the transaction is invalid, the block will not be changed.

        :returns: `True` is the transaction was successfully added or `False`
                  if the transaction was invalid
        """
        assert self.head_candidate is not None
        if self.head_candidate.number < 40000:
            return
        head_candidate = self.head_candidate
        log.debug('add tx', num_txs=self.num_transactions(), tx=transaction, on=head_candidate)
        if self.head_candidate.includes_transaction(transaction.hash):
            log.debug('known tx')
            return
        old_state_root = head_candidate.state_root
        # revert finalization
        head_candidate.state_root = self.pre_finalize_state_root
        try:
            success, output = processblock.apply_transaction(head_candidate, transaction)
        except processblock.InvalidTransaction as e:
            # if unsuccessful the prerequisites were not fullfilled
            # and the tx is invalid, state must not have changed
            log.debug('invalid tx', error=e)
            head_candidate.state_root = old_state_root  # reset
            return False

        log.debug('valid tx')

        # we might have a new head_candidate (due to ctx switches in pyethapp)
        if self.head_candidate != head_candidate:
            log.debug('head_candidate changed during validation, trying again')
            self.add_transaction(transaction)
            return

        self.pre_finalize_state_root = head_candidate.state_root
        head_candidate.finalize()
        log.debug('tx applied', result=output)
        assert old_state_root != head_candidate.state_root
        return True
Example #24
0
def eth_sendRawTransaction(raw_tx):
    global evm
    global transaction_contract_addresses

    print('eth_sendRawTransaction')

    # Get a transaction object from the raw hash.
    tx = rlp.decode(decode_hex(strip_0x(raw_tx)), transactions.Transaction)

    print("")
    print("Raw Transaction Details:")
    print("  ")
    print("  From:     " + "0x" + encode_hex(tx.sender))
    print("  To:       " + "0x" + encode_hex(tx.to))
    print("  Gas:      " + int_to_hex(tx.startgas))
    print("  GasPrice: " + int_to_hex(tx.gasprice))
    print("  Value:    " + int_to_hex(tx.value))
    print("  Data:     " + "0x" + encode_hex(tx.data))
    print("")

    (s, r) = processblock.apply_transaction(evm.block, tx)

    if not s:
        raise Exception("Transaction failed")

    if isContract(tx):
        contract_address = r
    else:
        contract_address = None

    tx_hash = "0x" + encode_hex(tx.hash)

    if contract_address != None:
        transaction_contract_addresses[tx_hash] = contract_address

    mine(evm)
    return tx_hash
Example #25
0
def eth_sendRawTransaction(raw_tx):
    global evm
    global transaction_contract_addresses

    print 'eth_sendRawTransaction'

    # Get a transaction object from the raw hash.
    tx = rlp.decode(strip_0x(raw_tx).decode("hex"), transactions.Transaction)

    print ""
    print "Raw Transaction Details:"
    print "  "
    print "  From:     " + "0x" + tx.sender.encode("hex")
    print "  To:       " + "0x" + tx.to.encode("hex")
    print "  Gas:      " + int_to_hex(tx.startgas)
    print "  GasPrice: " + int_to_hex(tx.gasprice)
    print "  Value:    " + int_to_hex(tx.value)
    print "  Data:     " + "0x" + tx.data.encode("hex")
    print ""

    (s, r) = processblock.apply_transaction(evm.block, tx)

    if not s:
        raise Exception("Transaction failed")

    if isContract(tx):
        contract_address = r
    else:
        contract_address = None

    tx_hash = "0x" + tx.hash.encode("hex")

    if contract_address != None:
        transaction_contract_addresses[tx_hash] = contract_address

    evm.mine()
    return tx_hash
Example #26
0
def eth_sendRawTransaction(raw_tx):
    global evm
    global transaction_contract_addresses

    print 'eth_sendRawTransaction'

    # Get a transaction object from the raw hash.
    tx = rlp.decode(strip_0x(raw_tx).decode("hex"), transactions.Transaction)

    print ""
    print "Raw Transaction Details:"
    print "  "
    print "  From:     " + "0x" + tx.sender.encode("hex")
    print "  To:       " + "0x" + tx.to.encode("hex")
    print "  Gas:      " + int_to_hex(tx.startgas)
    print "  GasPrice: " + int_to_hex(tx.gasprice)
    print "  Value:    " + int_to_hex(tx.value)
    print "  Data:     " + "0x" + tx.data.encode("hex")
    print ""

    (s, r) = processblock.apply_transaction(evm.block, tx)

    if not s:
        raise Exception("Transaction failed")

    if isContract(tx):
        contract_address = r
    else:
        contract_address = None

    tx_hash = "0x" + tx.hash.encode("hex")

    if contract_address != None:
        transaction_contract_addresses[tx_hash] = contract_address

    evm.mine()
    return tx_hash
Example #27
0
def run_state_test(params, mode):
    pre = params['pre']
    exek = params['transaction']
    env = params['env']

    assert set(env.keys()) == set([
        'currentGasLimit', 'currentTimestamp', 'previousHash',
        'currentCoinbase', 'currentDifficulty', 'currentNumber'
    ])
    assert len(env['currentCoinbase']) == 40

    # setup env
    header = blocks.BlockHeader(
        prevhash=decode_hex(env['previousHash']),
        number=parse_int_or_hex(env['currentNumber']),
        coinbase=decode_hex(env['currentCoinbase']),
        difficulty=parse_int_or_hex(env['currentDifficulty']),
        gas_limit=parse_int_or_hex(env['currentGasLimit']),
        timestamp=parse_int_or_hex(env['currentTimestamp']))
    blk = blocks.Block(header, env=db_env)

    # setup state
    for address, h in list(pre.items()):
        assert len(address) == 40
        address = decode_hex(address)
        assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage'])
        blk.set_nonce(address, parse_int_or_hex(h['nonce']))
        blk.set_balance(address, parse_int_or_hex(h['balance']))
        blk.set_code(address, decode_hex(h['code'][2:]))
        for k, v in h['storage'].items():
            blk.set_storage_data(address,
                                 utils.big_endian_to_int(decode_hex(k[2:])),
                                 utils.big_endian_to_int(decode_hex(v[2:])))

    for address, h in list(pre.items()):
        address = decode_hex(address)
        assert blk.get_nonce(address) == parse_int_or_hex(h['nonce'])
        assert blk.get_balance(address) == parse_int_or_hex(h['balance'])
        assert blk.get_code(address) == decode_hex(h['code'][2:])
        for k, v in h['storage'].items():
            assert blk.get_storage_data(
                address, utils.big_endian_to_int(decode_hex(
                    k[2:]))) == utils.big_endian_to_int(decode_hex(v[2:]))

    # execute transactions
    orig_apply_msg = pb.apply_msg

    def apply_msg_wrapper(ext, msg):
        def blkhash(n):
            if n >= blk.number or n < blk.number - 256:
                return b''
            else:
                return utils.sha3(to_string(n))

        ext.block_hash = blkhash
        return orig_apply_msg(ext, msg)

    pb.apply_msg = apply_msg_wrapper

    try:
        tx = transactions.Transaction(
            nonce=parse_int_or_hex(exek['nonce'] or b"0"),
            gasprice=parse_int_or_hex(exek['gasPrice'] or b"0"),
            startgas=parse_int_or_hex(exek['gasLimit'] or b"0"),
            to=decode_hex(exek['to'][2:] if exek['to'][:2] ==
                          b'0x' else exek['to']),
            value=parse_int_or_hex(exek['value'] or b"0"),
            data=decode_hex(remove_0x_head(exek['data'])))
    except InvalidTransaction:
        tx = None
        success, output = False, b''
        time_pre = time.time()
        time_post = time_pre
    else:
        if 'secretKey' in exek:
            tx.sign(exek['secretKey'])
        elif all(key in exek for key in ['v', 'r', 's']):
            tx.v = decode_hex(remove_0x_head(exek['v']))
            tx.r = decode_hex(remove_0x_head(exek['r']))
            tx.s = decode_hex(remove_0x_head(exek['s']))
        else:
            assert False

        time_pre = time.time()
        try:
            success, output = pb.apply_transaction(blk, tx)
            blk.commit_state()
        except pb.InvalidTransaction:
            success, output = False, b''
            blk.commit_state()
            pass
        time_post = time.time()

        if tx.to == b'':
            output = blk.get_code(output)

    pb.apply_msg = orig_apply_msg

    params2 = copy.deepcopy(params)
    if success:
        params2['logs'] = [log.to_dict() for log in blk.get_receipt(0).logs]

    params2['out'] = b'0x' + encode_hex(output)
    params2['post'] = copy.deepcopy(blk.to_dict(True)['state'])
    params2['postStateRoot'] = encode_hex(blk.state.root_hash)
    assert 'post' in params  # we always have a post state in the tests

    if mode == FILL:
        return params2
    elif mode == VERIFY:
        params1 = copy.deepcopy(params)
        shouldbe, reallyis = params1.get('post',
                                         None), params2.get('post', None)
        compare_post_states(shouldbe, reallyis)
        for k in [
                'pre', 'exec', 'env', 'callcreates', 'out', 'gas', 'logs',
                'postStateRoot'
        ]:
            shouldbe = params1.get(k, None)
            reallyis = params2.get(k, None)
            if shouldbe != reallyis:
                raise Exception("Mismatch: " + k +
                                ':\n shouldbe %r\n reallyis %r' %
                                (shouldbe, reallyis))

    elif mode == TIME:
        return time_post - time_pre
Example #28
0
    def _send(self, sender, to, value, evmdata='', funid=None, abi=None,  # pylint: disable=too-many-arguments
              profiling=0):
        # pylint: disable=too-many-locals

        if funid is not None or abi is not None:
            raise Exception(
                'Send with funid+abi is deprecated. Please use the abi_contract mechanism'
            )

        start_time = time.time()
        gas_used = self.block.gas_used

        sendnonce = self.block.get_nonce(privtoaddr(sender))
        transaction = transactions.Transaction(sendnonce, gas_price, gas_limit, to, value, evmdata)
        self.last_tx = transaction
        transaction.sign(sender)
        recorder = None

        if profiling > 1:
            recorder = LogRecorder(
                disable_other_handlers=True,
                log_config=TRACE_LVL_MAP[3],
            )

        try:
            (success, output) = processblock.apply_transaction(self.block, transaction)

            if not success:
                raise TransactionFailed()

            out = {
                'output': output,
            }

            if profiling > 0:
                zero_bytes_count = transaction.data.count(ascii_chr(0))
                non_zero_bytes_count = len(transaction.data) - zero_bytes_count

                zero_bytes_cost = opcodes.GTXDATAZERO * zero_bytes_count
                nonzero_bytes_cost = opcodes.GTXDATANONZERO * non_zero_bytes_count

                base_gas_cost = opcodes.GTXCOST
                intrinsic_gas_used = base_gas_cost + zero_bytes_cost + nonzero_bytes_cost

                out['time'] = time.time() - start_time
                out['gas'] = self.block.gas_used - gas_used - intrinsic_gas_used

            if profiling > 1:
                trace = recorder.pop_records()
                vm_operations = [
                    event['op']
                    for event in trace
                    if event['event'] == 'vm'
                ]
                opdict = {}
                for operation in vm_operations:
                    opdict[operation] = opdict.get(operation, 0) + 1
                out['ops'] = opdict

            return out
        finally:
            # ensure LogRecorder has been disabled
            if recorder:
                recorder.pop_records()
Example #29
0
    def _send(
            self,
            sender,
            to,
            value,
            evmdata='',
            funid=None,
            abi=None,  # pylint: disable=too-many-arguments
            profiling=0):
        # pylint: disable=too-many-locals

        if funid is not None or abi is not None:
            raise Exception(
                'Send with funid+abi is deprecated. Please use the abi_contract mechanism'
            )

        start_time = time.time()
        gas_used = self.block.gas_used

        sendnonce = self.block.get_nonce(privtoaddr(sender))
        transaction = transactions.Transaction(sendnonce, gas_price, gas_limit,
                                               to, value, evmdata)
        self.last_tx = transaction
        transaction.sign(sender)
        recorder = None

        if profiling > 1:
            recorder = LogRecorder(
                disable_other_handlers=True,
                log_config=TRACE_LVL_MAP[3],
            )

        try:
            (success,
             output) = processblock.apply_transaction(self.block, transaction)

            if not success:
                raise TransactionFailed()

            out = {
                'output': output,
            }

            if profiling > 0:
                zero_bytes_count = transaction.data.count(ascii_chr(0))
                non_zero_bytes_count = len(transaction.data) - zero_bytes_count

                zero_bytes_cost = opcodes.GTXDATAZERO * zero_bytes_count
                nonzero_bytes_cost = opcodes.GTXDATANONZERO * non_zero_bytes_count

                base_gas_cost = opcodes.GTXCOST
                intrinsic_gas_used = base_gas_cost + zero_bytes_cost + nonzero_bytes_cost

                out['time'] = time.time() - start_time
                out['gas'] = self.block.gas_used - gas_used - intrinsic_gas_used

            if profiling > 1:
                trace = recorder.pop_records()
                vm_operations = [
                    event['op'] for event in trace if event['event'] == 'vm'
                ]
                opdict = {}
                for operation in vm_operations:
                    opdict[operation] = opdict.get(operation, 0) + 1
                out['ops'] = opdict

            return out
        finally:
            # ensure LogRecorder has been disabled
            if recorder:
                recorder.pop_records()
Example #30
0
def run_state_test(params, mode):
    pre = params['pre']
    exek = params['transaction']
    env = params['env']

    assert set(env.keys()) == set(['currentGasLimit', 'currentTimestamp',
                                   'previousHash', 'currentCoinbase',
                                   'currentDifficulty', 'currentNumber'])
    assert len(env['currentCoinbase']) == 40

    # setup env
    header = blocks.BlockHeader(
        prevhash=decode_hex(env['previousHash']),
        number=parse_int_or_hex(env['currentNumber']),
        coinbase=decode_hex(env['currentCoinbase']),
        difficulty=parse_int_or_hex(env['currentDifficulty']),
        timestamp=parse_int_or_hex(env['currentTimestamp']),
        # work around https://github.com/ethereum/pyethereum/issues/390 [1]:
        gas_limit=min(2 ** 63 - 1, parse_int_or_hex(env['currentGasLimit'])))
    blk = blocks.Block(header, env=db_env)

    # work around https://github.com/ethereum/pyethereum/issues/390 [2]:
    blk.gas_limit = parse_int_or_hex(env['currentGasLimit'])

    # setup state
    for address, h in list(pre.items()):
        assert len(address) == 40
        address = decode_hex(address)
        assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage'])
        blk.set_nonce(address, parse_int_or_hex(h['nonce']))
        blk.set_balance(address, parse_int_or_hex(h['balance']))
        blk.set_code(address, decode_hex(h['code'][2:]))
        for k, v in h['storage'].items():
            blk.set_storage_data(address,
                                 utils.big_endian_to_int(decode_hex(k[2:])),
                                 utils.big_endian_to_int(decode_hex(v[2:])))

    for address, h in list(pre.items()):
        address = decode_hex(address)
        assert blk.get_nonce(address) == parse_int_or_hex(h['nonce'])
        assert blk.get_balance(address) == parse_int_or_hex(h['balance'])
        assert blk.get_code(address) == decode_hex(h['code'][2:])
        for k, v in h['storage'].items():
            assert blk.get_storage_data(address, utils.big_endian_to_int(
                decode_hex(k[2:]))) == utils.big_endian_to_int(decode_hex(v[2:]))

    # execute transactions
    orig_apply_msg = pb.apply_msg

    def apply_msg_wrapper(ext, msg):

        def blkhash(n):
            if n >= blk.number or n < blk.number - 256:
                return b''
            else:
                return utils.sha3(to_string(n))

        ext.block_hash = blkhash
        return orig_apply_msg(ext, msg)

    pb.apply_msg = apply_msg_wrapper

    try:
        tx = transactions.Transaction(
            nonce=parse_int_or_hex(exek['nonce'] or b"0"),
            gasprice=parse_int_or_hex(exek['gasPrice'] or b"0"),
            startgas=parse_int_or_hex(exek['gasLimit'] or b"0"),
            to=normalize_address(exek['to'], allow_blank=True),
            value=parse_int_or_hex(exek['value'] or b"0"),
            data=decode_hex(remove_0x_head(exek['data'])))
    except InvalidTransaction:
        tx = None
        success, output = False, b''
        time_pre = time.time()
        time_post = time_pre
    else:
        if 'secretKey' in exek:
            tx.sign(exek['secretKey'])
        elif all(key in exek for key in ['v', 'r', 's']):
            tx.v = decode_hex(remove_0x_head(exek['v']))
            tx.r = decode_hex(remove_0x_head(exek['r']))
            tx.s = decode_hex(remove_0x_head(exek['s']))
        else:
            assert False

        time_pre = time.time()
        try:
            print('trying')
            success, output = pb.apply_transaction(blk, tx)
            blk.commit_state()
            print('success', blk.get_receipts()[-1].gas_used)
        except InvalidTransaction:
            success, output = False, b''
            blk.commit_state()
            pass
        time_post = time.time()

        if tx.to == b'':
            output = blk.get_code(output)

    pb.apply_msg = orig_apply_msg

    params2 = copy.deepcopy(params)
    if success:
        params2['logs'] = [log.to_dict() for log in blk.get_receipt(0).logs]

    params2['out'] = b'0x' + encode_hex(output)
    params2['post'] = copy.deepcopy(blk.to_dict(True)['state'])
    params2['postStateRoot'] = encode_hex(blk.state.root_hash)

    if mode == FILL:
        return params2
    elif mode == VERIFY:
        params1 = copy.deepcopy(params)
        shouldbe, reallyis = params1.get('post', None), params2.get('post', None)
        compare_post_states(shouldbe, reallyis)
        for k in ['pre', 'exec', 'env', 'callcreates',
                  'out', 'gas', 'logs', 'postStateRoot']:
            _shouldbe = params1.get(k, None)
            _reallyis = params2.get(k, None)
            if _shouldbe != _reallyis:
                print(('Mismatch {key}: shouldbe {shouldbe_key} != reallyis {reallyis_key}.\n'
                       'post: {shouldbe_post} != {reallyis_post}').format(
                    shouldbe_key=_shouldbe, reallyis_key=_reallyis,
                    shouldbe_post=shouldbe, reallyis_post=reallyis, key=k))
                raise Exception("Mismatch: " + k + ':\n shouldbe %r\n reallyis %r' %
                                (_shouldbe, _reallyis))

    elif mode == TIME:
        return time_post - time_pre
Example #31
0
    def __init__(self, header, transaction_list=[], uncles=[], db=None,
                 parent=None, making=False):
        if db is None:
            raise TypeError("No database object given")
        self.db = db
        self.header = header
        self.uncles = uncles

        self.uncles = uncles
        self.suicides = []
        self.logs = []
        self.log_listeners = []
        self.refunds = 0

        self.ether_delta = 0

        # Journaling cache for state tree updates
        self.caches = {
            'balance': {},
            'nonce': {},
            'code': {},
            'storage': {},
            'all': {}
        }
        self.journal = []

        if self.number > 0:
            self.ancestor_hashes = [self.prevhash]
        else:
            self.ancestor_hashes = [None] * 256

        # do some consistency checks on parent if given
        if parent:
            if hasattr(parent, 'db') and self.db != parent.db:
                raise ValueError("Parent lives in different database")
            if self.prevhash != parent.header.hash:
                raise ValueError("Block's prevhash and parent's hash do not match")
            if self.number != parent.header.number + 1:
                raise ValueError("Block's number is not the successor of its parent number")
            if not check_gaslimit(parent, self.gas_limit):
                raise ValueError("Block's gaslimit is inconsistent with its parent's gaslimit")
            if self.difficulty != calc_difficulty(parent, self.timestamp):
                raise ValueError("Block's difficulty is inconsistent with its parent's difficulty")

        for uncle in uncles:
            assert isinstance(uncle, BlockHeader)

        original_values = {
            'gas_used': header.gas_used,
            'timestamp': header.timestamp,
            'difficulty': header.difficulty,
            'uncles_hash': header.uncles_hash,
            'bloom': header.bloom,
        }

        self.transactions = Trie(db, trie.BLANK_ROOT)
        self.receipts = Trie(db, trie.BLANK_ROOT)
        # replay transactions if state is unknown
        state_unknown = (header.prevhash != GENESIS_PREVHASH and
                         header.state_root != trie.BLANK_ROOT and
                         (len(header.state_root) != 32 or
                          b'validated:' + self.hash not in db) and
                         not making)
        if state_unknown:
            assert transaction_list is not None
            if not parent:
                parent = self.get_parent_header()
            self.state = SecureTrie(Trie(db, parent.state_root))
            self.transaction_count = 0
            self.gas_used = 0
            # replay
            for tx in transaction_list:
                success, output = processblock.apply_transaction(self, tx)
            self.finalize()
        else:
            # trust the state root in the header
            self.state = SecureTrie(Trie(self.db, header._state_root))
            self.transaction_count = 0
            if transaction_list:
                for tx in transaction_list:
                    self.add_transaction_to_list(tx)
            if self.transactions.root_hash != header.tx_list_root:
                raise ValueError("Transaction list root hash does not match")
            # receipts trie populated by add_transaction_to_list is incorrect
            # (it doesn't know intermediate states), so reset it
            self.receipts = Trie(self.db, header.receipts_root)

        if self.number < 40000:
            assert len(self.transactions) == 0

        # checks ##############################

        def must(what, f, symb, a, b):
            if not f(a, b):
                if dump_block_on_failed_verification:
                    sys.stderr.write('%r' % self.to_dict())
                raise VerificationFailed(what, a, symb, b)

        def must_equal(what, a, b):
            return must(what, lambda x, y: x == y, "==", a, b)

        def must_ge(what, a, b):
            return must(what, lambda x, y: x >= y, ">=", a, b)

        def must_le(what, a, b):
            return must(what, lambda x, y: x <= y, "<=", a, b)

        if parent:
            must_equal('prev_hash', self.prevhash, parent.hash)
            must_ge('gas_limit', self.gas_limit,
                    parent.gas_limit * (GASLIMIT_ADJMAX_FACTOR - 1) // GASLIMIT_ADJMAX_FACTOR)
            must_le('gas_limit', self.gas_limit,
                    parent.gas_limit * (GASLIMIT_ADJMAX_FACTOR + 1) // GASLIMIT_ADJMAX_FACTOR)
        must_equal('gas_used', original_values['gas_used'], self.gas_used)
        must_equal('timestamp', self.timestamp, original_values['timestamp'])
        must_equal('difficulty', self.difficulty, original_values['difficulty'])
        must_equal('uncles_hash', utils.sha3(rlp.encode(uncles)), original_values['uncles_hash'])
        assert header.block is None
        must_equal('state_root', self.state.root_hash, header.state_root)
        must_equal('tx_list_root', self.transactions.root_hash, header.tx_list_root)
        must_equal('receipts_root', self.receipts.root_hash, header.receipts_root)
        must_equal('bloom', self.bloom, original_values['bloom'])

        # from now on, trie roots refer to block instead of header
        header.block = self

        # Basic consistency verifications
        if not self.check_fields():
            raise ValueError("Block is invalid")
        if len(self.header.extra_data) > 1024:
            raise ValueError("Extra data cannot exceed 1024 bytes")
        if self.header.coinbase == '':
            raise ValueError("Coinbase cannot be empty address")
        if not self.state.root_hash_valid():
            raise ValueError("State Merkle root of block %r not found in "
                             "database" % self)
        if (not self.is_genesis() and self.nonce and not self.header.check_pow()):
            raise ValueError("PoW check failed")
        self.db.put(b'validated:' + self.hash, '1')
 def send(tx):
     success, _ = apply_transaction(self.state.block, tx)
     assert success  # What happens in real RPC eth_send?
     return '0x' + tx.hash.encode('hex')
Example #33
0
def run_state_test(params, mode):
    pre = params['pre']
    exek = params['transaction']
    env = params['env']

    assert set(env.keys()) == set(['currentGasLimit', 'currentTimestamp',
                                   'previousHash', 'currentCoinbase',
                                   'currentDifficulty', 'currentNumber'])
    assert len(env['currentCoinbase']) == 40

    # setup env
    header = blocks.BlockHeader(
        prevhash=decode_hex(env['previousHash']),
        number=parse_int_or_hex(env['currentNumber']),
        coinbase=decode_hex(env['currentCoinbase']),
        difficulty=parse_int_or_hex(env['currentDifficulty']),
        timestamp=parse_int_or_hex(env['currentTimestamp']),
        # work around https://github.com/ethereum/pyethereum/issues/390 [1]:
        gas_limit=min(db_env.config['MAX_GAS_LIMIT'], parse_int_or_hex(env['currentGasLimit'])))
    blk = blocks.Block(header, env=db_env)

    # work around https://github.com/ethereum/pyethereum/issues/390 [2]:
    blk.gas_limit = parse_int_or_hex(env['currentGasLimit'])

    # setup state
    for address, h in list(pre.items()):
        assert len(address) == 40
        address = decode_hex(address)
        assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage'])
        blk.set_nonce(address, parse_int_or_hex(h['nonce']))
        blk.set_balance(address, parse_int_or_hex(h['balance']))
        blk.set_code(address, decode_hex(h['code'][2:]))
        for k, v in h['storage'].items():
            blk.set_storage_data(address,
                                 utils.big_endian_to_int(decode_hex(k[2:])),
                                 utils.big_endian_to_int(decode_hex(v[2:])))

    for address, h in list(pre.items()):
        address = decode_hex(address)
        assert blk.get_nonce(address) == parse_int_or_hex(h['nonce'])
        assert blk.get_balance(address) == parse_int_or_hex(h['balance'])
        assert blk.get_code(address) == decode_hex(h['code'][2:])
        for k, v in h['storage'].items():
            assert blk.get_storage_data(address, utils.big_endian_to_int(
                decode_hex(k[2:]))) == utils.big_endian_to_int(decode_hex(v[2:]))

    # execute transactions
    orig_apply_msg = pb.apply_msg

    def apply_msg_wrapper(ext, msg):

        def blkhash(n):
            if n >= blk.number or n < blk.number - 256:
                return b''
            else:
                return utils.sha3(to_string(n))

        ext.block_hash = blkhash
        return orig_apply_msg(ext, msg)

    pb.apply_msg = apply_msg_wrapper

    try:
        tx = transactions.Transaction(
            nonce=parse_int_or_hex(exek['nonce'] or b"0"),
            gasprice=parse_int_or_hex(exek['gasPrice'] or b"0"),
            startgas=parse_int_or_hex(exek['gasLimit'] or b"0"),
            to=normalize_address(exek['to'], allow_blank=True),
            value=parse_int_or_hex(exek['value'] or b"0"),
            data=decode_hex(remove_0x_head(exek['data'])))
    except InvalidTransaction:
        tx = None
        success, output = False, b''
        time_pre = time.time()
        time_post = time_pre
    else:
        if 'secretKey' in exek:
            tx.sign(exek['secretKey'])
        elif all(key in exek for key in ['v', 'r', 's']):
            tx.v = decode_hex(remove_0x_head(exek['v']))
            tx.r = decode_hex(remove_0x_head(exek['r']))
            tx.s = decode_hex(remove_0x_head(exek['s']))
        else:
            assert False

        time_pre = time.time()
        try:
            print('trying')
            success, output = pb.apply_transaction(blk, tx)
            blk.commit_state()
            print('success', blk.get_receipts()[-1].gas_used)
        except InvalidTransaction:
            success, output = False, b''
            blk.commit_state()
            pass
        time_post = time.time()

        if tx.to == b'':
            output = blk.get_code(output)

    pb.apply_msg = orig_apply_msg

    params2 = copy.deepcopy(params)
    if success:
        params2['logs'] = [log.to_dict() for log in blk.get_receipt(0).logs]

    params2['out'] = b'0x' + encode_hex(output)
    params2['post'] = copy.deepcopy(blk.to_dict(True)['state'])
    params2['postStateRoot'] = encode_hex(blk.state.root_hash)

    if mode == FILL:
        return params2
    elif mode == VERIFY:
        params1 = copy.deepcopy(params)
        shouldbe, reallyis = params1.get('post', None), params2.get('post', None)
        compare_post_states(shouldbe, reallyis)
        for k in ['pre', 'exec', 'env', 'callcreates',
                  'out', 'gas', 'logs', 'postStateRoot']:
            _shouldbe = params1.get(k, None)
            _reallyis = params2.get(k, None)
            if str_to_bytes(k) == b'out' and _shouldbe[:1] in ('#', b'#'):
                _reallyis = str_to_bytes('#%s' % ((len(_reallyis) - 2) // 2))
            if _shouldbe != _reallyis:
                print(('Mismatch {key}: shouldbe {shouldbe_key} != reallyis {reallyis_key}.\n'
                       'post: {shouldbe_post} != {reallyis_post}').format(
                    shouldbe_key=_shouldbe, reallyis_key=_reallyis,
                    shouldbe_post=shouldbe, reallyis_post=reallyis, key=k))
                raise Exception("Mismatch: " + k + ':\n shouldbe %r\n reallyis %r' %
                                (_shouldbe, _reallyis))

    elif mode == TIME:
        return time_post - time_pre