// DirBlockLocatorFromHash returns a block locator for the passed block hash. // See BlockLocator for details on the algotirhm used to create a block locator. // // In addition to the general algorithm referenced above, there are a couple of // special cases which are handled: // // - If the genesis hash is passed, there are no previous hashes to add and // therefore the block locator will only consist of the genesis hash // - If the passed hash is not currently known, the block locator will only // consist of the passed hash func DirBlockLocatorFromHash(hash *wire.ShaHash) blockchain.BlockLocator { // The locator contains the requested hash at the very least. locator := make(blockchain.BlockLocator, 0, wire.MaxBlockLocatorsPerMsg) locator = append(locator, hash) h, _ := common.HexToHash(common.GENESIS_DIR_BLOCK_HASH) genesisHash := wire.FactomHashToShaHash(h) // Nothing more to do if a locator for the genesis hash was requested. if genesisHash.IsEqual(hash) { return locator } // Attempt to find the height of the block that corresponds to the // passed hash, and if it's on a side chain, also find the height at // which it forks from the main chain. blockHeight := int64(-1) // Generate the block locators according to the algorithm described in // in the BlockLocator comment and make sure to leave room for the // final genesis hash. dblock, _ := db.FetchDBlockByHash(hash.ToFactomHash()) if dblock != nil { blockHeight = int64(dblock.Header.DBHeight) } increment := int64(1) for len(locator) < wire.MaxBlockLocatorsPerMsg-1 { // Once there are 10 locators, exponentially increase the // distance between each block locator. if len(locator) > 10 { increment *= 2 } blockHeight -= increment if blockHeight < 1 { break } blk, _ := db.FetchDBlockByHeight(uint32(blockHeight)) if blk == nil { continue } else if blk.DBHash == nil { blk.DBHash, _ = common.CreateHash(blk) } locator = append(locator, wire.FactomHashToShaHash(blk.DBHash)) } // Append the appropriate genesis block. locator = append(locator, genesisHash) return locator }
// FetchHeightRange looks up a range of blocks by the start and ending // heights. Fetch is inclusive of the start height and exclusive of the // ending height. To fetch all hashes from the start height until no // more are present, use the special id `AllShas'. func (db *LevelDb) FetchHeightRange(startHeight, endHeight int64) (rshalist []wire.ShaHash, err error) { var endidx int64 if endHeight == database.AllShas { endidx = startHeight + wire.MaxBlocksPerMsg } else { endidx = endHeight } shalist := make([]wire.ShaHash, 0, endidx-startHeight) for height := startHeight; height < endidx; height++ { // TODO(drahn) fix blkFile from height dbhash, lerr := db.FetchDBHashByHeight(uint32(height)) if lerr != nil || dbhash == nil { break } sha := wire.FactomHashToShaHash(dbhash) shalist = append(shalist, *sha) } if err != nil { return } //log.Tracef("FetchIdxRange idx %v %v returned %v shas err %v", startHeight, endHeight, len(shalist), err) return shalist, nil }
// handleECBlockMsg is invoked when a peer receives a entry credit block // message. func (p *peer) handleECBlockMsg(msg *wire.MsgECBlock, buf []byte) { headerHash, err := msg.ECBlock.HeaderHash() if err != nil { panic(err) } hash := wire.FactomHashToShaHash(headerHash) iv := wire.NewInvVect(wire.InvTypeFactomEntryCreditBlock, hash) p.AddKnownInventory(iv) inMsgQueue <- msg }