Ejemplo n.º 1
0
def compute_state_test_unit(state, txdata, indices, konfig):
    state.env.config = konfig
    s = state.snapshot()
    try:
        # Create the transaction
        tx = transactions.Transaction(
            nonce=parse_int_or_hex(txdata['nonce'] or b"0"),
            gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"),
            startgas=parse_int_or_hex(txdata['gasLimit'][indices["gas"]]
                                      or b"0"),
            to=decode_hex(remove_0x_head(txdata['to'])),
            value=parse_int_or_hex(txdata['value'][indices["value"]] or b"0"),
            data=decode_hex(remove_0x_head(txdata['data'][indices["data"]])))
        if 'secretKey' in txdata:
            tx.sign(decode_hex(remove_0x_head(txdata['secretKey'])))
        else:
            tx.v = parse_int_or_hex(txdata['v'])
        # Run it
        prev = state.to_dict()
        success, output = apply_transaction(state, tx)
        print("Applied tx")
    except InvalidTransaction as e:
        print("Exception: %r" % e)
        success, output = False, b''
    # state.set_code('0x3e180b1862f9d158abb5e519a6d8605540c23682', b'')
    state.commit()
    post = state.to_dict()
    # print('pozt', post)
    output_decl = {
        "hash": '0x' + encode_hex(state.trie.root_hash),
        "indexes": indices,
        "diff": mk_state_diff(prev, post)
    }
    state.revert(s)
    return output_decl
Ejemplo n.º 2
0
def init_state(env, pre, is_qkc_state, qkc_env=None):
    # Setup env
    db = InMemoryDb()
    state_env = Env(config=konfig)
    state_env.db = db
    state = State(
        env=state_env,
        block_prevhash=decode_hex(remove_0x_head(env["previousHash"])),
        prev_headers=[
            mk_fake_header(i)
            for i in range(
                parse_int_or_hex(env["currentNumber"]) - 1,
                max(-1, parse_int_or_hex(env["currentNumber"]) - 257),
                -1,
            )
        ],
        block_number=parse_int_or_hex(env["currentNumber"]),
        block_coinbase=decode_hex(remove_0x_head(env["currentCoinbase"])),
        block_difficulty=parse_int_or_hex(env["currentDifficulty"]),
        gas_limit=parse_int_or_hex(env["currentGasLimit"]),
        timestamp=parse_int_or_hex(env["currentTimestamp"]),
        qkc_config=qkc_env.quark_chain_config,
        # If testing QuarkChain states, should not use mock account
        use_mock_evm_account=not is_qkc_state,
    )

    seen_token_ids = set()
    # Fill up pre
    for address, h in list(pre.items()):
        assert len(address) in (40, 42)
        address = decode_hex(remove_0x_head(address))
        state.set_nonce(address, parse_int_or_hex(h["nonce"]))
        if is_qkc_state and "balances" in h:
            # In QuarkChain state tests, can either specify balance map or single balance
            for token_id, balance in h["balances"].items():
                parsed_token_id = parse_int_or_hex(token_id)
                state.set_token_balance(
                    address, parsed_token_id, parse_int_or_hex(balance)
                )
                seen_token_ids.add(parsed_token_id)
        else:
            state.set_balance(address, parse_int_or_hex(h["balance"]))
        state.set_code(address, decode_hex(remove_0x_head(h["code"])))
        for k, v in h["storage"].items():
            state.set_storage_data(
                address,
                big_endian_to_int(decode_hex(k[2:])),
                big_endian_to_int(decode_hex(v[2:])),
            )

    # Update allowed token IDs
    if seen_token_ids:
        state.qkc_config._allowed_token_ids = seen_token_ids

    state.commit(allow_empties=True)
    return state
