lnd: add new chainRegistry struct for multi-chain dispatch

This commit adds a new agent to the codebase: the chainRegistry. In a
multi-chain future, the chainRegistry will be the dispatch point
capable of mapping cross-chain parameters, and a particular chain to
the chainControl for that chain. The chainControl struct encompasses
the 3 primary interfaces used within the daemon to register for events,
and drive other workflows.
This commit is contained in:
Olaoluwa Osuntokun 2017-05-02 19:16:37 -07:00
parent 337a4a4f56
commit 04d0e099cc
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2

164
chainregistry.go Normal file

@ -0,0 +1,164 @@
package main
import (
"sync"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/roasbeef/btcd/chaincfg/chainhash"
)
// chainCode is an enum-like structure for keeping track of the chains currently
// supported within lnd.
type chainCode uint32
const (
// bitcoinChain is Bitcoin's testnet chain.
bitcoinChain chainCode = iota
// litecoinChain is Litecoin's testnet chain.
litecoinChain
)
// String returns a string representation of the target chainCode.
func (c chainCode) String() string {
switch c {
case bitcoinChain:
return "bitcoin"
case litecoinChain:
return "litecoin"
default:
return "kekcoin"
}
}
// chainControl couples the three primary interfaces lnd utilizes for a
// particular chain together. A single chainControl instance will exist for all
// the chains lnd is currently active on.
type chainControl struct {
chainIO lnwallet.BlockChainIO
chainNotifier chainntnfs.ChainNotifier
wallet *lnwallet.LightningWallet
}
var (
// bitcoinGenesis is the genesis hash of Bitcoin's testnet chain.
bitcoinGenesis = chainhash.Hash([chainhash.HashSize]byte{
0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
})
// litecoinGenesis is the genesis hash of Litecoin's testnet4 chain.
litecoinGenesis = chainhash.Hash([chainhash.HashSize]byte{
0xa0, 0x29, 0x3e, 0x4e, 0xeb, 0x3d, 0xa6, 0xe6,
0xf5, 0x6f, 0x81, 0xed, 0x59, 0x5f, 0x57, 0x88,
0x0d, 0x1a, 0x21, 0x56, 0x9e, 0x13, 0xee, 0xfd,
0xd9, 0x51, 0x28, 0x4b, 0x5a, 0x62, 0x66, 0x49,
})
// chainMap is a simple index that maps a chain's genesis hash to the
// chainCode enum for that chain.
chainMap = map[chainhash.Hash]chainCode{
bitcoinGenesis: bitcoinChain,
litecoinGenesis: litecoinChain,
}
// reverseChainMap is the inverse of the chainMap above: it maps the
// chain enum for a chain to its genesis hash.
reverseChainMap = map[chainCode]chainhash.Hash{
bitcoinChain: bitcoinGenesis,
litecoinChain: litecoinGenesis,
}
)
// chainRegistry keeps track of the current chains
type chainRegistry struct {
sync.RWMutex
activeChains map[chainCode]*chainControl
netParams map[chainCode]*bitcoinNetParams
primaryChain chainCode
}
// newChainRegistry creates a new chainRegistry.
func newChainRegistry() *chainRegistry {
return &chainRegistry{
activeChains: make(map[chainCode]*chainControl),
netParams: make(map[chainCode]*bitcoinNetParams),
}
}
// RegisterChain assigns an active chainControl instance to a target chain
// identified by its chainCode.
func (c *chainRegistry) RegisterChain(newChain chainCode, cc *chainControl) {
c.Lock()
c.activeChains[newChain] = cc
c.Unlock()
}
// LookupChain attempts to lookup an active chainControl instance for the
// target chain.
func (c *chainRegistry) LookupChain(targetChain chainCode) (*chainControl, bool) {
c.RLock()
cc, ok := c.activeChains[targetChain]
c.RUnlock()
return cc, ok
}
// LookupChainByHash attempts to look up an active chainControl which
// corresponds to the passed genesis hash.
func (c *chainRegistry) LookupChainByHash(chainHash chainhash.Hash) (*chainControl, bool) {
c.RLock()
defer c.RUnlock()
targetChain, ok := chainMap[chainHash]
if !ok {
return nil, ok
}
cc, ok := c.activeChains[targetChain]
return cc, ok
}
// RegisterPrimaryChain sets a target chain as the "home chain" for lnd.
func (c *chainRegistry) RegisterPrimaryChain(cc chainCode) {
c.Lock()
defer c.Unlock()
c.primaryChain = cc
}
// PrimaryChain returns the primary chain for this running lnd instance. The
// primary chain is considered the "home base" while the other registered
// chains are treated as secondary chains.
func (c *chainRegistry) PrimaryChain() chainCode {
c.RLock()
defer c.RUnlock()
return c.primaryChain
}
// ActiveChains returns the total number of active chains.
func (c *chainRegistry) ActiveChains() []chainCode {
c.RLock()
defer c.RUnlock()
chains := make([]chainCode, 0, len(c.activeChains))
for activeChain := range c.activeChains {
chains = append(chains, activeChain)
}
return chains
}
// NumActiveChains returns the total number of active chains.
func (c *chainRegistry) NumActiveChains() uint32 {
c.RLock()
defer c.RUnlock()
return uint32(len(c.activeChains))
}