2015-12-26 21:35:15 +03:00
|
|
|
package channeldb
|
2015-12-24 21:41:15 +03:00
|
|
|
|
|
|
|
import (
|
2015-12-26 03:00:44 +03:00
|
|
|
"bytes"
|
2016-03-24 08:39:52 +03:00
|
|
|
"encoding/hex"
|
2015-12-26 03:00:44 +03:00
|
|
|
"fmt"
|
2016-03-24 08:39:52 +03:00
|
|
|
"sync"
|
2015-12-24 21:41:15 +03:00
|
|
|
"time"
|
|
|
|
|
2016-03-23 04:46:30 +03:00
|
|
|
"github.com/boltdb/bolt"
|
2016-05-15 17:17:44 +03:00
|
|
|
"github.com/roasbeef/btcd/btcec"
|
|
|
|
"github.com/roasbeef/btcd/wire"
|
|
|
|
"github.com/roasbeef/btcwallet/walletdb"
|
2016-05-01 06:24:57 +03:00
|
|
|
"github.com/lightningnetwork/lnd/elkrem"
|
2016-05-15 17:17:44 +03:00
|
|
|
"github.com/roasbeef/btcutil"
|
2015-12-24 21:41:15 +03:00
|
|
|
)
|
2015-12-26 02:00:20 +03:00
|
|
|
|
|
|
|
var (
|
2016-03-24 08:39:52 +03:00
|
|
|
// openChanBucket stores all the currently open channels. This bucket
|
|
|
|
// has a second, nested bucket which is keyed by a node's ID. Additionally,
|
|
|
|
// at the base level of this bucket several prefixed keys are stored which
|
|
|
|
// house channel meta-data such as total satoshis sent, number of updates
|
|
|
|
// etc. These fields are stored at this top level rather than within a
|
|
|
|
// node's channel bucket in orer to facilitate sequential prefix scans
|
|
|
|
// to gather stats such as total satoshis received.
|
|
|
|
openChannelBucket = []byte("ocb")
|
|
|
|
|
|
|
|
// closedChannelBucket stores summarization information concerning
|
|
|
|
// previously open, but now closed channels.
|
|
|
|
closedChannelBucket = []byte("ccb")
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
channelLogBucket = []byte("clb")
|
|
|
|
|
|
|
|
// 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
|
|
|
|
// openChannelBucket. In order to retrieve a particular field for an
|
|
|
|
// active, or historic channel, append the channels ID to the prefix:
|
|
|
|
// key = prefix || chanID. Storing certain fields at the top level
|
|
|
|
// using a prefix scheme serves two purposes: first to facilitate
|
|
|
|
// sequential prefix scans, and second to eliminate write amplification
|
|
|
|
// caused by serializing/deserializing the *entire* struct with each
|
|
|
|
// update.
|
|
|
|
chanCapacityPrefix = []byte("ccp")
|
|
|
|
selfBalancePrefix = []byte("sbp")
|
|
|
|
theirBalancePrefix = []byte("tbp")
|
|
|
|
minFeePerKbPrefix = []byte("mfp")
|
|
|
|
updatePrefix = []byte("uup")
|
|
|
|
satSentPrefix = []byte("ssp")
|
|
|
|
satRecievedPrefix = []byte("srp")
|
|
|
|
netFeesPrefix = []byte("ntp")
|
|
|
|
|
|
|
|
// chanIDKey stores the node, and channelID for an active channel.
|
|
|
|
chanIDKey = []byte("cik")
|
|
|
|
|
|
|
|
// commitKeys stores both commitment keys (ours, and theirs) for an
|
|
|
|
// active channel. Our private key is stored in an encrypted format
|
|
|
|
// using channeldb's currently registered cryptoSystem.
|
|
|
|
commitKeys = []byte("ckk")
|
|
|
|
|
|
|
|
// commitTxnsKey stores the full version of both current, non-revoked
|
|
|
|
// commitment transactions in addition to the csvDelay for both.
|
|
|
|
commitTxnsKey = []byte("ctk")
|
|
|
|
|
|
|
|
// fundingTxnKey stroes the funding tx, our encrypted multi-sig key,
|
|
|
|
// and finally 2-of-2 multisig redeem script.
|
|
|
|
fundingTxnKey = []byte("fsk")
|
|
|
|
|
|
|
|
// elkremStateKey stores their current revocation hash, and our elkrem
|
|
|
|
// sender, and their elkrem reciever.
|
|
|
|
elkremStateKey = []byte("esk")
|
|
|
|
|
|
|
|
// deliveryScriptsKey stores the scripts for the final delivery in the
|
|
|
|
// case of a cooperative closure.
|
|
|
|
deliveryScriptsKey = []byte("dsk")
|
2015-12-26 02:00:20 +03:00
|
|
|
)
|
|
|
|
|
2015-12-26 21:35:15 +03:00
|
|
|
// OpenChannel...
|
2016-03-24 08:39:52 +03:00
|
|
|
// TODO(roasbeef): Copy/Clone method, so CoW on writes?
|
|
|
|
// * CoW method would allow for intelligent partial writes for updates
|
|
|
|
// TODO(roasbeef): UpdateState(func (newChan *OpenChannel) error)
|
|
|
|
// * need mutex, invarient that all reads/writes grab the mutex
|
|
|
|
// * needs to also return two slices of added then removed HTLC's
|
2015-12-26 21:35:15 +03:00
|
|
|
type OpenChannel struct {
|
|
|
|
// Hash? or Their current pubKey?
|
|
|
|
TheirLNID [wire.HashSize]byte
|
|
|
|
|
|
|
|
// The ID of a channel is the txid of the funding transaction.
|
|
|
|
ChanID [wire.HashSize]byte
|
|
|
|
|
|
|
|
MinFeePerKb btcutil.Amount
|
|
|
|
// Our reserve. Assume symmetric reserve amounts. Only needed if the
|
|
|
|
// funding type is CLTV.
|
|
|
|
//ReserveAmount btcutil.Amount
|
|
|
|
|
|
|
|
// Keys for both sides to be used for the commitment transactions.
|
|
|
|
OurCommitKey *btcec.PrivateKey
|
|
|
|
TheirCommitKey *btcec.PublicKey
|
|
|
|
|
|
|
|
// Tracking total channel capacity, and the amount of funds allocated
|
|
|
|
// to each side.
|
|
|
|
Capacity btcutil.Amount
|
|
|
|
OurBalance btcutil.Amount
|
|
|
|
TheirBalance btcutil.Amount
|
|
|
|
|
2015-12-28 23:16:55 +03:00
|
|
|
// Commitment transactions for both sides (they're asymmetric). Our
|
|
|
|
// commitment transaction includes a valid sigScript, and is ready for
|
|
|
|
// broadcast.
|
|
|
|
TheirCommitTx *wire.MsgTx
|
2016-03-24 08:39:52 +03:00
|
|
|
OurCommitTx *wire.MsgTx
|
2015-12-26 21:35:15 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// The final funding transaction. Kept for wallet-related records.
|
2015-12-26 21:35:15 +03:00
|
|
|
FundingTx *wire.MsgTx
|
|
|
|
|
|
|
|
MultiSigKey *btcec.PrivateKey
|
|
|
|
FundingRedeemScript []byte
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// In blocks
|
|
|
|
LocalCsvDelay uint32
|
|
|
|
RemoteCsvDelay uint32
|
|
|
|
|
2015-12-26 21:35:15 +03:00
|
|
|
// Current revocation for their commitment transaction. However, since
|
|
|
|
// this is the hash, and not the pre-image, we can't yet verify that
|
|
|
|
// it's actually in the chain.
|
2015-12-31 09:28:00 +03:00
|
|
|
TheirCurrentRevocation [20]byte
|
2016-03-24 08:39:52 +03:00
|
|
|
LocalElkrem *elkrem.ElkremSender
|
|
|
|
RemoteElkrem *elkrem.ElkremReceiver
|
2015-12-26 21:35:15 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// The pkScript for both sides to be used for final delivery in the case
|
|
|
|
// of a cooperative close.
|
|
|
|
OurDeliveryScript []byte
|
|
|
|
TheirDeliveryScript []byte
|
2015-12-26 21:35:15 +03:00
|
|
|
|
|
|
|
NumUpdates uint64
|
|
|
|
TotalSatoshisSent uint64
|
|
|
|
TotalSatoshisReceived uint64
|
2016-03-24 08:39:52 +03:00
|
|
|
TotalNetFees uint64 // TODO(roasbeef): total fees paid too?
|
|
|
|
CreationTime time.Time // TODO(roasbeef): last update time?
|
|
|
|
|
|
|
|
// isPrevState denotes if this instane of an OpenChannel is a previous,
|
|
|
|
// revoked channel state. If so, then the FullSynv, and UpdateState
|
|
|
|
// methods are disabled in order to prevent overiding the latest channel
|
|
|
|
// state.
|
|
|
|
// TODO(roasbeef): scrap? already have snapshots now?
|
|
|
|
isPrevState bool
|
|
|
|
|
2016-03-24 10:00:22 +03:00
|
|
|
// TODO(roasbeef): eww
|
|
|
|
Db *DB
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
sync.RWMutex
|
2015-12-26 02:00:20 +03:00
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// ChannelSnapshot....
|
|
|
|
// TODO(roasbeef): methods to roll forwards/backwards in state etc
|
|
|
|
// * use botldb cursor?
|
|
|
|
type ChannelSnapshot struct {
|
|
|
|
OpenChannel
|
2015-12-26 03:00:44 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// TODO(roasbeef): active HTLC's + their direction
|
|
|
|
updateNum uint64
|
|
|
|
deltaNamespace walletdb.Namespace
|
2015-12-26 03:00:44 +03:00
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// FindPreviousState...
|
|
|
|
// TODO(roasbeef): method to retrieve both old commitment txns given update #
|
|
|
|
func (c *OpenChannel) FindPreviousState(updateNum uint64) (*ChannelSnapshot, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Snapshot....
|
|
|
|
// read-only snapshot
|
|
|
|
func (c *OpenChannel) Snapshot() (*ChannelSnapshot, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2015-12-26 03:00:44 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// ChannelDelta...
|
|
|
|
// TODO(roasbeef): binlog like entry?
|
|
|
|
type ChannelDelta struct {
|
|
|
|
// change in allocations
|
|
|
|
// added + removed htlcs
|
|
|
|
// index
|
|
|
|
}
|
|
|
|
|
|
|
|
// RecordChannelDelta
|
|
|
|
// TODO(roasbeef): only need their commit?
|
|
|
|
// * or as internal helper func to UpdateState func?
|
|
|
|
func (c OpenChannel) RecordChannelDelta(theirRevokedCommit *wire.MsgTx, updateNum uint64) error {
|
|
|
|
// TODO(roasbeef): record all HTLCs, pass those instead?
|
|
|
|
// *
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// FullSync serializes, and writes to disk the *full* channel state, using
|
|
|
|
// both the active channel bucket to store the prefixed column fields, and the
|
|
|
|
// remote node's ID to store the remainder of the channel state.
|
|
|
|
//
|
|
|
|
// NOTE: This method requires an active EncryptorDecryptor to be registered in
|
|
|
|
// order to encrypt sensitive information.
|
|
|
|
func (c *OpenChannel) FullSync() error {
|
2016-03-24 10:00:22 +03:00
|
|
|
return c.Db.store.Update(func(tx *bolt.Tx) error {
|
2016-03-24 08:39:52 +03:00
|
|
|
// First fetch the top level bucket which stores all data related to
|
|
|
|
// current, active channels.
|
|
|
|
chanBucket := tx.Bucket(openChannelBucket)
|
|
|
|
|
|
|
|
// 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[:])
|
2015-12-26 03:00:44 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 10:00:22 +03:00
|
|
|
return putOpenChannel(chanBucket, nodeChanBucket, c, c.Db.cryptoSystem)
|
2016-03-24 08:39:52 +03:00
|
|
|
})
|
2015-12-26 03:00:44 +03:00
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// putChannel serializes, and stores the current state of the channel in its
|
|
|
|
// entirety.
|
|
|
|
func putOpenChannel(openChanBucket *bolt.Bucket, nodeChanBucket *bolt.Bucket,
|
|
|
|
channel *OpenChannel, encryptor EncryptorDecryptor) error {
|
2015-12-26 03:00:44 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// First write out all the "common" fields using the field's prefix
|
|
|
|
// appened with the channel's ID. These fields go into a top-level bucket
|
|
|
|
// to allow for ease of metric aggregation via efficient prefix scans.
|
|
|
|
if err := putChanCapacity(openChanBucket, channel); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanMinFeePerKb(openChanBucket, channel); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanNumUpdates(openChanBucket, channel); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanTotalFlow(openChanBucket, channel); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanNetFee(openChanBucket, channel); err != nil {
|
2015-12-26 03:00:44 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// Next, write out the fields of the channel update less frequently.
|
|
|
|
if err := putChannelIDs(nodeChanBucket, channel); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanCommitKeys(nodeChanBucket, channel, encryptor); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanCommitTxns(nodeChanBucket, channel); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanFundingInfo(nodeChanBucket, channel, encryptor); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanEklremState(nodeChanBucket, channel); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := putChanDeliveryScripts(nodeChanBucket, channel); err != nil {
|
2015-12-26 03:00:44 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
return nil
|
2015-12-26 03:00:44 +03:00
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// fetchOpenChannel retrieves, and deserializes (including decrypting
|
|
|
|
// sensitive) the complete channel currently active with the passed nodeID.
|
|
|
|
// An EncryptorDecryptor is required to decrypt sensitive information stored
|
|
|
|
// within the database.
|
|
|
|
func fetchOpenChannel(openChanBucket *bolt.Bucket, nodeID [32]byte,
|
|
|
|
decryptor EncryptorDecryptor) (*OpenChannel, error) {
|
2015-12-26 09:12:31 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// WIthin this top level bucket, fetch the bucket dedicated to storing
|
|
|
|
// open channel data specific to the remote node.
|
|
|
|
nodeChanBucket := openChanBucket.Bucket(nodeID[:])
|
|
|
|
if nodeChanBucket == nil {
|
|
|
|
return nil, fmt.Errorf("node chan bucket for node %v does not exist",
|
|
|
|
hex.EncodeToString(nodeID[:]))
|
2015-12-26 03:00:44 +03:00
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
channel := &OpenChannel{}
|
|
|
|
|
|
|
|
// First, read out the fields of the channel update less frequently.
|
|
|
|
if err := fetchChannelIDs(nodeChanBucket, channel); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanCommitKeys(nodeChanBucket, channel, decryptor); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanCommitTxns(nodeChanBucket, channel); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanFundingInfo(nodeChanBucket, channel, decryptor); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanEklremState(nodeChanBucket, channel); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanDeliveryScripts(nodeChanBucket, channel); err != nil {
|
|
|
|
return nil, err
|
2015-12-26 03:00:44 +03:00
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
// With the existence of an open channel bucket with this node verified,
|
|
|
|
// perform a full read of the entire struct. Starting with the prefixed
|
|
|
|
// fields residing in the parent bucket.
|
|
|
|
if err := fetchChanCapacity(openChanBucket, channel); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanMinFeePerKb(openChanBucket, channel); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanNumUpdates(openChanBucket, channel); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanTotalFlow(openChanBucket, channel); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := fetchChanNetFee(openChanBucket, channel); err != nil {
|
2015-12-26 03:00:44 +03:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return channel, nil
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
func putChanCapacity(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
// Some scratch bytes re-used for serializing each of the uint64's.
|
|
|
|
scratch1 := make([]byte, 8)
|
|
|
|
scratch2 := make([]byte, 8)
|
|
|
|
scratch3 := make([]byte, 8)
|
|
|
|
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
|
|
|
|
copy(keyPrefix[:3], chanCapacityPrefix)
|
|
|
|
byteOrder.PutUint64(scratch1, uint64(channel.Capacity))
|
|
|
|
if err := openChanBucket.Put(keyPrefix, scratch1); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
copy(keyPrefix[:3], selfBalancePrefix)
|
|
|
|
byteOrder.PutUint64(scratch2, uint64(channel.OurBalance))
|
|
|
|
if err := openChanBucket.Put(keyPrefix, scratch2); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
copy(keyPrefix[:3], theirBalancePrefix)
|
|
|
|
byteOrder.PutUint64(scratch3, uint64(channel.TheirBalance))
|
|
|
|
return openChanBucket.Put(keyPrefix, scratch3)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanCapacity(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
// A byte slice re-used to compute each key prefix eblow.
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
|
|
|
|
copy(keyPrefix[:3], chanCapacityPrefix)
|
|
|
|
capacityBytes := openChanBucket.Get(keyPrefix)
|
|
|
|
channel.Capacity = btcutil.Amount(byteOrder.Uint64(capacityBytes))
|
|
|
|
|
|
|
|
copy(keyPrefix[:3], selfBalancePrefix)
|
|
|
|
selfBalanceBytes := openChanBucket.Get(keyPrefix)
|
|
|
|
channel.OurBalance = btcutil.Amount(byteOrder.Uint64(selfBalanceBytes))
|
|
|
|
|
|
|
|
copy(keyPrefix[:3], theirBalancePrefix)
|
|
|
|
theirBalanceBytes := openChanBucket.Get(keyPrefix)
|
|
|
|
channel.TheirBalance = btcutil.Amount(byteOrder.Uint64(theirBalanceBytes))
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanMinFeePerKb(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
scratch := make([]byte, 8)
|
|
|
|
byteOrder.PutUint64(scratch, uint64(channel.MinFeePerKb))
|
|
|
|
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
copy(keyPrefix, minFeePerKbPrefix)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
|
|
|
|
return openChanBucket.Put(keyPrefix, scratch)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanMinFeePerKb(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
copy(keyPrefix, minFeePerKbPrefix)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
|
|
|
|
feeBytes := openChanBucket.Get(keyPrefix)
|
|
|
|
channel.MinFeePerKb = btcutil.Amount(byteOrder.Uint64(feeBytes))
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanNumUpdates(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
scratch := make([]byte, 8)
|
|
|
|
byteOrder.PutUint64(scratch, channel.NumUpdates)
|
|
|
|
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
copy(keyPrefix, updatePrefix)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
|
|
|
|
return openChanBucket.Put(keyPrefix, scratch)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanNumUpdates(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
copy(keyPrefix, updatePrefix)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
|
|
|
|
updateBytes := openChanBucket.Get(keyPrefix)
|
|
|
|
channel.NumUpdates = byteOrder.Uint64(updateBytes)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanTotalFlow(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
scratch1 := make([]byte, 8)
|
|
|
|
scratch2 := make([]byte, 8)
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
|
|
|
|
copy(keyPrefix[:3], satSentPrefix)
|
|
|
|
byteOrder.PutUint64(scratch1, uint64(channel.TotalSatoshisSent))
|
|
|
|
if err := openChanBucket.Put(keyPrefix, scratch1); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
copy(keyPrefix[:3], satRecievedPrefix)
|
|
|
|
byteOrder.PutUint64(scratch2, uint64(channel.TotalSatoshisReceived))
|
|
|
|
return openChanBucket.Put(keyPrefix, scratch2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanTotalFlow(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
|
|
|
|
copy(keyPrefix[:3], satSentPrefix)
|
|
|
|
totalSentBytes := openChanBucket.Get(keyPrefix)
|
|
|
|
channel.TotalSatoshisSent = byteOrder.Uint64(totalSentBytes)
|
|
|
|
|
|
|
|
copy(keyPrefix[:3], satRecievedPrefix)
|
|
|
|
totalReceivedBytes := openChanBucket.Get(keyPrefix)
|
|
|
|
channel.TotalSatoshisReceived = byteOrder.Uint64(totalReceivedBytes)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanNetFee(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
scratch := make([]byte, 8)
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
|
|
|
|
copy(keyPrefix, netFeesPrefix)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
byteOrder.PutUint64(scratch, uint64(channel.TotalNetFees))
|
|
|
|
return openChanBucket.Put(keyPrefix, scratch)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanNetFee(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
keyPrefix := make([]byte, 3+32)
|
|
|
|
|
|
|
|
copy(keyPrefix, netFeesPrefix)
|
|
|
|
copy(keyPrefix[3:], channel.ChanID[:])
|
|
|
|
feeBytes := openChanBucket.Get(keyPrefix)
|
|
|
|
channel.TotalNetFees = byteOrder.Uint64(feeBytes)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChannelIDs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
idSlice := make([]byte, wire.HashSize*2)
|
|
|
|
copy(idSlice, channel.TheirLNID[:])
|
|
|
|
copy(idSlice[32:], channel.ChanID[:])
|
|
|
|
|
|
|
|
return nodeChanBucket.Put(chanIDKey, idSlice)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChannelIDs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
idBytes := nodeChanBucket.Get(chanIDKey)
|
|
|
|
|
|
|
|
copy(channel.TheirLNID[:], idBytes[:32])
|
|
|
|
copy(channel.ChanID[:], idBytes[32:])
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanCommitKeys(nodeChanBucket *bolt.Bucket, channel *OpenChannel,
|
|
|
|
ed EncryptorDecryptor) error {
|
|
|
|
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
|
|
|
if _, err := b.Write(channel.TheirCommitKey.SerializeCompressed()); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
encryptedPriv, err := ed.Encrypt(channel.OurCommitKey.Serialize())
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
if _, err := b.Write(encryptedPriv); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
return nodeChanBucket.Put(commitKeys, b.Bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanCommitKeys(nodeChanBucket *bolt.Bucket, channel *OpenChannel,
|
|
|
|
ed EncryptorDecryptor) error {
|
|
|
|
|
|
|
|
var err error
|
|
|
|
keyBytes := nodeChanBucket.Get(commitKeys)
|
|
|
|
|
|
|
|
channel.TheirCommitKey, err = btcec.ParsePubKey(keyBytes[:33], btcec.S256())
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
decryptedPriv, err := ed.Decrypt(keyBytes[33:])
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.OurCommitKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), decryptedPriv)
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanCommitTxns(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
|
|
|
if err := channel.TheirCommitTx.Serialize(&b); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
if err := channel.OurCommitTx.Serialize(&b); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
scratch := make([]byte, 4)
|
|
|
|
byteOrder.PutUint32(scratch, channel.LocalCsvDelay)
|
|
|
|
if _, err := b.Write(scratch); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
byteOrder.PutUint32(scratch, channel.RemoteCsvDelay)
|
|
|
|
if _, err := b.Write(scratch); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
return nodeChanBucket.Put(commitTxnsKey, b.Bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanCommitTxns(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
txnBytes := bytes.NewReader(nodeChanBucket.Get(commitTxnsKey))
|
|
|
|
|
|
|
|
channel.TheirCommitTx = wire.NewMsgTx()
|
|
|
|
if err := channel.TheirCommitTx.Deserialize(txnBytes); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.OurCommitTx = wire.NewMsgTx()
|
|
|
|
if err := channel.OurCommitTx.Deserialize(txnBytes); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
scratch := make([]byte, 4)
|
|
|
|
|
|
|
|
if _, err := txnBytes.Read(scratch); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.LocalCsvDelay = byteOrder.Uint32(scratch)
|
|
|
|
|
|
|
|
if _, err := txnBytes.Read(scratch); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.RemoteCsvDelay = byteOrder.Uint32(scratch)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanFundingInfo(nodeChanBucket *bolt.Bucket, channel *OpenChannel,
|
|
|
|
ed EncryptorDecryptor) error {
|
|
|
|
var b bytes.Buffer
|
2015-12-26 02:00:20 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
if err := channel.FundingTx.Serialize(&b); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
encryptedPriv, err := ed.Encrypt(channel.MultiSigKey.Serialize())
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
if err := wire.WriteVarBytes(&b, 0, encryptedPriv); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
if err := wire.WriteVarBytes(&b, 0, channel.FundingRedeemScript[:]); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
scratch := make([]byte, 8)
|
|
|
|
byteOrder.PutUint64(scratch, uint64(channel.CreationTime.Unix()))
|
|
|
|
|
|
|
|
if _, err := b.Write(scratch); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
return nodeChanBucket.Put(fundingTxnKey, b.Bytes())
|
2015-12-26 02:00:20 +03:00
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
func fetchChanFundingInfo(nodeChanBucket *bolt.Bucket, channel *OpenChannel,
|
|
|
|
ed EncryptorDecryptor) error {
|
2015-12-26 02:00:20 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
infoBytes := bytes.NewReader(nodeChanBucket.Get(fundingTxnKey))
|
2015-12-26 02:00:20 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.FundingTx = wire.NewMsgTx()
|
|
|
|
if err := channel.FundingTx.Deserialize(infoBytes); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
encryptedPrivBytes, err := wire.ReadVarBytes(infoBytes, 0, 100, "")
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
decryptedPriv, err := ed.Decrypt(encryptedPrivBytes)
|
2015-12-26 02:00:20 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.MultiSigKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), decryptedPriv)
|
2015-12-26 02:00:20 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.FundingRedeemScript, err = wire.ReadVarBytes(infoBytes, 0, 520, "")
|
2015-12-26 02:00:20 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
scratch := make([]byte, 8)
|
|
|
|
if _, err := infoBytes.Read(scratch); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
unixSecs := byteOrder.Uint64(scratch)
|
|
|
|
channel.CreationTime = time.Unix(int64(unixSecs), 0)
|
2015-12-26 02:00:20 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanEklremState(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
|
|
|
if _, err := b.Write(channel.TheirCurrentRevocation[:]); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
senderBytes, err := channel.LocalElkrem.ToBytes()
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
if err := wire.WriteVarBytes(&b, 0, senderBytes); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
reciverBytes, err := channel.RemoteElkrem.ToBytes()
|
2015-12-26 02:00:20 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
if err := wire.WriteVarBytes(&b, 0, reciverBytes); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
return nodeChanBucket.Put(elkremStateKey, b.Bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanEklremState(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
elkremStateBytes := bytes.NewReader(nodeChanBucket.Get(elkremStateKey))
|
|
|
|
|
|
|
|
if _, err := elkremStateBytes.Read(channel.TheirCurrentRevocation[:]); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
senderBytes, err := wire.ReadVarBytes(elkremStateBytes, 0, 1000, "")
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
localE, err := elkrem.ElkremSenderFromBytes(senderBytes)
|
2015-12-26 02:00:20 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.LocalElkrem = &localE
|
2015-12-26 02:00:20 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
reciverBytes, err := wire.ReadVarBytes(elkremStateBytes, 0, 1000, "")
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
remoteE, err := elkrem.ElkremReceiverFromBytes(reciverBytes)
|
2015-12-26 02:00:20 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.RemoteElkrem = &remoteE
|
2015-12-26 02:00:20 +03:00
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func putChanDeliveryScripts(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
var b bytes.Buffer
|
|
|
|
if err := wire.WriteVarBytes(&b, 0, channel.OurDeliveryScript); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
if err := wire.WriteVarBytes(&b, 0, channel.TheirDeliveryScript); err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-03-24 08:39:52 +03:00
|
|
|
|
|
|
|
return nodeChanBucket.Put(deliveryScriptsKey, b.Bytes())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func fetchChanDeliveryScripts(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
|
|
|
|
var err error
|
|
|
|
deliveryBytes := bytes.NewReader(nodeChanBucket.Get(deliveryScriptsKey))
|
|
|
|
|
|
|
|
channel.OurDeliveryScript, err = wire.ReadVarBytes(deliveryBytes, 0, 520, "")
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-24 08:39:52 +03:00
|
|
|
channel.TheirDeliveryScript, err = wire.ReadVarBytes(deliveryBytes, 0, 520, "")
|
|
|
|
if err != nil {
|
2015-12-26 02:00:20 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|