Ejemplo n.º 3
0
def compute_state_test_unit(state,
                            txdata,
                            indices,
                            konfig,
                            is_qkc_state,
                            qkc_env=None):
    state.env.config = konfig
    s = state.snapshot()
    if "transferTokenId" in txdata:
        transfer_token_id = parse_int_or_hex(
            txdata["transferTokenId"][indices["transferTokenId"]])
    else:
        transfer_token_id = token_id_encode("QKC")
    try:
        # Create the transaction
        tx = transactions.Transaction(
            nonce=parse_int_or_hex(txdata["nonce"] or b"0"),
            gasprice=parse_int_or_hex(txdata["gasPrice"] or b"0"),
            startgas=parse_int_or_hex(txdata["gasLimit"][indices["gas"]]
                                      or b"0"),
            to=decode_hex(remove_0x_head(txdata["to"])),
            value=parse_int_or_hex(txdata["value"][indices["value"]] or b"0"),
            data=decode_hex(remove_0x_head(txdata["data"][indices["data"]])),
            gas_token_id=token_id_encode("QKC"),
            transfer_token_id=transfer_token_id,
            # Should not set testing flag if testing QuarkChain state
            is_testing=not is_qkc_state,
        )
        tx.set_quark_chain_config(qkc_env.quark_chain_config)
        if "secretKey" in txdata:
            tx.sign(decode_hex(remove_0x_head(txdata["secretKey"])))
        else:
            tx._in_mutable_context = True
            tx.v = parse_int_or_hex(txdata["v"])
            tx._in_mutable_context = False
        # Run it
        prev = state.to_dict()
        success, output = apply_transaction(state,
                                            tx,
                                            tx_wrapper_hash=bytes(32))
    except InvalidTransaction as e:
        print("Exception: %r" % e)
        success, output = False, b""
    # touch coinbase, make behavior consistent with go-ethereum
    state.delta_token_balance(state.block_coinbase, token_id_encode("QKC"), 0)
    state.commit()
    post = state.to_dict()
    output_decl = {
        "hash": "0x" + encode_hex(state.trie.root_hash),
        "indexes": indices,
        "diff": mk_state_diff(prev, post),
    }
    state.revert(s)
    return output_decl
Ejemplo n.º 4
0
    def coinbase(self):
        """Return the address that should be used as coinbase for new blocks.

        The coinbase address is given by the config field pow.coinbase_hex. If this does not exist
        or is `None`, the address of the first account is used instead. If there are no accounts,
        the coinbase is `DEFAULT_COINBASE`.

        :raises: :exc:`ValueError` if the coinbase is invalid (no string, wrong length) or there is
                 no account for it and the config flag `accounts.check_coinbase` is set (does not
                 apply to the default coinbase)
        """
        cb_hex = self.app.config.get('pow', {}).get('coinbase_hex')
        if cb_hex is None:
            if not self.accounts_with_address:
                return DEFAULT_COINBASE
            cb = self.accounts_with_address[0].address
        else:
            # [NOTE]: check it!
            # if not is_string(cb_hex):
            if not isinstance(cb_hex, str):
                raise ValueError('coinbase must be string')
            try:
                cb = decode_hex(remove_0x_head(cb_hex))
            except (ValueError, TypeError):
                raise ValueError('invalid coinbase')
        if len(cb) != 20:
            raise ValueError('wrong coinbase length')
        if self.config['accounts']['must_include_coinbase']:
            if cb not in (acct.address for acct in self.accounts):
                raise ValueError('no account for coinbase')
        return cb
Ejemplo n.º 5
0
def init_state(env, pre):
    # Setup env
    db = InMemoryDb()
    stateEnv = Env(config=konfig)
    stateEnv.db = db
    state = State(
        env=stateEnv,
        block_prevhash=decode_hex(remove_0x_head(env["previousHash"])),
        prev_headers=[
            mk_fake_header(i) for i in range(
                parse_int_or_hex(env["currentNumber"]) - 1,
                max(-1,
                    parse_int_or_hex(env["currentNumber"]) - 257),
                -1,
            )
        ],
        block_number=parse_int_or_hex(env["currentNumber"]),
        block_coinbase=decode_hex(remove_0x_head(env["currentCoinbase"])),
        block_difficulty=parse_int_or_hex(env["currentDifficulty"]),
        gas_limit=parse_int_or_hex(env["currentGasLimit"]),
        timestamp=parse_int_or_hex(env["currentTimestamp"]),
    )

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

    state.commit(allow_empties=True)
    # state.commit()
    return state
