lnwallet: update reservation workflow to be segwitty

Only nested p2sh or pure witness outputs are used when selecting coins
for inputs to a funding transaction.

The funding transaction output now uses p2wsh rather than regular p2sh.

All tests have been updated accordingly.
This commit is contained in:
Olaoluwa Osuntokun 2016-05-03 19:49:58 -07:00
parent 4b4c0f73b0
commit c6eedafb9a
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
2 changed files with 111 additions and 76 deletions

@ -8,6 +8,7 @@ import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"github.com/btcsuite/btcd/btcjson"
"github.com/lightningnetwork/lnd/chainntfs" "github.com/lightningnetwork/lnd/chainntfs"
"github.com/lightningnetwork/lnd/chainntfs/btcdnotify" "github.com/lightningnetwork/lnd/chainntfs/btcdnotify"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
@ -26,7 +27,7 @@ import (
) )
const ( const (
// The size of the buffered queue of request to the wallet from the // The size of the buffered queue of requests to the wallet from the
// outside word. // outside word.
msgBufferSize = 100 msgBufferSize = 100
) )
@ -124,7 +125,7 @@ type addCounterPartySigsMsg struct {
// Should be order of sorted inputs that are theirs. Sorting is done // Should be order of sorted inputs that are theirs. Sorting is done
// in accordance to BIP-69: // in accordance to BIP-69:
// https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki. // https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki.
theirFundingSigs [][]byte theirFundingInputScripts []*InputScript
// This should be 1/2 of the signatures needed to succesfully spend our // This should be 1/2 of the signatures needed to succesfully spend our
// version of the commitment transaction. // version of the commitment transaction.
@ -674,21 +675,13 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
theirContribution := req.contribution theirContribution := req.contribution
ourContribution := pendingReservation.ourContribution ourContribution := pendingReservation.ourContribution
// First, add all multi-party inputs to the transaction // Add all multi-party inputs and outputs to the transaction.
// TODO(roasbeef); handle case that tx doesn't exist, fake input
// TODO(roasbeef): validate SPV proof from other side if in SPV mode.
// * actually, pure SPV would need fraud proofs right? must prove input
// is unspent
// * or, something like getutxo?
for _, ourInput := range ourContribution.Inputs { for _, ourInput := range ourContribution.Inputs {
fundingTx.AddTxIn(ourInput) fundingTx.AddTxIn(ourInput)
} }
for _, theirInput := range theirContribution.Inputs { for _, theirInput := range theirContribution.Inputs {
fundingTx.AddTxIn(theirInput) fundingTx.AddTxIn(theirInput)
} }
// Next, add all multi-party outputs to the transaction. This includes
// change outputs for both side.
for _, ourChangeOutput := range ourContribution.ChangeOutputs { for _, ourChangeOutput := range ourContribution.ChangeOutputs {
fundingTx.AddTxOut(ourChangeOutput) fundingTx.AddTxOut(ourChangeOutput)
} }
@ -702,7 +695,7 @@ 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.
channelCapacity := int64(pendingReservation.partialState.Capacity) channelCapacity := int64(pendingReservation.partialState.Capacity)
redeemScript, multiSigOut, err := fundMultiSigOut(ourKey.PubKey().SerializeCompressed(), redeemScript, multiSigOut, err := genFundingPkScript(ourKey.PubKey().SerializeCompressed(),
theirKey.SerializeCompressed(), channelCapacity) theirKey.SerializeCompressed(), channelCapacity)
if err != nil { if err != nil {
req.err <- err req.err <- err
@ -733,7 +726,8 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
// Next, sign all inputs that are ours, collecting the signatures in // Next, sign all inputs that are ours, collecting the signatures in
// order of the inputs. // order of the inputs.
pendingReservation.ourFundingSigs = make([][]byte, 0, len(ourContribution.Inputs)) pendingReservation.ourFundingInputScripts = make([]*InputScript, 0, len(ourContribution.Inputs))
hashCache := txscript.NewTxSigHashes(fundingTx)
for i, txIn := range fundingTx.TxIn { for i, txIn := range fundingTx.TxIn {
// Does the wallet know about the txin? // Does the wallet know about the txin?
txDetail, _ := l.TxStore.TxDetails(&txIn.PreviousOutPoint.Hash) txDetail, _ := l.TxStore.TxDetails(&txIn.PreviousOutPoint.Hash)
@ -741,14 +735,11 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
continue continue
} }
// Is this our txin? TODO(roasbeef): assumes all inputs are P2PKH... // Is this our txin?
prevIndex := txIn.PreviousOutPoint.Index prevIndex := txIn.PreviousOutPoint.Index
prevOut := txDetail.TxRecord.MsgTx.TxOut[prevIndex] prevOut := txDetail.TxRecord.MsgTx.TxOut[prevIndex]
_, addrs, _, _ := txscript.ExtractPkScriptAddrs(prevOut.PkScript, l.cfg.NetParams) _, addrs, _, _ := txscript.ExtractPkScriptAddrs(prevOut.PkScript, l.cfg.NetParams)
apkh, ok := addrs[0].(*btcutil.AddressPubKeyHash) apkh := addrs[0]
if !ok {
req.err <- fmt.Errorf("only p2pkh wallet outputs are supported")
}
ai, err := l.Manager.Address(apkh) ai, err := l.Manager.Address(apkh)
if err != nil { if err != nil {
@ -756,22 +747,52 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
return return
} }
pka := ai.(waddrmgr.ManagedPubKeyAddress) pka := ai.(waddrmgr.ManagedPubKeyAddress)
privkey, err := pka.PrivKey() privKey, err := pka.PrivKey()
if err != nil { if err != nil {
req.err <- fmt.Errorf("cannot get private key: %v", err) req.err <- fmt.Errorf("cannot get private key: %v", err)
return return
} }
sigscript, err := txscript.SignatureScript(pendingReservation.partialState.FundingTx, i, var witnessProgram []byte
prevOut.PkScript, txscript.SigHashAll, privkey, inputScript := &InputScript{}
ai.Compressed())
// If we're spending p2wkh output nested within a p2sh output,
// then we'll need to attach a sigScript in addition to witness
// data.
if pka.IsNestedWitness() {
witnessProgram, err = txscript.PayToAddrScript(pka.Address())
if err != nil { if err != nil {
req.err <- fmt.Errorf("cannot create sigscript: %s", err) req.err <- fmt.Errorf("unable to create witness program: %v", err)
return return
} }
bldr := txscript.NewScriptBuilder()
bldr.AddData(witnessProgram)
scriptSig, err := bldr.Script()
if err != nil {
req.err <- fmt.Errorf("unable to create scriptsig: %v", err)
return
}
txIn.SignatureScript = scriptSig
inputScript.ScriptSig = scriptSig
} else {
witnessProgram = prevOut.PkScript
}
fundingTx.TxIn[i].SignatureScript = sigscript // Generate a valid witness stack for the input.
pendingReservation.ourFundingSigs = append(pendingReservation.ourFundingSigs, sigscript) inputValue := prevOut.Value
witnessScript, err := txscript.WitnessScript(fundingTx, hashCache, i,
inputValue, witnessProgram, txscript.SigHashAll, privKey, true)
if err != nil {
req.err <- fmt.Errorf("cannot create witnessscript: %s", err)
return
}
txIn.Witness = witnessScript
inputScript.Witness = witnessScript
pendingReservation.ourFundingInputScripts = append(
pendingReservation.ourFundingInputScripts,
inputScript,
)
} }
// Initialize an empty sha-chain for them, tracking the current pending // Initialize an empty sha-chain for them, tracking the current pending
@ -875,33 +896,39 @@ 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.theirFundingInputScripts = msg.theirFundingInputScripts
fundingTx := pendingReservation.partialState.FundingTx fundingTx := pendingReservation.partialState.FundingTx
sigIndex := 0 sigIndex := 0
fundingHashCache := txscript.NewTxSigHashes(fundingTx)
for i, txin := range fundingTx.TxIn { for i, txin := range fundingTx.TxIn {
if txin.SignatureScript == nil { if len(txin.Witness) == 0 {
// Attach the signature so we can verify it below. // Attach the input scripts so we can verify it below.
txin.SignatureScript = pendingReservation.theirFundingSigs[sigIndex] inputScripts := pendingReservation.theirFundingInputScripts
txin.Witness = inputScripts[sigIndex].Witness
txin.SignatureScript = inputScripts[sigIndex].ScriptSig
// Fetch the alleged previous output along with the // Fetch the alleged previous output along with the
// pkscript referenced by this input. // pkscript referenced by this input.
prevOut := txin.PreviousOutPoint prevOut := txin.PreviousOutPoint
output, err := l.rpc.GetTxOut(&prevOut.Hash, prevOut.Index, false) output, err := l.rpc.GetTxOut(&prevOut.Hash, prevOut.Index, false)
if output == nil { if output == nil {
// TODO(roasbeef): do this at the start to avoid wasting out time?
// 8 or a set of nodes "we" run with exposed unauthenticated RPC?
msg.err <- fmt.Errorf("input to funding tx does not exist: %v", err) msg.err <- fmt.Errorf("input to funding tx does not exist: %v", err)
return return
} }
pkscript, err := hex.DecodeString(output.ScriptPubKey.Hex)
pkScript, err := hex.DecodeString(output.ScriptPubKey.Hex)
if err != nil { if err != nil {
msg.err <- err msg.err <- err
return return
} }
// Sadly, gettxout returns the output value in BTC
// instead of satoshis.
inputValue := int64(output.Value) * 1e8
// Ensure that the signature is valid. // Ensure that the witness+sigScript combo is valid.
vm, err := txscript.NewEngine(pkscript, vm, err := txscript.NewEngine(pkScript,
fundingTx, i, txscript.StandardVerifyFlags, nil, nil, 0) fundingTx, i, txscript.StandardVerifyFlags, nil,
fundingHashCache, inputValue)
if err != nil { if err != nil {
// TODO(roasbeef): cancel at this stage if invalid sigs? // TODO(roasbeef): cancel at this stage if invalid sigs?
msg.err <- fmt.Errorf("cannot create script engine: %s", err) msg.err <- fmt.Errorf("cannot create script engine: %s", err)
@ -927,15 +954,17 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
// redeemScript script, but include the p2sh output as the subscript // redeemScript script, but include the p2sh output as the subscript
// for verification. // for verification.
redeemScript := pendingReservation.partialState.FundingRedeemScript redeemScript := pendingReservation.partialState.FundingRedeemScript
p2sh, err := scriptHashPkScript(redeemScript) p2wsh, err := witnessScriptHash(redeemScript)
if err != nil { if err != nil {
msg.err <- err msg.err <- err
return return
} }
// First, we sign our copy of the commitment transaction ourselves. // First, we sign our copy of the commitment transaction ourselves.
ourCommitSig, err := txscript.RawTxInSignature(commitTx, 0, redeemScript, channelValue := int64(pendingReservation.partialState.Capacity)
txscript.SigHashAll, ourKey) hashCache := txscript.NewTxSigHashes(commitTx)
ourCommitSig, err := txscript.RawTxInWitnessSignature(commitTx, hashCache, 0,
channelValue, redeemScript, txscript.SigHashAll, ourKey)
if err != nil { if err != nil {
msg.err <- err msg.err <- err
return return
@ -946,18 +975,17 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
theirCommitSig := msg.theirCommitmentSig theirCommitSig := msg.theirCommitmentSig
ourKeySer := ourKey.PubKey().SerializeCompressed() ourKeySer := ourKey.PubKey().SerializeCompressed()
theirKeySer := theirKey.SerializeCompressed() theirKeySer := theirKey.SerializeCompressed()
scriptSig, err := spendMultiSig(redeemScript, ourKeySer, ourCommitSig, witness := spendMultiSig(redeemScript, ourKeySer, ourCommitSig,
theirKeySer, theirCommitSig) theirKeySer, theirCommitSig)
if err != nil {
msg.err <- err
return
}
// Finally, create an instance of a Script VM, and ensure that the // Finally, create an instance of a Script VM, and ensure that the
// Script executes succesfully. // Script executes succesfully.
commitTx.TxIn[0].SignatureScript = scriptSig inputValue := pendingReservation.partialState.Capacity
vm, err := txscript.NewEngine(p2sh, commitTx, 0, fmt.Println(inputValue)
txscript.StandardVerifyFlags, nil, nil, 0) commitTx.TxIn[0].Witness = witness
vm, err := txscript.NewEngine(p2wsh,
commitTx, 0, txscript.StandardVerifyFlags, nil,
nil, int64(inputValue))
if err != nil { if err != nil {
msg.err <- err msg.err <- err
return return

@ -96,34 +96,42 @@ func (b *bobNode) Contribution() *ChannelContribution {
// signFundingTx generates signatures for all the inputs in the funding tx // signFundingTx generates signatures for all the inputs in the funding tx
// belonging to Bob. // belonging to Bob.
// NOTE: This generates the full sig-script. // NOTE: This generates the full witness stack.
func (b *bobNode) signFundingTx(fundingTx *wire.MsgTx) ([][]byte, error) { func (b *bobNode) signFundingTx(fundingTx *wire.MsgTx) ([]*InputScript, error) {
bobSigs := make([][]byte, 0, len(b.availableOutputs)) bobInputScripts := make([]*InputScript, 0, len(b.availableOutputs))
bobPkScript := b.changeOutputs[0].PkScript bobPkScript := b.changeOutputs[0].PkScript
inputValue := int64(7e8)
hashCache := txscript.NewTxSigHashes(fundingTx)
for i, _ := range fundingTx.TxIn { for i, _ := range fundingTx.TxIn {
// Alice has already signed this input // Alice has already signed this input.
if fundingTx.TxIn[i].SignatureScript != nil { if fundingTx.TxIn[i].Witness != nil {
continue continue
} }
sigScript, err := txscript.SignatureScript(fundingTx, i, witness, err := txscript.WitnessScript(fundingTx, hashCache, i,
bobPkScript, txscript.SigHashAll, b.privKey, inputValue, bobPkScript, txscript.SigHashAll, b.privKey,
true) true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bobSigs = append(bobSigs, sigScript) inputScript := &InputScript{Witness: witness}
bobInputScripts = append(bobInputScripts, inputScript)
} }
return bobSigs, nil return bobInputScripts, nil
} }
// signCommitTx generates a raw signature required for generating a spend from // signCommitTx generates a raw signature required for generating a spend from
// the funding transaction. // the funding transaction.
func (b *bobNode) signCommitTx(commitTx *wire.MsgTx, fundingScript []byte) ([]byte, error) { func (b *bobNode) signCommitTx(commitTx *wire.MsgTx, fundingScript []byte,
return txscript.RawTxInSignature(commitTx, 0, fundingScript, channelValue int64) ([]byte, error) {
txscript.SigHashAll, b.privKey)
hashCache := txscript.NewTxSigHashes(commitTx)
return txscript.RawTxInWitnessSignature(commitTx, hashCache, 0,
channelValue, fundingScript, txscript.SigHashAll, b.privKey)
} }
// newBobNode generates a test "ln node" to interact with Alice (us). For the // newBobNode generates a test "ln node" to interact with Alice (us). For the
@ -136,12 +144,13 @@ func newBobNode(miner *rpctest.Harness) (*bobNode, error) {
privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), bobsPrivKey) privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), bobsPrivKey)
// Next, generate an output redeemable by bob. // Next, generate an output redeemable by bob.
bobAddrPk, err := btcutil.NewAddressPubKey(privKey.PubKey().SerializeCompressed(), pkHash := btcutil.Hash160(pubKey.SerializeCompressed())
bobAddr, err := btcutil.NewAddressWitnessPubKeyHash(
pkHash,
miner.ActiveNet) miner.ActiveNet)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bobAddr := bobAddrPk.AddressPubKeyHash()
bobAddrScript, err := txscript.PayToAddrScript(bobAddr) bobAddrScript, err := txscript.PayToAddrScript(bobAddr)
if err != nil { if err != nil {
return nil, err return nil, err
@ -172,8 +181,6 @@ func newBobNode(miner *rpctest.Harness) (*bobNode, error) {
} }
prevOut := wire.NewOutPoint(mainTxid, index) prevOut := wire.NewOutPoint(mainTxid, index)
// TODO(roasbeef): When the chain rpc is hooked in, assert bob's output
// actually exists and it unspent in the chain.
bobTxIn := wire.NewTxIn(prevOut, nil, nil) bobTxIn := wire.NewTxIn(prevOut, nil, nil)
// Using bobs priv key above, create a change output he can spend. // Using bobs priv key above, create a change output he can spend.
@ -208,7 +215,7 @@ func loadTestCredits(miner *rpctest.Harness, w *LightningWallet, numOutputs, btc
addrs := make([]btcutil.Address, 0, numOutputs) addrs := make([]btcutil.Address, 0, numOutputs)
for i := 0; i < numOutputs; i++ { for i := 0; i < numOutputs; i++ {
// Grab a fresh address from the wallet to house this output. // Grab a fresh address from the wallet to house this output.
walletAddr, err := w.NewAddress(waddrmgr.DefaultAccountNum) walletAddr, err := w.NewAddress(waddrmgr.DefaultAccountNum, waddrmgr.WitnessPubKey)
if err != nil { if err != nil {
return err return err
} }
@ -284,7 +291,7 @@ func createTestWallet(miningNode *rpctest.Harness, netParams *chaincfg.Params) (
} }
dbDir := filepath.Join(tempTestDir, "cdb") dbDir := filepath.Join(tempTestDir, "cdb")
cdb, err := channeldb.Create(dbDir) cdb, err := channeldb.Open(dbDir, &chaincfg.SegNet4Params)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
@ -318,7 +325,7 @@ func testBasicWalletReservationWorkFlow(miner *rpctest.Harness, lnwallet *Lightn
// BTC total. He also generates 2 BTC in change. // BTC total. He also generates 2 BTC in change.
fundingAmount := btcutil.Amount(5 * 1e8) fundingAmount := btcutil.Amount(5 * 1e8)
chanReservation, err := lnwallet.InitChannelReservation(fundingAmount, chanReservation, err := lnwallet.InitChannelReservation(fundingAmount,
SIGHASH, bobNode.id, 4) bobNode.id, 4)
if err != nil { if err != nil {
t.Fatalf("unable to initialize funding reservation: %v", err) t.Fatalf("unable to initialize funding reservation: %v", err)
} }
@ -405,7 +412,8 @@ func testBasicWalletReservationWorkFlow(miner *rpctest.Harness, lnwallet *Lightn
} }
commitSig, err := bobNode.signCommitTx( commitSig, err := bobNode.signCommitTx(
chanReservation.partialState.OurCommitTx, chanReservation.partialState.OurCommitTx,
chanReservation.partialState.FundingRedeemScript) chanReservation.partialState.FundingRedeemScript,
10e8)
if err != nil { if err != nil {
t.Fatalf("bob is unable to sign alice's commit tx: %v", err) t.Fatalf("bob is unable to sign alice's commit tx: %v", err)
} }
@ -434,12 +442,12 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness, lnwallet *Light
// * also func for below // * also func for below
fundingAmount := btcutil.Amount(8 * 1e8) fundingAmount := btcutil.Amount(8 * 1e8)
chanReservation1, err := lnwallet.InitChannelReservation(fundingAmount, chanReservation1, err := lnwallet.InitChannelReservation(fundingAmount,
SIGHASH, testHdSeed, 4) testHdSeed, 4)
if err != nil { if err != nil {
t.Fatalf("unable to initialize funding reservation 1: %v", err) t.Fatalf("unable to initialize funding reservation 1: %v", err)
} }
chanReservation2, err := lnwallet.InitChannelReservation(fundingAmount, chanReservation2, err := lnwallet.InitChannelReservation(fundingAmount,
SIGHASH, testHdSeed, 4) testHdSeed, 4)
if err != nil { if err != nil {
t.Fatalf("unable to initialize funding reservation 2: %v", err) t.Fatalf("unable to initialize funding reservation 2: %v", err)
} }
@ -470,7 +478,7 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness, lnwallet *Light
// this should fail. // this should fail.
amt := btcutil.Amount(8 * 1e8) amt := btcutil.Amount(8 * 1e8)
failedReservation, err := lnwallet.InitChannelReservation(amt, failedReservation, err := lnwallet.InitChannelReservation(amt,
SIGHASH, testHdSeed, 4) testHdSeed, 4)
if err == nil { if err == nil {
t.Fatalf("not error returned, should fail on coin selection") t.Fatalf("not error returned, should fail on coin selection")
} }
@ -486,7 +494,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, lnwallet *Lig
// Create a reservation for 12 BTC. // Create a reservation for 12 BTC.
fundingAmount := btcutil.Amount(12 * 1e8) fundingAmount := btcutil.Amount(12 * 1e8)
chanReservation, err := lnwallet.InitChannelReservation(fundingAmount, chanReservation, err := lnwallet.InitChannelReservation(fundingAmount,
SIGHASH, testHdSeed, 4) testHdSeed, 4)
if err != nil { if err != nil {
t.Fatalf("unable to initialize funding reservation: %v", err) t.Fatalf("unable to initialize funding reservation: %v", err)
} }
@ -500,7 +508,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, lnwallet *Lig
// Attempt to create another channel with 12 BTC, this should fail. // Attempt to create another channel with 12 BTC, this should fail.
failedReservation, err := lnwallet.InitChannelReservation(fundingAmount, failedReservation, err := lnwallet.InitChannelReservation(fundingAmount,
SIGHASH, testHdSeed, 4) testHdSeed, 4)
if err != coinset.ErrCoinsNoSelectionAvailable { if err != coinset.ErrCoinsNoSelectionAvailable {
t.Fatalf("coin selection succeded should have insufficient funds: %+v", t.Fatalf("coin selection succeded should have insufficient funds: %+v",
failedReservation) failedReservation)
@ -529,7 +537,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, lnwallet *Lig
// Request to fund a new channel should now succeeed. // Request to fund a new channel should now succeeed.
_, err = lnwallet.InitChannelReservation(fundingAmount, _, err = lnwallet.InitChannelReservation(fundingAmount,
SIGHASH, testHdSeed, 4) testHdSeed, 4)
if err != nil { if err != nil {
t.Fatalf("unable to initialize funding reservation: %v", err) t.Fatalf("unable to initialize funding reservation: %v", err)
} }
@ -537,7 +545,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, lnwallet *Lig
func testCancelNonExistantReservation(miner *rpctest.Harness, lnwallet *LightningWallet, t *testing.T) { func testCancelNonExistantReservation(miner *rpctest.Harness, lnwallet *LightningWallet, t *testing.T) {
// Create our own reservation, give it some ID. // Create our own reservation, give it some ID.
res := newChannelReservation(SIGHASH, 1000, 5000, lnwallet, 22) res := newChannelReservation(1000, 5000, lnwallet, 22)
// Attempt to cancel this reservation. This should fail, we know // Attempt to cancel this reservation. This should fail, we know
// nothing of it. // nothing of it.
@ -576,7 +584,6 @@ func clearWalletState(w *LightningWallet) {
} }
func TestLightningWallet(t *testing.T) { func TestLightningWallet(t *testing.T) {
// TODO(roasbeef): switch to testnetL later
netParams := &chaincfg.SimNetParams netParams := &chaincfg.SimNetParams
// Initialize the harness around a btcd node which will serve as our // Initialize the harness around a btcd node which will serve as our