package channeldb import ( "errors" "net" "github.com/btcsuite/btcd/btcec/v2" ) // AddrSource is an interface that allow us to get the addresses for a target // node. It may combine the results of multiple address sources. type AddrSource interface { // AddrsForNode returns all known addresses for the target node public // key. The returned boolean must indicate if the given node is unknown // to the backing source. AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, error) } // multiAddrSource is an implementation of AddrSource which gathers all the // known addresses for a given node from multiple backends and de-duplicates the // results. type multiAddrSource struct { sources []AddrSource } // NewMultiAddrSource constructs a new AddrSource which will query all the // provided sources for a node's addresses and will then de-duplicate the // results. func NewMultiAddrSource(sources ...AddrSource) AddrSource { return &multiAddrSource{ sources: sources, } } // AddrsForNode returns all known addresses for the target node public key. It // queries all the address sources provided and de-duplicates the results. The // returned boolean is false only if none of the backing sources know of the // node. // // NOTE: this implements the AddrSource interface. func (c *multiAddrSource) AddrsForNode(nodePub *btcec.PublicKey) (bool, []net.Addr, error) { if len(c.sources) == 0 { return false, nil, errors.New("no address sources") } // The multiple address sources will likely contain duplicate addresses, // so we use a map here to de-dup them. dedupedAddrs := make(map[string]net.Addr) // known will be set to true if any backing source is aware of the node. var known bool // Iterate over all the address sources and query each one for the // addresses it has for the node in question. for _, src := range c.sources { isKnown, addrs, err := src.AddrsForNode(nodePub) if err != nil { return false, nil, err } if isKnown { known = true } for _, addr := range addrs { dedupedAddrs[addr.String()] = addr } } // Convert the map into a list we can return. addrs := make([]net.Addr, 0, len(dedupedAddrs)) for _, addr := range dedupedAddrs { addrs = append(addrs, addr) } return known, addrs, nil } // A compile-time check to ensure that multiAddrSource implements the AddrSource // interface. var _ AddrSource = (*multiAddrSource)(nil)