channeldb: switch to using a full public key to identity channel->node

This commit slightly modifies the existing structure of the channeldb
scheme to replace the former concept of a “nodeID” with simply the
compressed public key of the remote node. This change paves the way for
adding useful indexes mapping a node to all it’s active channels and
the other way around.

Additionally, the current channeldb code was written before it was
agreed by many of those implementing Lightning that a node’s ID will
simply be its compressed public key.
This commit is contained in:
Olaoluwa Osuntokun 2016-10-25 16:11:23 -07:00
parent d109bd9298
commit cb328e65c4
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
3 changed files with 42 additions and 28 deletions

View File

@ -40,10 +40,12 @@ var (
// channelLogBucket is dedicated for storing the necessary delta state
// between channel updates required to re-construct a past state in
// order to punish a counter party attempting a non-cooperative channel
// closure.
// closure. A channel log bucket is created for each node and is nested
// within a node's ID bucket.
channelLogBucket = []byte("clb")
// identityKey is the key for storing this node's current LD identity key.
// identityKey is the key for storing this node's current LD identity
// key.
identityKey = []byte("idk")
// The following prefixes are stored at the base level within the
@ -100,8 +102,9 @@ var (
// to an on-disk log, which can then subsequently be queried in order to
// "time-travel" to a prior state.
type OpenChannel struct {
// Hash? or Their current pubKey?
TheirLNID [wire.HashSize]byte
// IdentityPub is the identity public key of the remote node this
// channel has been established with.
IdentityPub *btcec.PublicKey
// The ID of a channel is the txid of the funding transaction.
ChanID *wire.OutPoint
@ -125,8 +128,8 @@ type OpenChannel struct {
// The outpoint of the final funding transaction.
FundingOutpoint *wire.OutPoint
OurMultiSigKey *btcec.PublicKey
TheirMultiSigKey *btcec.PublicKey
OurMultiSigKey *btcec.PublicKey
TheirMultiSigKey *btcec.PublicKey
FundingWitnessScript []byte
// In blocks
@ -181,7 +184,8 @@ func (c *OpenChannel) FullSync() error {
// Within this top level bucket, fetch the bucket dedicated to storing
// open channel data specific to the remote node.
nodeChanBucket, err := chanBucket.CreateBucketIfNotExists(c.TheirLNID[:])
nodePub := c.IdentityPub.SerializeCompressed()
nodeChanBucket, err := chanBucket.CreateBucketIfNotExists(nodePub)
if err != nil {
return err
}
@ -222,7 +226,7 @@ func (c *OpenChannel) UpdateCommitment(newCommitment *wire.MsgTx,
return err
}
id := c.TheirLNID[:]
id := c.IdentityPub.SerializeCompressed()
nodeChanBucket, err := chanBucket.CreateBucketIfNotExists(id)
if err != nil {
return err
@ -322,7 +326,7 @@ func (c *OpenChannel) AppendToRevocationLog(delta *ChannelDelta) error {
return err
}
id := c.TheirLNID[:]
id := c.IdentityPub.SerializeCompressed()
nodeChanBucket, err := chanBucket.CreateBucketIfNotExists(id)
if err != nil {
return err
@ -361,7 +365,8 @@ func (c *OpenChannel) FindPreviousState(updateNum uint64) (*ChannelDelta, error)
err := c.Db.store.View(func(tx *bolt.Tx) error {
chanBucket := tx.Bucket(openChannelBucket)
nodeChanBucket := chanBucket.Bucket(c.TheirLNID[:])
nodePub := c.IdentityPub.SerializeCompressed()
nodeChanBucket := chanBucket.Bucket(nodePub)
if nodeChanBucket == nil {
return ErrNoActiveChannels
}
@ -400,7 +405,8 @@ func (c *OpenChannel) CloseChannel() error {
// Within this top level bucket, fetch the bucket dedicated to storing
// open channel data specific to the remote node.
nodeChanBucket := chanBucket.Bucket(c.TheirLNID[:])
nodePub := c.IdentityPub.SerializeCompressed()
nodeChanBucket := chanBucket.Bucket(nodePub)
if nodeChanBucket == nil {
return ErrNoActiveChannels
}
@ -436,7 +442,7 @@ func (c *OpenChannel) CloseChannel() error {
// snapshot is detached from the original channel that generated it, providing
// read-only access to the current or prior state of an active channel.
type ChannelSnapshot struct {
RemoteID [wire.HashSize]byte
RemoteIdentity btcec.PublicKey
ChannelPoint *wire.OutPoint
@ -460,6 +466,7 @@ func (c *OpenChannel) Snapshot() *ChannelSnapshot {
defer c.RUnlock()
snapshot := &ChannelSnapshot{
RemoteIdentity: *c.IdentityPub,
ChannelPoint: c.ChanID,
Capacity: c.Capacity,
LocalBalance: c.OurBalance,
@ -468,7 +475,6 @@ func (c *OpenChannel) Snapshot() *ChannelSnapshot {
TotalSatoshisSent: c.TotalSatoshisSent,
TotalSatoshisReceived: c.TotalSatoshisReceived,
}
copy(snapshot.RemoteID[:], c.TheirLNID[:])
// Copy over the current set of HTLC's to ensure the caller can't
// mutate our internal state.
@ -907,7 +913,8 @@ func putChannelIDs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
copy(idKey[:3], chanIDKey)
copy(idKey[3:], b.Bytes())
return nodeChanBucket.Put(idKey, channel.TheirLNID[:])
idBytes := channel.IdentityPub.SerializeCompressed()
return nodeChanBucket.Put(idKey, idBytes)
}
func deleteChannelIDs(nodeChanBucket *bolt.Bucket, chanID []byte) error {
@ -918,8 +925,12 @@ func deleteChannelIDs(nodeChanBucket *bolt.Bucket, chanID []byte) error {
}
func fetchChannelIDs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
var (
err error
b bytes.Buffer
)
if err = writeOutpoint(&b, channel.ChanID); err != nil {
return err
}
@ -929,7 +940,10 @@ func fetchChannelIDs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
copy(idKey[3:], b.Bytes())
idBytes := nodeChanBucket.Get(idKey)
copy(channel.TheirLNID[:], idBytes)
channel.IdentityPub, err = btcec.ParsePubKey(idBytes, btcec.S256())
if err != nil {
return err
}
return nil
}

View File

@ -133,7 +133,7 @@ func createTestChannelState(cdb *DB) (*OpenChannel, error) {
}
return &OpenChannel{
TheirLNID: key,
IdentityPub: pubKey,
ChanID: id,
MinFeePerKb: btcutil.Amount(5000),
OurCommitKey: privKey.PubKey(),
@ -148,7 +148,7 @@ func createTestChannelState(cdb *DB) (*OpenChannel, error) {
FundingOutpoint: testOutpoint,
OurMultiSigKey: privKey.PubKey(),
TheirMultiSigKey: privKey.PubKey(),
FundingWitnessScript: script,
FundingWitnessScript: script,
TheirCurrentRevocation: privKey.PubKey(),
TheirCurrentRevocationHash: key,
OurDeliveryScript: script,
@ -190,8 +190,7 @@ func TestOpenChannelPutGetDelete(t *testing.T) {
t.Fatalf("unable to save and serialize channel state: %v", err)
}
nodeID := wire.ShaHash(state.TheirLNID)
openChannels, err := cdb.FetchOpenChannels(&nodeID)
openChannels, err := cdb.FetchOpenChannels(state.IdentityPub)
if err != nil {
t.Fatalf("unable to fetch open channel: %v", err)
}
@ -200,7 +199,7 @@ func TestOpenChannelPutGetDelete(t *testing.T) {
// The decoded channel state should be identical to what we stored
// above.
if !bytes.Equal(state.TheirLNID[:], newState.TheirLNID[:]) {
if !state.IdentityPub.IsEqual(newState.IdentityPub) {
t.Fatalf("their id doesn't match")
}
if !reflect.DeepEqual(state.ChanID, newState.ChanID) {
@ -328,7 +327,7 @@ func TestOpenChannelPutGetDelete(t *testing.T) {
// As the channel is now closed, attempting to fetch all open channels
// for our fake node ID should return an empty slice.
openChans, err := cdb.FetchOpenChannels(&nodeID)
openChans, err := cdb.FetchOpenChannels(state.IdentityPub)
if err != nil {
t.Fatalf("unable to fetch open channels: %v", err)
}
@ -396,8 +395,7 @@ func TestChannelStateTransition(t *testing.T) {
// The balances, new update, the HTLC's and the changes to the fake
// commitment transaction along with the modified signature should all
// have been updated.
nodeID := wire.ShaHash(channel.TheirLNID)
updatedChannel, err := cdb.FetchOpenChannels(&nodeID)
updatedChannel, err := cdb.FetchOpenChannels(channel.IdentityPub)
if err != nil {
t.Fatalf("unable to fetch updated channel: %v", err)
}
@ -469,7 +467,7 @@ func TestChannelStateTransition(t *testing.T) {
}
}
// The revocation state stored on-disk should now also be identical.
updatedChannel, err = cdb.FetchOpenChannels(&nodeID)
updatedChannel, err = cdb.FetchOpenChannels(channel.IdentityPub)
if err != nil {
t.Fatalf("unable to fetch updated channel: %v", err)
}

View File

@ -9,6 +9,7 @@ import (
"sync"
"github.com/boltdb/bolt"
"github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcd/chaincfg"
"github.com/roasbeef/btcd/wire"
)
@ -143,7 +144,7 @@ func fileExists(path string) bool {
// associated with the target nodeID. In the case that no active channels are
// known to have been created with this node, then a zero-length slice is
// returned.
func (d *DB) FetchOpenChannels(nodeID *wire.ShaHash) ([]*OpenChannel, error) {
func (d *DB) FetchOpenChannels(nodeID *btcec.PublicKey) ([]*OpenChannel, error) {
var channels []*OpenChannel
err := d.store.View(func(tx *bolt.Tx) error {
// Get the bucket dedicated to storing the meta-data for open
@ -155,7 +156,8 @@ func (d *DB) FetchOpenChannels(nodeID *wire.ShaHash) ([]*OpenChannel, error) {
// Within this top level bucket, fetch the bucket dedicated to storing
// open channel data specific to the remote node.
nodeChanBucket := openChanBucket.Bucket(nodeID[:])
pub := nodeID.SerializeCompressed()
nodeChanBucket := openChanBucket.Bucket(pub)
if nodeChanBucket == nil {
return nil
}