fn connect_block(
    store:           &mut Store,
    this_block_hash: Hash32,
    previous_block:  Option<BlockPtr>,
    this_block:      BlockPtr)

    -> BlockResult<()>
{
    trace!(store.logger, "Connect block";
        "this_hash"  =>  format!("{:?}", this_block_hash),
        "prev_end"   =>  format!("{:?}", previous_block),
        "this_start" =>  format!("{:?}", this_block)
    );

    // we lay connections between the end of one block and the start of this_block
    // previous_block is None only for genesis

    // A to_do item
    #[derive(Debug)]
    struct Connection {
        block:         BlockPtr,
        block_hash:    Hash32Buf,
        solved_guards: Vec<BlockPtr>
    }

    // connect this block if not genesis...
    if let Some(previous_block) = previous_block {
        store.spend_tree.connect_block( &mut store.spend_index, & store.logger, previous_block, this_block) ?;
    }

    // The to_do list contains blocks that are connected to their previous but not yet added to the
    // block-index. Start with the one we just connected;
    let mut todo = vec![Connection {
        block:         this_block,
        block_hash:    this_block_hash.as_buf(),
        solved_guards: vec![]
    }];


    while let Some(conn) = todo.pop() {

        trace!(store.logger, "Connect block - set-hash-loop";
            "conn"  => format!("{:?}",   conn));

        // if we can store this hash we can move to the next one
        if store.block_index.set(conn.block_hash.as_ref(), conn.block.to_non_guard(), &conn.solved_guards, false) {
            trace!(store.logger, "Connect block - set-hash-loop - ok");
            continue;
        }

        // we couldn't add this block to the index, which means some block is awaiting connection
        let guards = store.block_index.get(conn.block_hash.as_ref());

        if guards.iter().any(|ptr| !ptr.is_guard()) {
            // this is not a guard, this is _this_ block. This means the block
            // was added by a concurrent user; will do just fine.
            trace!(store.logger, "Connect block - set-hash-loop - concurrent add");
            continue;
        }

        // we'll try this one again the next iteration
        todo.push(Connection {
            block: conn.block,
            block_hash: conn.block_hash,
            solved_guards: guards.clone()
        });

        // and connect pending blocks first
        for ptr in guards {
            if conn.solved_guards.contains(&ptr) {
                continue;
            }

            let hash = store.get_block_hash(ptr);

            trace!(store.logger, "Connect block - set-hash-loop";
                "guard" => format!("{:?}", ptr),
                "hash" => format!("{:?}",   hash),
                "conn"  => format!("{:?}",   conn));


            store.spend_tree.revolve_orphan_pointers(
                &mut store.transactions,
                &mut store.tx_index,
                ptr
            );

            store.spend_tree.connect_block(&mut store.spend_index, &store.logger, conn.block, ptr)?;


            todo.push(Connection {
                block: ptr,
                block_hash: hash,
                solved_guards: vec![]

            });

        }
    }


    Ok(())
}
// Connects two blocks (A,B) in the spend-tree and then stores the hash of B in the hash-index
// Connecting the blocks will verify double-spends
//
// It can be that another block C is also waiting for B; this will trigger their connection (B,C) too
// and maybe (C,D)... etcetera
//
// This would be much cleaner to do recursively, but this can exhaust the stack, we use a loop with
// a to_do for connections.
Connects two blocks (A,B) in the spend-tree and then stores the hash of B in the hash-index
Connecting the blocks will verify double-spends

It can be that another block C is also waiting for B; this will trigger their connection (B,C) too
and maybe (C,D)... etcetera