Ejemplo n.º 6
0
    def create_minor_block(
            self, root_block: RootBlock, full_shard_id: int,
            evm_state: EvmState) -> Tuple[MinorBlock, TokenBalanceMap]:
        """ Create genesis block for shard.
        Genesis block's hash_prev_root_block is set to the genesis root block.
        Genesis state will be committed to the given evm_state.
        Based on ALLOC, genesis_token will be added to initial accounts.
        """
        branch = Branch(full_shard_id)
        shard_config = self._qkc_config.shards[full_shard_id]
        genesis = shard_config.GENESIS

        for address_hex, alloc_data in genesis.ALLOC.items():
            address = Address.create_from(bytes.fromhex(address_hex))
            check(
                self._qkc_config.get_full_shard_id_by_full_shard_key(
                    address.full_shard_key) == full_shard_id)
            evm_state.full_shard_key = address.full_shard_key
            recipient = address.recipient
            if "code" in alloc_data:
                code = decode_hex(remove_0x_head(alloc_data["code"]))
                evm_state.set_code(recipient, code)
                evm_state.set_nonce(recipient, 1)
            if "storage" in alloc_data:
                for k, v in alloc_data["storage"].items():
                    evm_state.set_storage_data(
                        recipient,
                        big_endian_to_int(decode_hex(k[2:])),
                        big_endian_to_int(decode_hex(v[2:])),
                    )
            # backward compatible:
            # v1: {addr: {QKC: 1234}}
            # v2: {addr: {balances: {QKC: 1234}, code: 0x, storage: {0x12: 0x34}}}
            balances = alloc_data
            if "balances" in alloc_data:
                balances = alloc_data["balances"]
            for k, v in balances.items():
                if k in ("code", "storage"):
                    continue
                evm_state.delta_token_balance(recipient, token_id_encode(k), v)

        evm_state.commit()

        meta = MinorBlockMeta(
            hash_merkle_root=bytes.fromhex(genesis.HASH_MERKLE_ROOT),
            hash_evm_state_root=evm_state.trie.root_hash,
            xshard_tx_cursor_info=XshardTxCursorInfo(root_block.header.height,
                                                     0, 0),
        )

        local_fee_rate = 1 - self._qkc_config.reward_tax_rate  # type: Fraction
        coinbase_tokens = {
            self._qkc_config.genesis_token:
            shard_config.COINBASE_AMOUNT * local_fee_rate.numerator //
            local_fee_rate.denominator
        }

        coinbase_address = Address.create_empty_account(full_shard_id)

        header = MinorBlockHeader(
            version=genesis.VERSION,
            height=genesis.HEIGHT,
            branch=branch,
            hash_prev_minor_block=bytes.fromhex(genesis.HASH_PREV_MINOR_BLOCK),
            hash_prev_root_block=root_block.header.get_hash(),
            evm_gas_limit=genesis.GAS_LIMIT,
            hash_meta=sha3_256(meta.serialize()),
            coinbase_amount_map=TokenBalanceMap(coinbase_tokens),
            coinbase_address=coinbase_address,
            create_time=genesis.TIMESTAMP,
            difficulty=genesis.DIFFICULTY,
            extra_data=bytes.fromhex(genesis.EXTRA_DATA),
        )
        return (
            MinorBlock(header=header, meta=meta, tx_list=[]),
            TokenBalanceMap(coinbase_tokens),
        )