mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
channeldb+funding: track opening height using MarkChannelAsOpen
This commit modifies the OpenChannel structure on-disk to also track that opening height of a channel. This change is being made in order to make and more light client friendly. A follow up commit will modify several areas of the codebase to use this new functionality.
This commit is contained in:
parent
373a1192ce
commit
a5113c2439
@ -70,6 +70,7 @@ var (
|
||||
satReceivedPrefix = []byte("srp")
|
||||
netFeesPrefix = []byte("ntp")
|
||||
isPendingPrefix = []byte("pdg")
|
||||
openHeightPrefix = []byte("open-height-prefix")
|
||||
|
||||
// chanIDKey stores the node, and channelID for an active channel.
|
||||
chanIDKey = []byte("cik")
|
||||
@ -129,6 +130,10 @@ const (
|
||||
// to an on-disk log, which can then subsequently be queried in order to
|
||||
// "time-travel" to a prior state.
|
||||
type OpenChannel struct {
|
||||
// OpeningHeight is the height in which this channel was officially
|
||||
// marked open.
|
||||
OpeningHeight uint32
|
||||
|
||||
// IdentityPub is the identity public key of the remote node this
|
||||
// channel has been established with.
|
||||
IdentityPub *btcec.PublicKey
|
||||
@ -356,17 +361,18 @@ func (c *OpenChannel) SyncPending(addr *net.TCPAddr) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// If a LinkNode for this identity public key already exsits, then
|
||||
// we can exit early.
|
||||
// If a LinkNode for this identity public key already exists,
|
||||
// then we can exit early.
|
||||
nodePub := c.IdentityPub.SerializeCompressed()
|
||||
if nodeInfoBucket.Get(nodePub) != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Next, we need to establish a (possibly) new LinkNode
|
||||
// relationship for this channel. The LinkNode metadata contains
|
||||
// reachability, up-time, and service bits related information.
|
||||
// TODO(roasbeef): net info shuld be in lnwire.NetAddress
|
||||
// relationship for this channel. The LinkNode metadata
|
||||
// contains reachability, up-time, and service bits related
|
||||
// information.
|
||||
// TODO(roasbeef): net info should be in lnwire.NetAddress
|
||||
linkNode := c.Db.NewLinkNode(wire.MainNet, c.IdentityPub, addr)
|
||||
|
||||
return putLinkNode(nodeInfoBucket, linkNode)
|
||||
@ -966,6 +972,9 @@ func putOpenChannel(openChanBucket *bolt.Bucket, nodeChanBucket *bolt.Bucket,
|
||||
if err := putChanIsPending(openChanBucket, channel); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := putChanOpenHeight(openChanBucket, channel); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Next, write out the fields of the channel update less frequently.
|
||||
if err := putChannelIDs(nodeChanBucket, channel); err != nil {
|
||||
@ -1053,6 +1062,9 @@ func fetchOpenChannel(openChanBucket *bolt.Bucket, nodeChanBucket *bolt.Bucket,
|
||||
if err = fetchChanIsPending(openChanBucket, channel); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := fetchChanOpenHeight(openChanBucket, channel); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return channel, nil
|
||||
}
|
||||
@ -1083,6 +1095,9 @@ func deleteOpenChannel(openChanBucket *bolt.Bucket, nodeChanBucket *bolt.Bucket,
|
||||
if err := deleteChanIsPending(openChanBucket, channelID); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := deleteChanOpenHeight(openChanBucket, channelID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Finally, delete all the fields directly within the node's channel
|
||||
// bucket.
|
||||
@ -1447,6 +1462,44 @@ func fetchChanIsPending(openChanBucket *bolt.Bucket, channel *OpenChannel) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func putChanOpenHeight(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
||||
var b bytes.Buffer
|
||||
if err := writeOutpoint(&b, channel.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keyPrefix := make([]byte, 3+b.Len())
|
||||
copy(keyPrefix[3:], b.Bytes())
|
||||
copy(keyPrefix[:3], openHeightPrefix)
|
||||
|
||||
var scratch [4]byte
|
||||
byteOrder.PutUint32(scratch[:], channel.OpeningHeight)
|
||||
return openChanBucket.Put(keyPrefix, scratch[:])
|
||||
}
|
||||
|
||||
func fetchChanOpenHeight(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
||||
var b bytes.Buffer
|
||||
if err := writeOutpoint(&b, channel.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keyPrefix := make([]byte, 3+b.Len())
|
||||
copy(keyPrefix[3:], b.Bytes())
|
||||
copy(keyPrefix[:3], openHeightPrefix)
|
||||
|
||||
openHeightBytes := openChanBucket.Get(keyPrefix)
|
||||
channel.OpeningHeight = byteOrder.Uint32(openHeightBytes)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteChanOpenHeight(openChanBucket *bolt.Bucket, chanID []byte) error {
|
||||
keyPrefix := make([]byte, 3+len(chanID))
|
||||
copy(keyPrefix[3:], chanID)
|
||||
copy(keyPrefix[:3], openHeightPrefix)
|
||||
return openChanBucket.Delete(keyPrefix)
|
||||
}
|
||||
|
||||
func putChannelIDs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
||||
// TODO(roasbeef): just pass in chanID everywhere for puts
|
||||
var b bytes.Buffer
|
||||
|
@ -666,10 +666,23 @@ func TestFetchPendingChannels(t *testing.T) {
|
||||
"got %v", 1, len(pendingChannels))
|
||||
}
|
||||
|
||||
if err := cdb.MarkChannelAsOpen(pendingChannels[0].ChanID); err != nil {
|
||||
const openHeight = 100
|
||||
err = cdb.MarkChannelAsOpen(pendingChannels[0].ChanID, openHeight)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to mark channel as open: %v", err)
|
||||
}
|
||||
|
||||
// Next, we'll re-fetch the channel to ensure that the open height was
|
||||
// properly set.
|
||||
openChans, err := cdb.FetchAllChannels()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to fetch channels: %v", err)
|
||||
}
|
||||
if openChans[0].OpeningHeight != openHeight {
|
||||
t.Fatalf("channel opening heights don't match: expected %v, "+
|
||||
"got %v", openChans[0].OpeningHeight, openHeight)
|
||||
}
|
||||
|
||||
pendingChannels, err = cdb.FetchPendingChannels()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to list pending channels: %v", err)
|
||||
@ -707,7 +720,8 @@ func TestFetchClosedChannels(t *testing.T) {
|
||||
|
||||
// Next, simulate the confirmation of the channel by marking it as
|
||||
// pending within the database.
|
||||
if err := cdb.MarkChannelAsOpen(state.ChanID); err != nil {
|
||||
const openHeight = 100
|
||||
if err := cdb.MarkChannelAsOpen(state.ChanID, openHeight); err != nil {
|
||||
t.Fatalf("unable to mark channel as open: %v", err)
|
||||
}
|
||||
|
||||
|
@ -344,6 +344,7 @@ func fetchChannels(d *DB, pendingOnly bool) ([]*OpenChannel, error) {
|
||||
return fmt.Errorf("unable to read channel for "+
|
||||
"node_key=%x: %v", k, err)
|
||||
}
|
||||
// TODO(roasbeef): simplify
|
||||
if pendingOnly {
|
||||
for _, channel := range nodeChannels {
|
||||
if channel.IsPending {
|
||||
@ -361,16 +362,17 @@ func fetchChannels(d *DB, pendingOnly bool) ([]*OpenChannel, error) {
|
||||
}
|
||||
|
||||
// MarkChannelAsOpen records the finalization of the funding process and marks
|
||||
// a channel as available for use.
|
||||
func (d *DB) MarkChannelAsOpen(outpoint *wire.OutPoint) error {
|
||||
// a channel as available for use. Additionally the height in which this
|
||||
// channel as opened will also be recorded within the database.
|
||||
func (d *DB) MarkChannelAsOpen(outpoint *wire.OutPoint, openHeight uint32) error {
|
||||
return d.Update(func(tx *bolt.Tx) error {
|
||||
openChanBucket := tx.Bucket(openChannelBucket)
|
||||
if openChanBucket == nil {
|
||||
return ErrNoActiveChannels
|
||||
}
|
||||
|
||||
// Generate the database key, which will consist of the IsPending
|
||||
// prefix followed by the channel's outpoint.
|
||||
// Generate the database key, which will consist of the
|
||||
// IsPending prefix followed by the channel's outpoint.
|
||||
var b bytes.Buffer
|
||||
if err := writeOutpoint(&b, outpoint); err != nil {
|
||||
return err
|
||||
@ -379,11 +381,20 @@ func (d *DB) MarkChannelAsOpen(outpoint *wire.OutPoint) error {
|
||||
copy(keyPrefix[3:], b.Bytes())
|
||||
copy(keyPrefix[:3], isPendingPrefix)
|
||||
|
||||
// For the database value, store a zero, since the channel is no
|
||||
// longer pending.
|
||||
scratch := make([]byte, 2)
|
||||
byteOrder.PutUint16(scratch, uint16(0))
|
||||
return openChanBucket.Put(keyPrefix, scratch)
|
||||
// For the database value, store a zero, since the channel is
|
||||
// no longer pending.
|
||||
scratch := make([]byte, 4)
|
||||
byteOrder.PutUint16(scratch[:2], uint16(0))
|
||||
if err := openChanBucket.Put(keyPrefix, scratch[:2]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Finally, we'll also store the opening height for this
|
||||
// channel as well.
|
||||
byteOrder.PutUint32(scratch, openHeight)
|
||||
copy(keyPrefix[:3], openHeightPrefix)
|
||||
|
||||
return openChanBucket.Put(keyPrefix, scratch[:])
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -922,7 +922,8 @@ func (f *fundingManager) waitForFundingConfirmation(completeChan *channeldb.Open
|
||||
// Now that the channel has been fully confirmed, we'll mark it as open
|
||||
// within the database.
|
||||
completeChan.IsPending = false
|
||||
err = f.cfg.Wallet.ChannelDB.MarkChannelAsOpen(&fundingPoint)
|
||||
err = f.cfg.Wallet.ChannelDB.MarkChannelAsOpen(&fundingPoint,
|
||||
confDetails.BlockHeight)
|
||||
if err != nil {
|
||||
fndgLog.Errorf("error setting channel pending flag to false: "+
|
||||
"%v", err)
|
||||
|
Loading…
Reference in New Issue
Block a user