fn handle_connected_block(&mut self, block_hash: BlockHash, block: Block) {

        // Quick optimization: don't do anything if the incoming block
        // is already the tip. Ideally we would bail out if the
        // incoming block is on the tip chain, but there is no quick
        // way to check that.
        if block_hash != self.chain_state.last_block {

            blob::write(&self.storage, &block_hash, cbor!(block).unwrap().as_ref())
                .expect("unable to write block to disk");

            // Compute the new chain state. In the common case, the
            // incoming block is a direct successor of the tip, so we
            // just apply the block to our current chain
            // state. Otherwise we use restore_chain_state() to
            // compute the chain state from the last state snapshot on
            // disk.
            let new_chain_state = if block.get_header().get_previous_header() == self.chain_state.last_block {
                let mut new_chain_state = self.chain_state.clone();
                match new_chain_state.verify_block(&block_hash, &block) {
                    Ok(()) => Ok(new_chain_state),
                    Err(err) => Err(err.into())
                }
            } else {
                restore_chain_state(&self.storage, &self.genesis_data, &block_hash)
            };

            match new_chain_state {
                Ok(new_chain_state) => {
                    assert_eq!(new_chain_state.last_block, block_hash);
                    if new_chain_state.chain_length > self.chain_state.chain_length {
                        info!("switching to new tip {} ({:?}), previous length {}, new length {}",
                              block_hash, new_chain_state.last_date,
                              self.chain_state.chain_length, new_chain_state.chain_length);
                        self.chain_state = new_chain_state;
                        tag::write_hash(&self.storage, &LOCAL_BLOCKCHAIN_TIP_TAG, &block_hash);
                    } else {
                        info!("discarding shorter incoming fork {} ({:?}, length {}), tip length {}",
                              block_hash, new_chain_state.last_date,
                              new_chain_state.chain_length, self.chain_state.chain_length);
                    }
                }
                Err(err) => error!("cannot compute chain state for incoming fork {}: {:?}", block_hash, err)
            }
        }

        // Process previously received children of this block.
        if let Some(children) = self.unconnected_blocks.remove(&block_hash) {
            for (child_hash, child_block) in children {
                info!("triggering child block {}", child_hash);
                self.handle_connected_block(child_hash, child_block);
            }
        }
    }
/// Handle a block whose ancestors are on disk.
Handle a block whose ancestors are on disk.
Handle a block whose ancestors are on disk .
fn handle_connected_block(&mut self, block_hash: BlockHash, block: Block) {
        // Quick optimization: don't do anything if the incoming block
        // is already the tip. Ideally we would bail out if the
        // incoming block is on the tip chain, but there is no quick
        // way to check that.
        if block_hash != self.chain_state.last_block {
            blob::write(&self.storage, &block_hash, cbor!(block).unwrap().as_ref())
                .expect("unable to write block to disk");
            // Compute the new chain state. In the common case, the
            // incoming block is a direct successor of the tip, so we
            // just apply the block to our current chain
            // state. Otherwise we use restore_chain_state() to
            // compute the chain state from the last state snapshot on
            // disk.
            let new_chain_state = if block.get_header().get_previous_header() == self.chain_state.last_block {
                let mut new_chain_state = self.chain_state.clone();
                match new_chain_state.verify_block(&block_hash, &block) {
                    Ok(()) => Ok(new_chain_state),
                    Err(err) => Err(err.into())
                }
            } else {
                restore_chain_state(&self.storage, &self.genesis_data, &block_hash)
            };
            match new_chain_state {
                Ok(new_chain_state) => {
                    assert_eq!(new_chain_state.last_block, block_hash);
                    if new_chain_state.chain_length > self.chain_state.chain_length {
                        info!("switching to new tip {} ({:?}), previous length {}, new length {}",
                              block_hash, new_chain_state.last_date,
                              self.chain_state.chain_length, new_chain_state.chain_length);
                        self.chain_state = new_chain_state;
                        tag::write_hash(&self.storage, &LOCAL_BLOCKCHAIN_TIP_TAG, &block_hash);
                    } else {
                        info!("discarding shorter incoming fork {} ({:?}, length {}), tip length {}",
                              block_hash, new_chain_state.last_date,
                              new_chain_state.chain_length, self.chain_state.chain_length);
                    }
                }
                Err(err) => error!("cannot compute chain state for incoming fork {}: {:?}", block_hash, err)
            }
        }
        // Process previously received children of this block.
        if let Some(children) = self.unconnected_blocks.remove(&block_hash) {
            for (child_hash, child_block) in children {
                info!("triggering child block {}", child_hash);
                self.handle_connected_block(child_hash, child_block);
            }
        }
    }
fn handle_connected_block ( & mut self , block_hash : BlockHash , block : Block ) { // Quick optimization: don't do anything if the incoming block // is already the tip. Ideally we would bail out if the // incoming block is on the tip chain, but there is no quick // way to check that. if block_hash != self . chain_state . last_block { blob :: write ( & self . storage , & block_hash , cbor ! ( block ) . unwrap ( ) . as_ref ( ) ) . expect ( " " ) ; // Compute the new chain state. In the common case, the // incoming block is a direct successor of the tip, so we // just apply the block to our current chain // state. Otherwise we use restore_chain_state() to // compute the chain state from the last state snapshot on // disk. let new_chain_state = if block . get_header ( ) . get_previous_header ( ) == self . chain_state . last_block { let mut new_chain_state = self . chain_state . clone ( ) ; match new_chain_state . verify_block ( & block_hash , & block ) { Ok ( ( ) ) => Ok ( new_chain_state ) , Err ( err ) => Err ( err . into ( ) ) } } else { restore_chain_state ( & self . storage , & self . genesis_data , & block_hash ) } ; match new_chain_state { Ok ( new_chain_state ) => { assert_eq ! ( new_chain_state last_block block_hash ) ; if new_chain_state . chain_length > self . chain_state . chain_length { info ! ( " " block_hash new_chain_state last_date self chain_state chain_length new_chain_state chain_length ) ; self . chain_state = new_chain_state ; tag :: write_hash ( & self . storage , & LOCAL_BLOCKCHAIN_TIP_TAG , & block_hash ) ; } else { info ! ( " " block_hash new_chain_state last_date new_chain_state chain_length self chain_state chain_length ) ; } } Err ( err ) => error ! ( " " block_hash err ) } } // Process previously received children of this block. if let Some ( children ) = self . unconnected_blocks . remove ( & block_hash ) { for ( child_hash , child_block ) in children { info ! ( " " child_hash ) ; self . handle_connected_block ( child_hash , child_block ) ; } } }
Handle a block whose ancestors are on disk.
Handle a block whose ancestors are on disk .
&mut self
block_hash
BlockHash
block
Block