// ChainTip returns the latest filter header and height known to the
// FilterHeaderStore.
429587
func (f *FilterHeaderStore) ChainTip() (*chainhash.Hash, uint32, error) {
	// Lock store for read.
	f.mtx.RLock()
	defer f.mtx.RUnlock()

	_, tipHeight, err := f.chainTip()
	if err != nil {
		return nil, 0, fmt.Errorf("unable to fetch chain tip: %v", err)
	}

	latestHeader, err := f.readHeader(tipHeight)
	if err != nil {
		return nil, 0, fmt.Errorf("unable to read header: %v", err)
	}

	return latestHeader, tipHeight, nil
}
658147
func (c *ChannelGraph) PruneTip() (*chainhash.Hash, uint32, error) {
	var (
		tipHash   chainhash.Hash
		tipHeight uint32
	)

	err := c.db.View(func(tx *bbolt.Tx) error {
		graphMeta := tx.Bucket(graphMetaBucket)
		if graphMeta == nil {
			return ErrGraphNotFound
		}
		pruneBucket := graphMeta.Bucket(pruneLogBucket)
		if pruneBucket == nil {
			return ErrGraphNeverPruned
		}

		pruneCursor := pruneBucket.Cursor()

		// The prune key with the largest block height will be our
		// prune tip.
		k, v := pruneCursor.Last()
		if k == nil {
			return ErrGraphNeverPruned
		}

		// Once we have the prune tip, the value will be the block hash,
		// and the key the block height.
		copy(tipHash[:], v[:])
		tipHeight = byteOrder.Uint32(k[:])

		return nil
	})
	if err != nil {
		return nil, 0, err
	}

	return &tipHash, tipHeight, nil
}
216084
func (r *FlatChain) ChainFlat(h FlatHandler) FlatChains {
	fh := NewFlatChain(h, r.log)
	r.Chain(fh)
	return fh
}
86368
func (b *blockManager) NotificationsSinceHeight(
	height uint32) ([]blockntfns.BlockNtfn, uint32, error) {

	b.newFilterHeadersMtx.RLock()
	defer b.newFilterHeadersMtx.RUnlock()

	bestHeight := b.filterHeaderTip

	// If a height of 0 is provided by the caller, then a backlog of
	// notifications is not needed.
	if height == 0 {
		return nil, bestHeight, nil
	}

	// If the best height matches the filter header tip, then we're done and
	// don't need to proceed any further.
	if bestHeight == height {
		return nil, bestHeight, nil
	}

	// If the request has a height later than a height we've yet to come
	// across in the chain, we'll return an error to indicate so to the
	// caller.
	if height > bestHeight {
		return nil, 0, fmt.Errorf("request with height %d is greater "+
			"than best height known %d", height, bestHeight)
	}

	// Otherwise, we need to read block headers from disk to deliver a
	// backlog to the caller before we proceed.
	blocks := make([]blockntfns.BlockNtfn, 0, bestHeight-height)
	for i := height + 1; i <= bestHeight; i++ {
		header, err := b.server.BlockHeaders.FetchHeaderByHeight(i)
		if err != nil {
			return nil, 0, err
		}

		blocks = append(blocks, blockntfns.NewBlockConnected(*header, i))
	}

	return blocks, bestHeight, nil
}
677703
func cropToRightmostSubchain(m MetaContext, links []*ChainLink, eldest keybase1.KID, uid keybase1.UID) (ChainLinks, error) {
	// Check for a totally empty chain (that is, a totally new account).
	if len(links) == 0 {
		return nil, nil
	}
	// Confirm that the last link is not stubbed. This would prevent us from
	// reading the eldest_kid, so the server should never do it.
	lastLink := links[len(links)-1]
	if lastLink.IsStubbed() {
		return nil, errors.New("the last chain link is unexpectedly stubbed in GetCurrentSunchain")
	}
	// Check whether the eldest KID doesn't match the latest link. That means
	// the account has just been reset, and so as with a new account, there is
	// no current subchain.
	if !lastLink.ToEldestKID().Equal(eldest) {
		return nil, nil
	}
	// The usual case: The eldest kid we're looking for matches the latest
	// link, and we need to loop backwards through every pair of links we have.
	// If we find a subchain start, return that subslice of links.
	for i := len(links) - 1; i > 0; i-- {
		curr := links[i]
		prev := links[i-1]
		isStart, err := isSubchainStart(m, curr, prev, uid)
		if err != nil {
			return nil, err
		}
		if isStart {
			return links[i:], nil
		}
	}
	// If we didn't find a start anywhere in the middle of the chain, then this
	// user has no resets, and we'll return the whole chain. Sanity check that
	// we actually loaded everything back to seqno 1. (Anything else would be
	// some kind of bug in chain loading.)
	if links[0].GetSeqno() != 1 {
		return nil, errors.New("chain ended unexpectedly before seqno 1 in GetCurrentSubchain")
	}

	// In this last case, we're returning the whole chain.
	return links, nil
}
401697
func (a *ActionWrap) ChainLastAction(f ActionInterface) ActionInterface {
	return a.action.ChainLastAction(f)
}
305493
func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error {
	c.Lock()
	defer c.Unlock()

	return c.Db.Update(func(tx *bbolt.Tx) error {
		return c.Packager.SetFwdFilter(tx, height, fwdFilter)
	})
}
880968
func (c CrossOriginResourceSharing) Filter(req *Request, resp *Response, chain *FilterChain) {
	origin := req.Request.Header.Get(HEADER_Origin)
	if len(origin) == 0 {
		if trace {
			traceLogger.Print("no Http header Origin set")
		}
		chain.ProcessFilter(req, resp)
		return
	}
	if !c.isOriginAllowed(origin) { // check whether this origin is allowed
		if trace {
			traceLogger.Printf("HTTP Origin:%s is not part of %v, neither matches any part of %v", origin, c.AllowedDomains, c.allowedOriginPatterns)
		}
		chain.ProcessFilter(req, resp)
		return
	}
	if req.Request.Method != "OPTIONS" {
		c.doActualRequest(req, resp)
		chain.ProcessFilter(req, resp)
		return
	}
	if acrm := req.Request.Header.Get(HEADER_AccessControlRequestMethod); acrm != "" {
		c.doPreflightRequest(req, resp)
	} else {
		c.doActualRequest(req, resp)
		chain.ProcessFilter(req, resp)
		return
	}
}
281240
func NewChainIndexer(chainDb ethdb.Database, indexDb ethdb.Database, backend ChainIndexerBackend, section, confirm uint64, throttling time.Duration, kind string) *ChainIndexer {
	c := &ChainIndexer{
		chainDb:     chainDb,
		indexDb:     indexDb,
		backend:     backend,
		update:      make(chan struct{}, 1),
		quit:        make(chan chan error),
		sectionSize: section,
		confirmsReq: confirm,
		throttling:  throttling,
		log:         log.New("type", kind),
	}
	// Initialize database dependent fields and start the updater
	c.loadValidSections()
	c.ctx, c.ctxCancel = context.WithCancel(context.Background())

	go c.updateLoop()

	return c
}
1313433
func NewFilteredBlockDisconnectedNtfn(height int32, header string) *FilteredBlockDisconnectedNtfn {
	return &FilteredBlockDisconnectedNtfn{
		Height: height,
		Header: header,
	}
}
706243
func (c *Chain) Add(filter interface{}) {
	switch filter.(type) {
	case Filter:
		break
	case FilterFunc:
		break
	case func(*Update) bool:
		break
	default:
		panic("telebot: unsupported filter type")
	}

	c.Filters = append(c.Filters, filter)
}
536179
func NewCfFilteredChainView(node *neutrino.ChainService) (*CfFilteredChainView, error) {
	return &CfFilteredChainView{
		blockQueue:    newBlockEventQueue(),
		quit:          make(chan struct{}),
		rescanErrChan: make(chan error),
		chainFilter:   make(map[wire.OutPoint][]byte),
		p2pNode:       node,
	}, nil
}
874725
func (g *gossipServiceImpl) UpdateLedgerHeight(height uint64, chainID common.ChainID) {
	gc := g.chanState.getGossipChannelByChainID(chainID)
	if gc == nil {
		g.logger.Warning("No such channel", chainID)
		return
	}
	gc.UpdateLedgerHeight(height)
}
335689
func (f *FilterHeaderStore) FetchHeaderByHeight(height uint32) (*chainhash.Hash, error) {
	// Lock store for read.
	f.mtx.RLock()
	defer f.mtx.RUnlock()

	return f.readHeader(height)
}
445285
func (t *TowerDB) GetLookoutTip() (*chainntnfs.BlockEpoch, error) {
	var epoch *chainntnfs.BlockEpoch
	err := t.db.View(func(tx *bbolt.Tx) error {
		lookoutTip := tx.Bucket(lookoutTipBkt)
		if lookoutTip == nil {
			return ErrUninitializedDB
		}

		epoch = getLookoutEpoch(lookoutTip)

		return nil
	})
	if err != nil {
		return nil, err
	}

	return epoch, nil
}
1130880
func (c *chainView) Tip() *blockNode {
	c.mtx.Lock()
	tip := c.tip()
	c.mtx.Unlock()
	return tip
}
781841
func (f *FilterHeaderStore) readHeader(height uint32) (*chainhash.Hash, error) {
	seekDistance := uint64(height) * 32

	rawHeader, err := f.readRaw(seekDistance)
	if err != nil {
		return nil, err
	}

	return chainhash.NewHash(rawHeader)
}