This would be much cleaner to do recursively, but this can exhaust the stack, we use a loop with
a to_do for connections.
Connects two blocks ( A B ) in the spend - tree and then stores the hash of B in the hash - index Connecting the blocks will verify double - spends It can be that another block C is also waiting for B ; this will trigger their connection ( B C ) too and maybe ( C D ) ... etcetera This would be much cleaner to do recursively but this can exhaust the stack we use a loop with a to_do for connections .
fn connect_block(
    store:           &mut Store,
    this_block_hash: Hash32,
    previous_block:  Option<BlockPtr>,
    this_block:      BlockPtr)
    -> BlockResult<()>
{
    trace!(store.logger, "Connect block";
        "this_hash"  =>  format!("{:?}", this_block_hash),
        "prev_end"   =>  format!("{:?}", previous_block),
        "this_start" =>  format!("{:?}", this_block)
    );
    // we lay connections between the end of one block and the start of this_block
    // previous_block is None only for genesis
    // A to_do item
    #[derive(Debug)]
    struct Connection {
        block:         BlockPtr,
        block_hash:    Hash32Buf,
        solved_guards: Vec<BlockPtr>
    }
    // connect this block if not genesis...
    if let Some(previous_block) = previous_block {
        store.spend_tree.connect_block( &mut store.spend_index, & store.logger, previous_block, this_block) ?;
    }
    // The to_do list contains blocks that are connected to their previous but not yet added to the
    // block-index. Start with the one we just connected;
    let mut todo = vec![Connection {
        block:         this_block,
        block_hash:    this_block_hash.as_buf(),
        solved_guards: vec![]
    }];
    while let Some(conn) = todo.pop() {
        trace!(store.logger, "Connect block - set-hash-loop";
            "conn"  => format!("{:?}",   conn));
        // if we can store this hash we can move to the next one
        if store.block_index.set(conn.block_hash.as_ref(), conn.block.to_non_guard(), &conn.solved_guards, false) {
            trace!(store.logger, "Connect block - set-hash-loop - ok");
            continue;
        }
        // we couldn't add this block to the index, which means some block is awaiting connection
        let guards = store.block_index.get(conn.block_hash.as_ref());
        if guards.iter().any(|ptr| !ptr.is_guard()) {
            // this is not a guard, this is _this_ block. This means the block
            // was added by a concurrent user; will do just fine.
            trace!(store.logger, "Connect block - set-hash-loop - concurrent add");
            continue;
        }
        // we'll try this one again the next iteration
        todo.push(Connection {
            block: conn.block,
            block_hash: conn.block_hash,
            solved_guards: guards.clone()
        });
        // and connect pending blocks first
        for ptr in guards {
            if conn.solved_guards.contains(&ptr) {
                continue;
            }
            let hash = store.get_block_hash(ptr);
            trace!(store.logger, "Connect block - set-hash-loop";
                "guard" => format!("{:?}", ptr),
                "hash" => format!("{:?}",   hash),
                "conn"  => format!("{:?}",   conn));
            store.spend_tree.revolve_orphan_pointers(
                &mut store.transactions,
                &mut store.tx_index,
                ptr
            );
            store.spend_tree.connect_block(&mut store.spend_index, &store.logger, conn.block, ptr)?;
            todo.push(Connection {
                block: ptr,
                block_hash: hash,
                solved_guards: vec![]
            });
        }
    }
    Ok(())
}
fn connect_block ( store : & mut Store , this_block_hash : Hash32 , previous_block : Option < BlockPtr > , this_block : BlockPtr ) -> BlockResult < ( ) > { trace ! ( store logger " " " " format ( " " this_block_hash ) " " format ( " " previous_block ) " " format ( " " this_block ) ) ; // we lay connections between the end of one block and the start of this_block // previous_block is None only for genesis // A to_do item # [ derive ( Debug ) ] struct Connection { block : BlockPtr , block_hash : Hash32Buf , solved_guards : Vec < BlockPtr > } // connect this block if not genesis... if let Some ( previous_block ) = previous_block { store . spend_tree . connect_block ( & mut store . spend_index , & store . logger , previous_block , this_block ) ? ; } // The to_do list contains blocks that are connected to their previous but not yet added to the // block-index. Start with the one we just connected; let mut todo = vec ! [ Connection { block this_block block_hash this_block_hash as_buf ( ) solved_guards vec [ ] } ] ; while let Some ( conn ) = todo . pop ( ) { trace ! ( store logger " " " " format ( " " conn ) ) ; // if we can store this hash we can move to the next one if store . block_index . set ( conn . block_hash . as_ref ( ) , conn . block . to_non_guard ( ) , & conn . solved_guards , false ) { trace ! ( store logger " " ) ; continue ; } // we couldn't add this block to the index, which means some block is awaiting connection let guards = store . block_index . get ( conn . block_hash . as_ref ( ) ) ; if guards . iter ( ) . any ( | ptr | ! ptr . is_guard ( ) ) { // this is not a guard, this is _this_ block. This means the block // was added by a concurrent user; will do just fine. trace ! ( store logger " " ) ; continue ; } // we'll try this one again the next iteration todo . push ( Connection { block : conn . block , block_hash : conn . block_hash , solved_guards : guards . clone ( ) } ) ; // and connect pending blocks first for ptr in guards { if conn . solved_guards . contains ( & ptr ) { continue ; } let hash = store . get_block_hash ( ptr ) ; trace ! ( store logger " " " " format ( " " ptr ) " " format ( " " hash ) " " format ( " " conn ) ) ; store . spend_tree . revolve_orphan_pointers ( & mut store . transactions , & mut store . tx_index , ptr ) ; store . spend_tree . connect_block ( & mut store . spend_index , & store . logger , conn . block , ptr ) ? ; todo . push ( Connection { block : ptr , block_hash : hash , solved_guards : vec ! [ ] } ) ; } } Ok ( ( ) ) }
Connects two blocks (A,B) in the spend-tree and then stores the hash of B in the hash-index
Connecting the blocks will verify double-spends
Connects two blocks ( A B ) in the spend - tree and then stores the hash of B in the hash - index Connecting the blocks will verify double - spends
store
&mut Store
this_block_hash
Hash32
previous_block
Option<BlockPtr>
this_block
BlockPtr
store
&mut Store
this_block_hash
Hash32
previous_block
Option<BlockPtr>
this_block
BlockPtr