nodes.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. package channeldb
  2. import (
  3. "bytes"
  4. "io"
  5. "net"
  6. "time"
  7. "github.com/btcsuite/btcd/btcec/v2"
  8. "github.com/btcsuite/btcd/wire"
  9. "github.com/lightningnetwork/lnd/kvdb"
  10. )
  11. var (
  12. // nodeInfoBucket stores metadata pertaining to nodes that we've had
  13. // direct channel-based correspondence with. This bucket allows one to
  14. // query for all open channels pertaining to the node by exploring each
  15. // node's sub-bucket within the openChanBucket.
  16. nodeInfoBucket = []byte("nib")
  17. )
  18. // LinkNode stores metadata related to node's that we have/had a direct
  19. // channel open with. Information such as the Bitcoin network the node
  20. // advertised, and its identity public key are also stored. Additionally, this
  21. // struct and the bucket its stored within have store data similar to that of
  22. // Bitcoin's addrmanager. The TCP address information stored within the struct
  23. // can be used to establish persistent connections will all channel
  24. // counterparties on daemon startup.
  25. //
  26. // TODO(roasbeef): also add current OnionKey plus rotation schedule?
  27. // TODO(roasbeef): add bitfield for supported services
  28. // - possibly add a wire.NetAddress type, type
  29. type LinkNode struct {
  30. // Network indicates the Bitcoin network that the LinkNode advertises
  31. // for incoming channel creation.
  32. Network wire.BitcoinNet
  33. // IdentityPub is the node's current identity public key. Any
  34. // channel/topology related information received by this node MUST be
  35. // signed by this public key.
  36. IdentityPub *btcec.PublicKey
  37. // LastSeen tracks the last time this node was seen within the network.
  38. // A node should be marked as seen if the daemon either is able to
  39. // establish an outgoing connection to the node or receives a new
  40. // incoming connection from the node. This timestamp (stored in unix
  41. // epoch) may be used within a heuristic which aims to determine when a
  42. // channel should be unilaterally closed due to inactivity.
  43. //
  44. // TODO(roasbeef): replace with block hash/height?
  45. // * possibly add a time-value metric into the heuristic?
  46. LastSeen time.Time
  47. // Addresses is a list of IP address in which either we were able to
  48. // reach the node over in the past, OR we received an incoming
  49. // authenticated connection for the stored identity public key.
  50. Addresses []net.Addr
  51. // db is the database instance this node was fetched from. This is used
  52. // to sync back the node's state if it is updated.
  53. db *LinkNodeDB
  54. }
  55. // NewLinkNode creates a new LinkNode from the provided parameters, which is
  56. // backed by an instance of a link node DB.
  57. func NewLinkNode(db *LinkNodeDB, bitNet wire.BitcoinNet, pub *btcec.PublicKey,
  58. addrs ...net.Addr) *LinkNode {
  59. return &LinkNode{
  60. Network: bitNet,
  61. IdentityPub: pub,
  62. LastSeen: time.Now(),
  63. Addresses: addrs,
  64. db: db,
  65. }
  66. }
  67. // UpdateLastSeen updates the last time this node was directly encountered on
  68. // the Lightning Network.
  69. func (l *LinkNode) UpdateLastSeen(lastSeen time.Time) error {
  70. l.LastSeen = lastSeen
  71. return l.Sync()
  72. }
  73. // AddAddress appends the specified TCP address to the list of known addresses
  74. // this node is/was known to be reachable at.
  75. func (l *LinkNode) AddAddress(addr net.Addr) error {
  76. for _, a := range l.Addresses {
  77. if a.String() == addr.String() {
  78. return nil
  79. }
  80. }
  81. l.Addresses = append(l.Addresses, addr)
  82. return l.Sync()
  83. }
  84. // Sync performs a full database sync which writes the current up-to-date data
  85. // within the struct to the database.
  86. func (l *LinkNode) Sync() error {
  87. // Finally update the database by storing the link node and updating
  88. // any relevant indexes.
  89. return kvdb.Update(l.db.backend, func(tx kvdb.RwTx) error {
  90. nodeMetaBucket := tx.ReadWriteBucket(nodeInfoBucket)
  91. if nodeMetaBucket == nil {
  92. return ErrLinkNodesNotFound
  93. }
  94. return putLinkNode(nodeMetaBucket, l)
  95. }, func() {})
  96. }
  97. // putLinkNode serializes then writes the encoded version of the passed link
  98. // node into the nodeMetaBucket. This function is provided in order to allow
  99. // the ability to re-use a database transaction across many operations.
  100. func putLinkNode(nodeMetaBucket kvdb.RwBucket, l *LinkNode) error {
  101. // First serialize the LinkNode into its raw-bytes encoding.
  102. var b bytes.Buffer
  103. if err := serializeLinkNode(&b, l); err != nil {
  104. return err
  105. }
  106. // Finally insert the link-node into the node metadata bucket keyed
  107. // according to the its pubkey serialized in compressed form.
  108. nodePub := l.IdentityPub.SerializeCompressed()
  109. return nodeMetaBucket.Put(nodePub, b.Bytes())
  110. }
  111. // LinkNodeDB is a database that keeps track of all link nodes.
  112. type LinkNodeDB struct {
  113. backend kvdb.Backend
  114. }
  115. // DeleteLinkNode removes the link node with the given identity from the
  116. // database.
  117. func (l *LinkNodeDB) DeleteLinkNode(identity *btcec.PublicKey) error {
  118. return kvdb.Update(l.backend, func(tx kvdb.RwTx) error {
  119. return deleteLinkNode(tx, identity)
  120. }, func() {})
  121. }
  122. func deleteLinkNode(tx kvdb.RwTx, identity *btcec.PublicKey) error {
  123. nodeMetaBucket := tx.ReadWriteBucket(nodeInfoBucket)
  124. if nodeMetaBucket == nil {
  125. return ErrLinkNodesNotFound
  126. }
  127. pubKey := identity.SerializeCompressed()
  128. return nodeMetaBucket.Delete(pubKey)
  129. }
  130. // FetchLinkNode attempts to lookup the data for a LinkNode based on a target
  131. // identity public key. If a particular LinkNode for the passed identity public
  132. // key cannot be found, then ErrNodeNotFound if returned.
  133. func (l *LinkNodeDB) FetchLinkNode(identity *btcec.PublicKey) (*LinkNode, error) {
  134. var linkNode *LinkNode
  135. err := kvdb.View(l.backend, func(tx kvdb.RTx) error {
  136. node, err := fetchLinkNode(tx, identity)
  137. if err != nil {
  138. return err
  139. }
  140. linkNode = node
  141. return nil
  142. }, func() {
  143. linkNode = nil
  144. })
  145. return linkNode, err
  146. }
  147. func fetchLinkNode(tx kvdb.RTx, targetPub *btcec.PublicKey) (*LinkNode, error) {
  148. // First fetch the bucket for storing node metadata, bailing out early
  149. // if it hasn't been created yet.
  150. nodeMetaBucket := tx.ReadBucket(nodeInfoBucket)
  151. if nodeMetaBucket == nil {
  152. return nil, ErrLinkNodesNotFound
  153. }
  154. // If a link node for that particular public key cannot be located,
  155. // then exit early with an ErrNodeNotFound.
  156. pubKey := targetPub.SerializeCompressed()
  157. nodeBytes := nodeMetaBucket.Get(pubKey)
  158. if nodeBytes == nil {
  159. return nil, ErrNodeNotFound
  160. }
  161. // Finally, decode and allocate a fresh LinkNode object to be returned
  162. // to the caller.
  163. nodeReader := bytes.NewReader(nodeBytes)
  164. return deserializeLinkNode(nodeReader)
  165. }
  166. // TODO(roasbeef): update link node addrs in server upon connection
  167. // FetchAllLinkNodes starts a new database transaction to fetch all nodes with
  168. // whom we have active channels with.
  169. func (l *LinkNodeDB) FetchAllLinkNodes() ([]*LinkNode, error) {
  170. var linkNodes []*LinkNode
  171. err := kvdb.View(l.backend, func(tx kvdb.RTx) error {
  172. nodes, err := fetchAllLinkNodes(tx)
  173. if err != nil {
  174. return err
  175. }
  176. linkNodes = nodes
  177. return nil
  178. }, func() {
  179. linkNodes = nil
  180. })
  181. if err != nil {
  182. return nil, err
  183. }
  184. return linkNodes, nil
  185. }
  186. // fetchAllLinkNodes uses an existing database transaction to fetch all nodes
  187. // with whom we have active channels with.
  188. func fetchAllLinkNodes(tx kvdb.RTx) ([]*LinkNode, error) {
  189. nodeMetaBucket := tx.ReadBucket(nodeInfoBucket)
  190. if nodeMetaBucket == nil {
  191. return nil, ErrLinkNodesNotFound
  192. }
  193. var linkNodes []*LinkNode
  194. err := nodeMetaBucket.ForEach(func(k, v []byte) error {
  195. if v == nil {
  196. return nil
  197. }
  198. nodeReader := bytes.NewReader(v)
  199. linkNode, err := deserializeLinkNode(nodeReader)
  200. if err != nil {
  201. return err
  202. }
  203. linkNodes = append(linkNodes, linkNode)
  204. return nil
  205. })
  206. if err != nil {
  207. return nil, err
  208. }
  209. return linkNodes, nil
  210. }
  211. func serializeLinkNode(w io.Writer, l *LinkNode) error {
  212. var buf [8]byte
  213. byteOrder.PutUint32(buf[:4], uint32(l.Network))
  214. if _, err := w.Write(buf[:4]); err != nil {
  215. return err
  216. }
  217. serializedID := l.IdentityPub.SerializeCompressed()
  218. if _, err := w.Write(serializedID); err != nil {
  219. return err
  220. }
  221. seenUnix := uint64(l.LastSeen.Unix())
  222. byteOrder.PutUint64(buf[:], seenUnix)
  223. if _, err := w.Write(buf[:]); err != nil {
  224. return err
  225. }
  226. numAddrs := uint32(len(l.Addresses))
  227. byteOrder.PutUint32(buf[:4], numAddrs)
  228. if _, err := w.Write(buf[:4]); err != nil {
  229. return err
  230. }
  231. for _, addr := range l.Addresses {
  232. if err := serializeAddr(w, addr); err != nil {
  233. return err
  234. }
  235. }
  236. return nil
  237. }
  238. func deserializeLinkNode(r io.Reader) (*LinkNode, error) {
  239. var (
  240. err error
  241. buf [8]byte
  242. )
  243. node := &LinkNode{}
  244. if _, err := io.ReadFull(r, buf[:4]); err != nil {
  245. return nil, err
  246. }
  247. node.Network = wire.BitcoinNet(byteOrder.Uint32(buf[:4]))
  248. var pub [33]byte
  249. if _, err := io.ReadFull(r, pub[:]); err != nil {
  250. return nil, err
  251. }
  252. node.IdentityPub, err = btcec.ParsePubKey(pub[:])
  253. if err != nil {
  254. return nil, err
  255. }
  256. if _, err := io.ReadFull(r, buf[:]); err != nil {
  257. return nil, err
  258. }
  259. node.LastSeen = time.Unix(int64(byteOrder.Uint64(buf[:])), 0)
  260. if _, err := io.ReadFull(r, buf[:4]); err != nil {
  261. return nil, err
  262. }
  263. numAddrs := byteOrder.Uint32(buf[:4])
  264. node.Addresses = make([]net.Addr, numAddrs)
  265. for i := uint32(0); i < numAddrs; i++ {
  266. addr, err := deserializeAddr(r)
  267. if err != nil {
  268. return nil, err
  269. }
  270. node.Addresses[i] = addr
  271. }
  272. return node, nil
  273. }