You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: compact_block.rs
    path of file: ./repos/ckb/test/src/specs/relay
    
    the code of the file until where you have to start completion: use crate::node::waiting_for_sync;
use crate::util::cell::gen_spendable;
use crate::util::check::is_transaction_committed;
use crate::util::mining::out_ibd_mode;
use crate::util::transaction::always_success_transaction;
use crate::utils::{
    build_block, build_block_transactions, build_compact_block, build_compact_block_with_prefilled,
    build_header, build_headers, wait_until,
};
use crate::{Net, Node, Spec};
use ckb_network::{bytes::Bytes, SupportProtocols};
use ckb_types::{
    core::{HeaderBuilder, HeaderView},
    h256,
    packed::{
        self, GetHeaders, RelayMessage, RelayMessageUnion::GetBlockTransactions, SyncMessage,
        SyncMessageUnion::GetBlocks,
    },
    prelude::*,
};

pub struct CompactBlockEmptyParentUnknown;

impl Spec for CompactBlockEmptyParentUnknown {
    // Case: Sent to node0 a parent-unknown empty block, node0 should be unable to reconstruct
    // it and send us back a `GetHeaders` message
    fn run(&self, nodes: &mut Vec<Node>) {
        out_ibd_mode(nodes);
        let node = &nodes[0];
        let mut net = Net::new(
            self.name(),
            node.consensus(),
            vec![SupportProtocols::Sync, SupportProtocols::RelayV3],
        );
        net.connect(node);

        node.mine(1);

        let parent_unknown_block = node
            .new_block_builder(None, None, None)
            .header(
                HeaderBuilder::default()
                    .parent_hash(h256!("0x123456").pack())
                    .build(),
            )
            .build();
        let tip_block = node.get_tip_block();
        net.send(
            node,
            SupportProtocols::RelayV3,
            build_compact_block(&parent_unknown_block),
        );
        let ret = wait_until(10, move || node.get_tip_block() != tip_block);
        assert!(!ret, "Node0 should reconstruct empty block failed");

        let ret = net.should_receive(node, |data: &Bytes| {
            SyncMessage::from_slice(data)
                .map(|message| 
    
    fn run(&self, nodes: &mut Vec<Node>) {
        let node0 = &nodes[0];
        let node1 = &nodes[1];
        let block_a = {
            let cells = gen_spendable(node1, 1);
            let tx = always_success_transaction(node1, &cells[0]);
            node1.submit_transaction(&tx);
            node1.mine_until_bool(|| is_transaction_committed(node1, &tx));
            node1.get_tip_block()
        };
        node1.mine(1);
        let block_b = node1.get_tip_block();

        for number in 1..block_a.number() {
            let block = node1.get_block_by_number(number);
            node0.submit_block(&block);
        }

        let mut net = Net::new(
            self.name(),
            node0.consensus(),
            vec![SupportProtocols::Sync, SupportProtocols::RelayV3],
        );
        net.connect(node0);

        // 1. Sync block_b's SendBlock to node0. It has the following steps:
        //   (1) Sync block_a's SendHeader to node0
        //   (2) Sync block_b's SendHeader to node0
        //   (3) Wait GetBlocks from node0
        //   (4) Sync block_b's SendBlock to node0
        // After then node0 should save block_b into orphan_block_pool as it only receives block_a's
        // header but lack of block_a's body.
        net.send(
            node0,
            SupportProtocols::Sync,
            build_header(&block_a.header()),
        );
        net.send(
            node0,
            SupportProtocols::Sync,
            build_header(&block_b.header()),
        );
        let ret = net.should_receive(node0, |data| {
            SyncMessage::from_slice(data)
                .map(|message| {
                    if let GetBlocks(get_blocks) = message.to_enum() {
                        for hash in get_blocks.block_hashes().into_iter() {
                            if hash == block_b.hash() {
                                return true;
                            }
                        }
                    }
                    false
                })
                .unwrap_or(false)
        });
        assert!(
            ret,
            "Node0 should receive GetBlocks which consists of `block_b`"
        );
        net.send(node0, SupportProtocols::Sync, build_block(&block_b));

        // 2. Relay CompactBlock-A to node0. Node0 misses fresh transactions of A, hence it will request for
        // the missing A.transactions via GetBlockTransactions
        net.send(
            node0,
            SupportProtocols::RelayV3,
            build_compact_block(&block_a),
        );
        let ret = net.should_receive(node0, |data| {
            RelayMessage::from_slice(data)
                .map(|message| {
                    if let GetBlockTransactions(get_block_transactions) = message.to_enum() {
                        get_block_transactions.block_hash() == block_a.hash()
                    } else {
                        false
                    }
                })
                .unwrap_or(false)
        });
        assert!(
            ret,
            "Node0 should request block_a's missing transactions via GetBlockTransactions"
        );

        // 3. Relay BlockTransactions-A to node0. Node0 will process A, and by the way process B that was
        // inserted in orphan_block_pool before
        net.send(
            node0,
            SupportProtocols::RelayV3,
            build_block_transactions(&block_a),
        );

        let ret = wait_until(20, || node0.get_tip_block_number() == block_b.number());
        if !ret {
            assert_eq!(
                node0.get_tip_block_number(),
                block_b.number(),
                "relayer should process the two blocks, including the orphan block"
            );
        }
    }