// AddBlock write the block into blocks bucket, add the pair of block hash and pre block hash into // tree in the block depth. func (bt *BlockTree) AddBlock(b *coin.Block) error { return UpdateTx(func(tx *bolt.Tx) error { blocks := tx.Bucket(bt.blocks.Name) // can't store block if it's not genesis block and has no parent. if b.Seq() > 0 && b.PreHashHeader() == emptyHash { return errNoParent } // check if the block already exist. hash := b.HashHeader() if blk := blocks.Get(hash[:]); blk != nil { return errBlockExist } // write block into blocks bucket. if err := setBlock(blocks, b); err != nil { return err } // get tree bucket. tree := tx.Bucket(bt.tree.Name) // the pre hash must be in depth - 1. if b.Seq() > 0 { preHash := b.PreHashHeader() parentHashPair, err := getHashPairInDepth(tree, b.Seq()-1, func(hp coin.HashPair) bool { return hp.Hash == preHash }) if err != nil { return err } if len(parentHashPair) == 0 { return errWrongParent } } hp := coin.HashPair{hash, b.Head.PrevHash} // get block pairs in the depth hashPairs, err := getHashPairInDepth(tree, b.Seq(), allPairs) if err != nil { return err } if len(hashPairs) == 0 { // no hash pair exist in the depth. // write the hash pair into tree. return setHashPairInDepth(tree, b.Seq(), []coin.HashPair{hp}) } // check dup block if containHash(hashPairs, hp) { return errBlockExist } hashPairs = append(hashPairs, hp) return setHashPairInDepth(tree, b.Seq(), hashPairs) }) }
// RemoveBlock remove block from blocks bucket and tree bucket. // can't remove block if it has children. func (bt *BlockTree) RemoveBlock(b *coin.Block) error { return UpdateTx(func(tx *bolt.Tx) error { // delete block in blocks bucket. blocks := tx.Bucket(bt.blocks.Name) hash := b.HashHeader() if err := blocks.Delete(hash[:]); err != nil { return err } // get tree bucket. tree := tx.Bucket(bt.tree.Name) // check if this block has children has, err := hasChild(tree, *b) if err != nil { return err } if has { return errHasChild } // get block hash pairs in depth hashPairs, err := getHashPairInDepth(tree, b.Seq(), func(hp coin.HashPair) bool { return true }) if err != nil { return err } // remove block hash pair in tree. ps := removePairs(hashPairs, coin.HashPair{hash, b.PreHashHeader()}) if len(ps) == 0 { tree.Delete(itob(b.Seq())) return nil } // update the hash pairs in tree. return setHashPairInDepth(tree, b.Seq(), ps) }) }