move channel state struct to channeldb.go

* All fields are now publicly exported
This commit is contained in:
Olaoluwa Osuntokun 2015-12-24 12:41:15 -06:00
parent 868ac0aca0
commit 07646d05db
5 changed files with 105 additions and 107 deletions

@ -1,12 +1,9 @@
package lnwallet package lnwallet
import ( import (
"bytes"
"sync" "sync"
"time"
"li.lan/labs/plasma/chainntfs" "li.lan/labs/plasma/chainntfs"
"li.lan/labs/plasma/revocation"
"github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
@ -21,80 +18,6 @@ const (
MaxPendingPayments = 10 MaxPendingPayments = 10
) )
type nodeId [32]byte
// OpenChannelState...
// TODO(roasbeef): script gen methods on this?
type OpenChannelState struct {
// Hash? or Their current pubKey?
// TODO(roasbeef): switch to Tadge's LNId
theirLNID nodeId
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 // TODO(roasbeef): again unencrypted
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
// Commitment transactions for both sides (they're asymmetric). Also
// their signature which lets us spend our version of the commitment
// transaction.
theirCommitTx *wire.MsgTx
ourCommitTx *wire.MsgTx
theirCommitSig []byte
// The final funding transaction. Kept wallet-related records.
fundingTx *wire.MsgTx
// TODO(roasbeef): instead store a btcutil.Address here? Otherwise key
// is stored unencrypted! Use manager.Encrypt() when storing.
multiSigKey *btcec.PrivateKey
// TODO(roasbeef): encrypt also, or store in waddrmanager?
fundingRedeemScript []byte
// 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.
theirCurrentRevocation [wire.HashSize]byte
theirShaChain *revocation.HyperShaChain
ourShaChain *revocation.HyperShaChain
// Final delivery address
ourDeliveryAddress btcutil.Address
theirDeliveryAddress btcutil.Address
// In blocks
htlcTimeout uint32
csvDelay uint32
// TODO(roasbeef): track fees, other stats?
numUpdates uint64
totalSatoshisSent uint64
totalSatoshisReceived uint64
creationTime time.Time
}
func (o *OpenChannelState) Encode(b bytes.Buffer) error {
return nil
}
func (o *OpenChannelState) Decode(b bytes.Buffer) error {
return nil
}
func newOpenChannelState(ID [32]byte) *OpenChannelState {
return &OpenChannelState{theirLNID: ID}
}
// LightningChannel... // LightningChannel...
// TODO(roasbeef): future peer struct should embed this struct // TODO(roasbeef): future peer struct should embed this struct
type LightningChannel struct { type LightningChannel struct {

76
lnwallet/channeldb.go Normal file

@ -0,0 +1,76 @@
package lnwallet
import (
"encoding/binary"
"io"
"time"
"li.lan/labs/plasma/shachain"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcwallet/waddrmgr"
"github.com/btcsuite/btcwallet/walletdb"
)
// OpenChannelState...
// TODO(roasbeef): trim...
type OpenChannelState struct {
// Hash? or Their current pubKey?
// TODO(roasbeef): switch to Tadge's LNId
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
// Commitment transactions for both sides (they're asymmetric). Also
// their signature which lets us spend our version of the commitment
// transaction.
TheirCommitTx *wire.MsgTx
OurCommitTx *wire.MsgTx
TheirCommitSig []byte
// The final funding transaction. Kept wallet-related records.
FundingTx *wire.MsgTx
// TODO(roasbeef): instead store a btcutil.Address here? Otherwise key
// is stored unencrypted! Use manager.Encrypt() when storing.
MultiSigKey *btcec.PrivateKey
// TODO(roasbeef): encrypt also, or store in waddrmanager?
FundingRedeemScript []byte
// 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.
TheirCurrentRevocation [wire.HashSize]byte
TheirShaChain *shachain.HyperShaChain
OurShaChain *shachain.HyperShaChain
// Final delivery address
OurDeliveryAddress btcutil.Address
TheirDeliveryAddress btcutil.Address
// In blocks
CsvDelay uint32
// TODO(roasbeef): track fees, other stats?
NumUpdates uint64
TotalSatoshisSent uint64
TotalSatoshisReceived uint64
CreationTime time.Time
}

@ -92,8 +92,8 @@ func newChannelReservation(t FundingType, fundingAmt btcutil.Amount,
}, },
partialState: &OpenChannelState{ partialState: &OpenChannelState{
// TODO(roasbeef): assumes balanced symmetric channels. // TODO(roasbeef): assumes balanced symmetric channels.
capacity: fundingAmt * 2, Capacity: fundingAmt * 2,
minFeePerKb: minFeeRate, MinFeePerKb: minFeeRate,
}, },
reservationID: id, reservationID: id,
wallet: wallet, wallet: wallet,
@ -153,14 +153,14 @@ func (r *ChannelReservation) CompleteReservation(fundingSigs [][]byte, commitmen
func (r *ChannelReservation) TheirSignatures() ([][]byte, []byte) { func (r *ChannelReservation) TheirSignatures() ([][]byte, []byte) {
r.RLock() r.RLock()
defer r.RUnlock() defer r.RUnlock()
return r.theirFundingSigs, r.partialState.theirCommitSig return r.theirFundingSigs, r.partialState.TheirCommitSig
} }
// FinalFundingTransaction... // FinalFundingTransaction...
func (r *ChannelReservation) FinalFundingTx() *wire.MsgTx { func (r *ChannelReservation) FinalFundingTx() *wire.MsgTx {
r.RLock() r.RLock()
defer r.RUnlock() defer r.RUnlock()
return r.partialState.fundingTx return r.partialState.FundingTx
} }
// RequestFundingReserveCancellation... // RequestFundingReserveCancellation...

@ -417,9 +417,9 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
req.resp <- nil req.resp <- nil
return return
} }
reservation.partialState.multiSigKey = multiSigKey reservation.partialState.MultiSigKey = multiSigKey
ourContribution.MultiSigKey = multiSigKey.PubKey() ourContribution.MultiSigKey = multiSigKey.PubKey()
reservation.partialState.ourCommitKey = commitKey reservation.partialState.OurCommitKey = commitKey
ourContribution.CommitKey = commitKey.PubKey() ourContribution.CommitKey = commitKey.PubKey()
// Generate a fresh address to be used in the case of a cooperative // Generate a fresh address to be used in the case of a cooperative
@ -433,7 +433,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
req.resp <- nil req.resp <- nil
return return
} }
reservation.partialState.ourDeliveryAddress = addrs[0].Address() reservation.partialState.OurDeliveryAddress = addrs[0].Address()
ourContribution.DeliveryAddress = addrs[0].Address() ourContribution.DeliveryAddress = addrs[0].Address()
// Create a new shaChain for verifiable transaction revocations. // Create a new shaChain for verifiable transaction revocations.
@ -443,7 +443,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
req.resp <- nil req.resp <- nil
return return
} }
reservation.partialState.ourShaChain = shaChain reservation.partialState.OurShaChain = shaChain
ourContribution.RevocationHash = shaChain.CurrentRevocationHash() ourContribution.RevocationHash = shaChain.CurrentRevocationHash()
// Funding reservation request succesfully handled. The funding inputs // Funding reservation request succesfully handled. The funding inputs
@ -503,8 +503,8 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
// Create a blank, fresh transaction. Soon to be a complete funding // Create a blank, fresh transaction. Soon to be a complete funding
// transaction which will allow opening a lightning channel. // transaction which will allow opening a lightning channel.
pendingReservation.partialState.fundingTx = wire.NewMsgTx() pendingReservation.partialState.FundingTx = wire.NewMsgTx()
fundingTx := pendingReservation.partialState.fundingTx fundingTx := pendingReservation.partialState.FundingTx
pendingReservation.theirContribution = req.contribution pendingReservation.theirContribution = req.contribution
theirContribution := req.contribution theirContribution := req.contribution
@ -534,10 +534,10 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
// Finally, add the 2-of-2 multi-sig output which will set up the lightning // Finally, add the 2-of-2 multi-sig output which will set up the lightning
// channel. // channel.
ourKey := pendingReservation.partialState.multiSigKey ourKey := pendingReservation.partialState.MultiSigKey
theirKey := theirContribution.MultiSigKey theirKey := theirContribution.MultiSigKey
channelCapacity := int64(pendingReservation.partialState.capacity) channelCapacity := int64(pendingReservation.partialState.Capacity)
redeemScript, multiSigOut, err := fundMultiSigOut(ourKey.PubKey().SerializeCompressed(), redeemScript, multiSigOut, err := fundMultiSigOut(ourKey.PubKey().SerializeCompressed(),
theirKey.SerializeCompressed(), channelCapacity) theirKey.SerializeCompressed(), channelCapacity)
if err != nil { if err != nil {
@ -550,7 +550,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
// Sort the transaction. Since both side agree to a cannonical // Sort the transaction. Since both side agree to a cannonical
// ordering, by sorting we no longer need to send the entire // ordering, by sorting we no longer need to send the entire
// transaction. Only signatures will be exchanged. // transaction. Only signatures will be exchanged.
txsort.InPlaceSort(pendingReservation.partialState.fundingTx) txsort.InPlaceSort(pendingReservation.partialState.FundingTx)
// Now that the transaction has been cannonically sorted, compute the // Now that the transaction has been cannonically sorted, compute the
// normalized transation ID before we attach our signatures. // normalized transation ID before we attach our signatures.
@ -589,7 +589,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
return return
} }
sigscript, err := txscript.SignatureScript(pendingReservation.partialState.fundingTx, i, sigscript, err := txscript.SignatureScript(pendingReservation.partialState.FundingTx, i,
prevOut.PkScript, txscript.SigHashAll, privkey, prevOut.PkScript, txscript.SigHashAll, privkey,
ai.Compressed()) ai.Compressed())
if err != nil { if err != nil {
@ -597,7 +597,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
return return
} }
pendingReservation.partialState.fundingTx.TxIn[i].SignatureScript = sigscript fundingTx.TxIn[i].SignatureScript = sigscript
pendingReservation.ourFundingSigs = append(pendingReservation.ourFundingSigs, sigscript) pendingReservation.ourFundingSigs = append(pendingReservation.ourFundingSigs, sigscript)
} }
@ -610,15 +610,14 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
// Grab the hash of the current pre-image in our chain, this is needed // Grab the hash of the current pre-image in our chain, this is needed
// for out commitment tx. // for out commitment tx.
// TODO(roasbeef): grab partial state above to avoid long attr chain // TODO(roasbeef): grab partial state above to avoid long attr chain
ourCurrentRevokeHash := pendingReservation.partialState.ourShaChain.CurrentRevocationHash() ourCurrentRevokeHash := pendingReservation.partialState.OurShaChain.CurrentRevocationHash()
ourContribution.RevocationHash = ourCurrentRevokeHash ourContribution.RevocationHash = ourCurrentRevokeHash
// Create the txIn to our commitment transaction. In the process, we // Create the txIn to our commitment transaction. In the process, we
// need to locate the index of the multi-sig output on the funding tx // need to locate the index of the multi-sig output on the funding tx
// since the outputs are cannonically sorted. // since the outputs are cannonically sorted.
fundingNTxid := pendingReservation.partialState.fundingTx.TxSha() // NOTE: assumes testnet-L fundingNTxid := fundingTx.TxSha() // NOTE: assumes testnet-L
_, multiSigIndex := findScriptOutputIndex(pendingReservation.partialState.fundingTx, _, multiSigIndex := findScriptOutputIndex(fundingTx, multiSigOut.PkScript)
multiSigOut.PkScript)
fundingTxIn := wire.NewTxIn(wire.NewOutPoint(&fundingNTxid, multiSigIndex), nil) fundingTxIn := wire.NewTxIn(wire.NewOutPoint(&fundingNTxid, multiSigIndex), nil)
// With the funding tx complete, create both commitment transactions. // With the funding tx complete, create both commitment transactions.
@ -639,9 +638,9 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
return return
} }
pendingReservation.partialState.theirCommitKey = theirCommitKey pendingReservation.partialState.TheirCommitKey = theirCommitKey
pendingReservation.partialState.theirCommitTx = theirCommitTx pendingReservation.partialState.TheirCommitTx = theirCommitTx
pendingReservation.partialState.ourCommitTx = ourCommitTx pendingReservation.partialState.OurCommitTx = ourCommitTx
// Generate a signature for their version of the initial commitment // Generate a signature for their version of the initial commitment
// transaction. // transaction.
@ -651,7 +650,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
req.err <- err req.err <- err
return return
} }
pendingReservation.partialState.theirCommitSig = sigTheirCommit pendingReservation.partialState.TheirCommitSig = sigTheirCommit
pendingReservation.ourCommitmentSig = sigTheirCommit pendingReservation.ourCommitmentSig = sigTheirCommit
req.err <- nil req.err <- nil
@ -674,7 +673,7 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
// Now we can complete the funding transaction by adding their // Now we can complete the funding transaction by adding their
// signatures to their inputs. // signatures to their inputs.
pendingReservation.theirFundingSigs = msg.theirFundingSigs pendingReservation.theirFundingSigs = msg.theirFundingSigs
fundingTx := pendingReservation.partialState.fundingTx fundingTx := pendingReservation.partialState.FundingTx
for i, txin := range fundingTx.TxIn { for i, txin := range fundingTx.TxIn {
if txin.SignatureScript == nil { if txin.SignatureScript == nil {
txin.SignatureScript = pendingReservation.theirFundingSigs[i] txin.SignatureScript = pendingReservation.theirFundingSigs[i]
@ -712,7 +711,7 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
// At this point, wen calso record and verify their isgnature for our // At this point, wen calso record and verify their isgnature for our
// commitment transaction. // commitment transaction.
pendingReservation.partialState.theirCommitSig = msg.theirCommitmentSig pendingReservation.partialState.TheirCommitSig = msg.theirCommitmentSig
// TODO(roasbeef): verify // TODO(roasbeef): verify
//commitSig := msg.theirCommitmentSig //commitSig := msg.theirCommitmentSig
@ -740,7 +739,7 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
// Create a new sub-bucket within the open channel bucket // Create a new sub-bucket within the open channel bucket
// specifically for this channel. // specifically for this channel.
// TODO(roasbeef): should def be indexed by LNID, cuz mal etc. // TODO(roasbeef): should def be indexed by LNID, cuz mal etc.
txID := pendingReservation.partialState.fundingTx.TxSha() txID := fundingTx.TxSha()
chanBucket, err := openChanBucket.CreateBucketIfNotExists(txID.Bytes()) chanBucket, err := openChanBucket.CreateBucketIfNotExists(txID.Bytes())
if err != nil { if err != nil {
return err return err

@ -360,7 +360,7 @@ func testBasicWalletReservationWorkFlow(lnwallet *LightningWallet, t *testing.T)
t.Fatalf("commitment sig not found") t.Fatalf("commitment sig not found")
} }
// Additionally, the funding tx should have been populated. // Additionally, the funding tx should have been populated.
if chanReservation.partialState.fundingTx == nil { if chanReservation.partialState.FundingTx == nil {
t.Fatalf("funding transaction never created!") t.Fatalf("funding transaction never created!")
} }
// Their funds should also be filled in. // Their funds should also be filled in.
@ -388,7 +388,7 @@ func testBasicWalletReservationWorkFlow(lnwallet *LightningWallet, t *testing.T)
// Alice responds with her output, change addr, multi-sig key and signatures. // Alice responds with her output, change addr, multi-sig key and signatures.
// Bob then responds with his signatures. // Bob then responds with his signatures.
bobsSigs, err := bobNode.signFundingTx(chanReservation.partialState.fundingTx) bobsSigs, err := bobNode.signFundingTx(chanReservation.partialState.FundingTx)
if err != nil { if err != nil {
t.Fatalf("unable to sign inputs for bob: %v", err) t.Fatalf("unable to sign inputs for bob: %v", err)
} }
@ -414,7 +414,7 @@ func testBasicWalletReservationWorkFlow(lnwallet *LightningWallet, t *testing.T)
// The sub-bucket for this channel, keyed by the txid of the // The sub-bucket for this channel, keyed by the txid of the
// funding transaction // funding transaction
txid := chanReservation.partialState.fundingTx.TxSha() txid := chanReservation.partialState.FundingTx.TxSha()
bobChanBucket := openChanBucket.Bucket(txid[:]) bobChanBucket := openChanBucket.Bucket(txid[:])
if bobChanBucket == nil { if bobChanBucket == nil {
t.Fatalf("bucket for the alice-bob channe should exist, " + t.Fatalf("bucket for the alice-bob channe should exist, " +
@ -427,7 +427,7 @@ func testBasicWalletReservationWorkFlow(lnwallet *LightningWallet, t *testing.T)
// The hash of the stored tx should be indentical to our funding tx. // The hash of the stored tx should be indentical to our funding tx.
storedTxId := storedTx.TxSha() storedTxId := storedTx.TxSha()
actualTxId := chanReservation.partialState.fundingTx.TxSha() actualTxId := chanReservation.partialState.FundingTx.TxSha()
if !bytes.Equal(storedTxId.Bytes(), actualTxId.Bytes()) { if !bytes.Equal(storedTxId.Bytes(), actualTxId.Bytes()) {
t.Fatalf("stored funding tx doesn't match actual") t.Fatalf("stored funding tx doesn't match actual")
} }