def METHOD_NAME(self):
    priv_key = default_config["GENESIS_PRI_KEY"]
    sender = encode_hex(priv_to_addr(priv_key))
    # deploy contract
    bytecode_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), CONTRACT_PATH)
    assert(os.path.isfile(bytecode_file))
    bytecode = open(bytecode_file).read()
    _, contract_addr = self.deploy_contract(sender, priv_key, bytecode)
    self.log.info("Contract deployed")
    parent_hash = self.rpc[FULLNODE0].block_by_epoch("latest_mined")['hash']
    nonce = self.rpc[FULLNODE0].get_nonce(sender)
    hashes = []
    num_events = 0
    num_blamed = 0
    for i in range(0, NORMAL_CHAIN_LENGTH):
        if i % (2 * ERA_EPOCH_COUNT) == 0:
            # Leave some time for PoS to progress, so we can avoid cross-checkpoint reference.
            time.sleep(1)
        rnd = random.random()
        # ~20% of all block have events
        if rnd < 0.2:
            tx = self.rpc[FULLNODE0].new_contract_tx(
                receiver=contract_addr,
                data_hex=encode_hex_0x(keccak(b"foo()")),
                sender=sender, priv_key=priv_key,
                storage_limit=64,
                nonce = nonce
            )
            parent_hash = self.rpc[FULLNODE0].generate_custom_block(parent_hash=parent_hash, txs=[tx], referee=[])
            nonce += 1
            hashes.append(tx.hash_hex())
            num_events += 1
        # ~10% of all blocks are incorrect and blamed
        elif rnd < 0.3:
            blame_info = {}
            blame_info['blame'] = "0x1"
            blame_info['deferredStateRoot'] = "0x1111111111111111111111111111111111111111111111111111111111111111"
            parent_hash = self.nodes[FULLNODE0].test_generateblockwithblameinfo(1, 0, blame_info)
            num_blamed += 1
        # the rest are empty
        else:
            parent_hash = self.rpc[FULLNODE0].generate_block_with_parent(parent_hash=parent_hash)
        # TODO: generate blamed blocks with txs in them (overlap)
    # generate a pivot chain section where we might not be able to decide blaming
    # in this section, all headers will have blame=1
    # odd-numbered blocks are incorrect, even-numbered blocks are correct
    for _ in range(0, BLAMED_SECTION_LENGTH):
        blame_info = {}
        blame_info['blame'] = "0x1"
        parent_hash = self.nodes[FULLNODE0].test_generateblockwithblameinfo(1, 0, blame_info)
    num_blamed += BLAMED_SECTION_LENGTH // 2
    # mine some more blocks to keep blame check offset
    for _ in range(0, BLAMED_SECTION_LENGTH):
        parent_hash = self.rpc[FULLNODE0].generate_custom_block(parent_hash=parent_hash, txs=[], referee=[])
    # check if all txs have been executed successfully
    for hash in hashes:
        receipt = self.rpc[FULLNODE0].get_transaction_receipt(hash)
        assert_equal(receipt["outcomeStatus"], "0x0")
    length = NORMAL_CHAIN_LENGTH + 2 * BLAMED_SECTION_LENGTH
    self.log.info(f"Generated {length} blocks with {num_events} events and {num_blamed} incorrect blocks")