lnwallet: create channeldb.go add serialization methods for OpenChannel

This commit is contained in:
Olaoluwa Osuntokun 2015-12-25 17:00:20 -06:00
parent c2403d4b2d
commit 8e5f028eea

@ -13,8 +13,35 @@ import (
"github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/waddrmgr"
"github.com/btcsuite/btcwallet/walletdb" "github.com/btcsuite/btcwallet/walletdb"
) )
var (
// Namespace bucket keys.
lightningNamespaceKey = []byte("ln-wallet")
waddrmgrNamespaceKey = []byte("waddrmgr")
wtxmgrNamespaceKey = []byte("wtxmgr")
openChannelBucket = []byte("o-chans")
closedChannelBucket = []byte("c-chans")
fundingTxKey = []byte("funding")
endian = binary.BigEndian
)
// ChannelDB...
type ChannelDB struct {
// TODO(roasbeef): caching, etc?
wallet *LightningWallet
namespace walletdb.Namespace
}
func NewChannelDB(wallet *LightningWallet, n walletdb.Namespace) *ChannelDB {
return &ChannelDB{wallet, n}
}
// OpenChannelState... // OpenChannelState...
// TODO(roasbeef): trim... // TODO(roasbeef): store only the essentials? optimize space...
// TODO(roasbeef): switch to "column store"
type OpenChannelState struct { type OpenChannelState struct {
// Hash? or Their current pubKey? // Hash? or Their current pubKey?
// TODO(roasbeef): switch to Tadge's LNId // TODO(roasbeef): switch to Tadge's LNId
@ -42,16 +69,13 @@ type OpenChannelState struct {
// their signature which lets us spend our version of the commitment // their signature which lets us spend our version of the commitment
// transaction. // transaction.
TheirCommitTx *wire.MsgTx TheirCommitTx *wire.MsgTx
OurCommitTx *wire.MsgTx OurCommitTx *wire.MsgTx // TODO(roasbeef): store hash instead?
TheirCommitSig []byte TheirCommitSig []byte // TODO(roasbeef): fixed length?, same w/ redeem
// The final funding transaction. Kept wallet-related records. // The final funding transaction. Kept wallet-related records.
FundingTx *wire.MsgTx FundingTx *wire.MsgTx
// TODO(roasbeef): instead store a btcutil.Address here? Otherwise key MultiSigKey *btcec.PrivateKey
// is stored unencrypted! Use manager.Encrypt() when storing.
MultiSigKey *btcec.PrivateKey
// TODO(roasbeef): encrypt also, or store in waddrmanager?
FundingRedeemScript []byte FundingRedeemScript []byte
// Current revocation for their commitment transaction. However, since // Current revocation for their commitment transaction. However, since
@ -74,3 +98,231 @@ type OpenChannelState struct {
TotalSatoshisReceived uint64 TotalSatoshisReceived uint64
CreationTime time.Time CreationTime time.Time
} }
// Encode...
// TODO(roasbeef): checksum
func (o *OpenChannelState) Encode(b io.Writer, addrManager *waddrmgr.Manager) error {
if _, err := b.Write(o.TheirLNID[:]); err != nil {
return err
}
if _, err := b.Write(o.ChanID[:]); err != nil {
return err
}
if err := binary.Write(b, endian, uint64(o.MinFeePerKb)); err != nil {
return err
}
encryptedPriv, err := addrManager.Encrypt(waddrmgr.CKTPrivate,
o.OurCommitKey.Serialize())
if err != nil {
return err
}
if _, err := b.Write(encryptedPriv); err != nil {
return err
}
if _, err := b.Write(o.TheirCommitKey.SerializeCompressed()); err != nil {
return err
}
if err := binary.Write(b, endian, uint64(o.Capacity)); err != nil {
return err
}
if err := binary.Write(b, endian, uint64(o.OurBalance)); err != nil {
return err
}
if err := binary.Write(b, endian, uint64(o.TheirBalance)); err != nil {
return err
}
if err := o.TheirCommitTx.Serialize(b); err != nil {
return err
}
if err := o.OurCommitTx.Serialize(b); err != nil {
return err
}
if _, err := b.Write(o.TheirCommitSig[:]); err != nil {
return err
}
if err := o.FundingTx.Serialize(b); err != nil {
return err
}
encryptedPriv, err = addrManager.Encrypt(waddrmgr.CKTPrivate,
o.MultiSigKey.Serialize())
if err != nil {
return err
}
if _, err := b.Write(encryptedPriv); err != nil {
return err
}
if _, err := b.Write(o.FundingRedeemScript); err != nil {
return err
}
if _, err := b.Write(o.TheirCurrentRevocation[:]); err != nil {
return err
}
// TODO(roasbeef): serialize shachains
if _, err := b.Write([]byte(o.OurDeliveryAddress.EncodeAddress())); err != nil {
return err
}
if _, err := b.Write([]byte(o.TheirDeliveryAddress.EncodeAddress())); err != nil {
return err
}
if err := binary.Write(b, endian, o.CsvDelay); err != nil {
return err
}
if err := binary.Write(b, endian, o.NumUpdates); err != nil {
return err
}
if err := binary.Write(b, endian, o.TotalSatoshisSent); err != nil {
return err
}
if err := binary.Write(b, endian, o.TotalSatoshisReceived); err != nil {
return err
}
if err := binary.Write(b, endian, o.CreationTime.Unix()); err != nil {
return err
}
return nil
}
// Decode...
func (o *OpenChannelState) Decode(b io.Reader, addrManager *waddrmgr.Manager) error {
var scratch [8]byte
if _, err := b.Read(o.TheirLNID[:]); err != nil {
return err
}
if _, err := b.Read(o.ChanID[:]); err != nil {
return err
}
if _, err := b.Read(scratch[:]); err != nil {
return err
}
o.MinFeePerKb = btcutil.Amount(endian.Uint64(scratch[:]))
// nonce + serPrivKey + mac
var encryptedPriv [24 + 32 + 16]byte
if _, err := b.Read(encryptedPriv[:]); err != nil {
return err
}
decryptedPriv, err := addrManager.Decrypt(waddrmgr.CKTPrivate, encryptedPriv[:])
if err != nil {
return err
}
o.OurCommitKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), decryptedPriv)
var serPubKey [33]byte
if _, err := b.Read(serPubKey[:]); err != nil {
return err
}
o.TheirCommitKey, err = btcec.ParsePubKey(serPubKey[:], btcec.S256())
if err != nil {
return err
}
if _, err := b.Read(scratch[:]); err != nil {
return err
}
o.Capacity = btcutil.Amount(endian.Uint64(scratch[:]))
if _, err := b.Read(scratch[:]); err != nil {
return err
}
o.OurBalance = btcutil.Amount(endian.Uint64(scratch[:]))
if _, err := b.Read(scratch[:]); err != nil {
return err
}
o.TheirBalance = btcutil.Amount(endian.Uint64(scratch[:]))
o.TheirCommitTx = wire.NewMsgTx()
if err := o.TheirCommitTx.Deserialize(b); err != nil {
return err
}
o.OurCommitTx = wire.NewMsgTx()
if err := o.OurCommitTx.Deserialize(b); err != nil {
return err
}
var sig [64]byte
if _, err := b.Read(sig[:]); err != nil {
return err
}
o.TheirCommitSig = sig[:]
if err != nil {
return err
}
o.FundingTx = wire.NewMsgTx()
if err := o.FundingTx.Deserialize(b); err != nil {
return err
}
if _, err := b.Read(encryptedPriv[:]); err != nil {
return err
}
decryptedPriv, err = addrManager.Decrypt(waddrmgr.CKTPrivate, encryptedPriv[:])
if err != nil {
return err
}
o.MultiSigKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), decryptedPriv)
var redeemScript [71]byte
if _, err := b.Read(redeemScript[:]); err != nil {
return err
}
o.FundingRedeemScript = redeemScript[:]
if _, err := b.Read(o.TheirCurrentRevocation[:]); err != nil {
return err
}
var addr [34]byte
if _, err := b.Read(addr[:]); err != nil {
return err
}
o.OurDeliveryAddress, err = btcutil.DecodeAddress(string(addr[:]), ActiveNetParams)
if err != nil {
return err
}
if _, err := b.Read(addr[:]); err != nil {
return err
}
o.TheirDeliveryAddress, err = btcutil.DecodeAddress(string(addr[:]), ActiveNetParams)
if err != nil {
return err
}
if err := binary.Read(b, endian, &o.CsvDelay); err != nil {
return err
}
if err := binary.Read(b, endian, &o.NumUpdates); err != nil {
return err
}
if err := binary.Read(b, endian, &o.TotalSatoshisSent); err != nil {
return err
}
if err := binary.Read(b, endian, &o.TotalSatoshisReceived); err != nil {
return err
}
var unix int64
if err := binary.Read(b, endian, &unix); err != nil {
return err
}
o.CreationTime = time.Unix(unix, 0)
return nil
}
func newOpenChannelState(ID [32]byte) *OpenChannelState {
return &OpenChannelState{TheirLNID: ID}
}