2019-01-24 16:28:25 +03:00
|
|
|
package lnd
|
2017-07-14 22:05:55 +03:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2018-03-05 19:20:36 +03:00
|
|
|
crand "crypto/rand"
|
|
|
|
"encoding/binary"
|
|
|
|
"io"
|
2017-07-14 22:05:55 +03:00
|
|
|
"io/ioutil"
|
|
|
|
"math/rand"
|
|
|
|
"net"
|
|
|
|
"os"
|
2019-02-15 04:13:44 +03:00
|
|
|
"time"
|
2017-07-14 22:05:55 +03:00
|
|
|
|
2018-07-18 05:23:47 +03:00
|
|
|
"github.com/btcsuite/btcd/btcec"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
|
|
|
"github.com/btcsuite/btcutil"
|
2017-07-14 22:05:55 +03:00
|
|
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
|
|
|
"github.com/lightningnetwork/lnd/channeldb"
|
2020-02-03 13:52:22 +03:00
|
|
|
"github.com/lightningnetwork/lnd/clock"
|
2018-01-17 07:56:51 +03:00
|
|
|
"github.com/lightningnetwork/lnd/contractcourt"
|
2017-07-14 22:05:55 +03:00
|
|
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
2019-01-16 17:47:43 +03:00
|
|
|
"github.com/lightningnetwork/lnd/input"
|
2018-02-18 02:29:01 +03:00
|
|
|
"github.com/lightningnetwork/lnd/keychain"
|
2017-07-14 22:05:55 +03:00
|
|
|
"github.com/lightningnetwork/lnd/lnwallet"
|
2019-10-31 05:43:05 +03:00
|
|
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
2020-06-17 03:33:06 +03:00
|
|
|
"github.com/lightningnetwork/lnd/lnwallet/chancloser"
|
2017-07-14 22:05:55 +03:00
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
2019-02-15 04:13:44 +03:00
|
|
|
"github.com/lightningnetwork/lnd/netann"
|
2017-07-14 22:05:55 +03:00
|
|
|
"github.com/lightningnetwork/lnd/shachain"
|
2018-08-01 07:01:45 +03:00
|
|
|
"github.com/lightningnetwork/lnd/ticker"
|
2017-07-14 22:05:55 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
alicesPrivKey = []byte{
|
|
|
|
0x2b, 0xd8, 0x06, 0xc9, 0x7f, 0x0e, 0x00, 0xaf,
|
|
|
|
0x1a, 0x1f, 0xc3, 0x32, 0x8f, 0xa7, 0x63, 0xa9,
|
|
|
|
0x26, 0x97, 0x23, 0xc8, 0xdb, 0x8f, 0xac, 0x4f,
|
|
|
|
0x93, 0xaf, 0x71, 0xdb, 0x18, 0x6d, 0x6e, 0x90,
|
|
|
|
}
|
|
|
|
|
|
|
|
bobsPrivKey = []byte{
|
|
|
|
0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
|
|
|
|
0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
|
|
|
|
0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
|
|
|
|
0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use a hard-coded HD seed.
|
|
|
|
testHdSeed = [32]byte{
|
|
|
|
0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
|
|
|
|
0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
|
|
|
|
0x4f, 0x2f, 0x6f, 0x25, 0x88, 0xa3, 0xef, 0xb9,
|
|
|
|
0x6a, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Just use some arbitrary bytes as delivery script.
|
|
|
|
dummyDeliveryScript = alicesPrivKey[:]
|
2018-03-11 04:27:51 +03:00
|
|
|
|
|
|
|
// testTx is used as the default funding txn for single-funder channels.
|
|
|
|
testTx = &wire.MsgTx{
|
|
|
|
Version: 1,
|
|
|
|
TxIn: []*wire.TxIn{
|
|
|
|
{
|
|
|
|
PreviousOutPoint: wire.OutPoint{
|
|
|
|
Hash: chainhash.Hash{},
|
|
|
|
Index: 0xffffffff,
|
|
|
|
},
|
|
|
|
SignatureScript: []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62},
|
|
|
|
Sequence: 0xffffffff,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
TxOut: []*wire.TxOut{
|
|
|
|
{
|
|
|
|
Value: 5000000000,
|
|
|
|
PkScript: []byte{
|
|
|
|
0x41, // OP_DATA_65
|
|
|
|
0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
|
|
|
|
0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
|
|
|
|
0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
|
|
|
|
0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
|
|
|
|
0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
|
|
|
|
0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
|
|
|
|
0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
|
|
|
|
0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
|
|
|
|
0xa6, // 65-byte signature
|
|
|
|
0xac, // OP_CHECKSIG
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
LockTime: 5,
|
|
|
|
}
|
2017-07-14 22:05:55 +03:00
|
|
|
)
|
|
|
|
|
2019-12-09 16:44:00 +03:00
|
|
|
// noUpdate is a function which can be used as a parameter in createTestPeer to
|
|
|
|
// call the setup code with no custom values on the channels set up.
|
|
|
|
var noUpdate = func(a, b *channeldb.OpenChannel) {}
|
|
|
|
|
2017-07-14 22:05:55 +03:00
|
|
|
// createTestPeer creates a channel between two nodes, and returns a peer for
|
2019-12-09 16:44:00 +03:00
|
|
|
// one of the nodes, together with the channel seen from both nodes. It takes
|
|
|
|
// an updateChan function which can be used to modify the default values on
|
|
|
|
// the channel states for each peer.
|
|
|
|
func createTestPeer(notifier chainntnfs.ChainNotifier, publTx chan *wire.MsgTx,
|
|
|
|
updateChan func(a, b *channeldb.OpenChannel)) (*peer, *lnwallet.LightningChannel,
|
2017-07-14 22:05:55 +03:00
|
|
|
*lnwallet.LightningChannel, func(), error) {
|
|
|
|
|
2020-04-28 11:06:27 +03:00
|
|
|
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(
|
|
|
|
btcec.S256(), alicesPrivKey,
|
|
|
|
)
|
|
|
|
aliceKeySigner := &keychain.PrivKeyDigestSigner{PrivKey: aliceKeyPriv}
|
|
|
|
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(
|
|
|
|
btcec.S256(), bobsPrivKey,
|
|
|
|
)
|
2017-07-14 22:05:55 +03:00
|
|
|
|
|
|
|
channelCapacity := btcutil.Amount(10 * 1e8)
|
|
|
|
channelBal := channelCapacity / 2
|
|
|
|
aliceDustLimit := btcutil.Amount(200)
|
|
|
|
bobDustLimit := btcutil.Amount(1300)
|
|
|
|
csvTimeoutAlice := uint32(5)
|
|
|
|
csvTimeoutBob := uint32(4)
|
|
|
|
|
|
|
|
prevOut := &wire.OutPoint{
|
|
|
|
Hash: chainhash.Hash(testHdSeed),
|
|
|
|
Index: 0,
|
|
|
|
}
|
|
|
|
fundingTxIn := wire.NewTxIn(prevOut, nil, nil)
|
|
|
|
|
|
|
|
aliceCfg := channeldb.ChannelConfig{
|
|
|
|
ChannelConstraints: channeldb.ChannelConstraints{
|
|
|
|
DustLimit: aliceDustLimit,
|
2017-08-22 09:25:41 +03:00
|
|
|
MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()),
|
2017-07-14 22:05:55 +03:00
|
|
|
ChanReserve: btcutil.Amount(rand.Int63()),
|
2017-08-22 09:25:41 +03:00
|
|
|
MinHTLC: lnwire.MilliSatoshi(rand.Int63()),
|
2017-07-14 22:05:55 +03:00
|
|
|
MaxAcceptedHtlcs: uint16(rand.Int31()),
|
2018-12-11 00:56:41 +03:00
|
|
|
CsvDelay: uint16(csvTimeoutAlice),
|
2017-07-14 22:05:55 +03:00
|
|
|
},
|
2018-02-18 02:29:01 +03:00
|
|
|
MultiSigKey: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
RevocationBasePoint: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
PaymentBasePoint: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
DelayBasePoint: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
|
|
|
HtlcBasePoint: keychain.KeyDescriptor{
|
|
|
|
PubKey: aliceKeyPub,
|
|
|
|
},
|
2017-07-14 22:05:55 +03:00
|
|
|
}
|
|
|
|
bobCfg := channeldb.ChannelConfig{
|
|
|
|
ChannelConstraints: channeldb.ChannelConstraints{
|
|
|
|
DustLimit: bobDustLimit,
|
2017-08-22 09:25:41 +03:00
|
|
|
MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()),
|
2017-07-14 22:05:55 +03:00
|
|
|
ChanReserve: btcutil.Amount(rand.Int63()),
|
2017-08-22 09:25:41 +03:00
|
|
|
MinHTLC: lnwire.MilliSatoshi(rand.Int63()),
|
2017-07-14 22:05:55 +03:00
|
|
|
MaxAcceptedHtlcs: uint16(rand.Int31()),
|
2018-12-11 00:56:41 +03:00
|
|
|
CsvDelay: uint16(csvTimeoutBob),
|
2017-07-14 22:05:55 +03:00
|
|
|
},
|
2018-02-18 02:29:01 +03:00
|
|
|
MultiSigKey: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
RevocationBasePoint: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
PaymentBasePoint: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
DelayBasePoint: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
|
|
|
HtlcBasePoint: keychain.KeyDescriptor{
|
|
|
|
PubKey: bobKeyPub,
|
|
|
|
},
|
2017-07-14 22:05:55 +03:00
|
|
|
}
|
|
|
|
|
2018-02-18 02:29:01 +03:00
|
|
|
bobRoot, err := chainhash.NewHash(bobKeyPriv.Serialize())
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
bobPreimageProducer := shachain.NewRevocationProducer(*bobRoot)
|
2017-07-14 22:05:55 +03:00
|
|
|
bobFirstRevoke, err := bobPreimageProducer.AtIndex(0)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
2019-01-16 17:47:43 +03:00
|
|
|
bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:])
|
2017-07-14 22:05:55 +03:00
|
|
|
|
2018-02-18 02:29:01 +03:00
|
|
|
aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize())
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
alicePreimageProducer := shachain.NewRevocationProducer(*aliceRoot)
|
2017-07-14 22:05:55 +03:00
|
|
|
aliceFirstRevoke, err := alicePreimageProducer.AtIndex(0)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
2019-01-16 17:47:43 +03:00
|
|
|
aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:])
|
2017-07-14 22:05:55 +03:00
|
|
|
|
2019-08-01 06:10:45 +03:00
|
|
|
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(
|
|
|
|
channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint,
|
2020-01-06 13:42:04 +03:00
|
|
|
bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit,
|
2019-08-01 06:10:45 +03:00
|
|
|
)
|
2017-07-14 22:05:55 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
alicePath, err := ioutil.TempDir("", "alicedb")
|
2019-09-13 05:59:07 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
2017-07-14 22:05:55 +03:00
|
|
|
dbAlice, err := channeldb.Open(alicePath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
bobPath, err := ioutil.TempDir("", "bobdb")
|
2019-09-13 05:59:07 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
2017-07-14 22:05:55 +03:00
|
|
|
dbBob, err := channeldb.Open(bobPath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
2019-10-31 05:43:05 +03:00
|
|
|
estimator := chainfee.NewStaticEstimator(12500, 0)
|
2018-07-28 04:20:58 +03:00
|
|
|
feePerKw, err := estimator.EstimateFeePerKW(1)
|
2017-11-23 22:41:20 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-11 02:24:29 +03:00
|
|
|
// TODO(roasbeef): need to factor in commit fee?
|
|
|
|
aliceCommit := channeldb.ChannelCommitment{
|
|
|
|
CommitHeight: 0,
|
|
|
|
LocalBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
|
|
|
RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
2018-02-13 17:15:14 +03:00
|
|
|
FeePerKw: btcutil.Amount(feePerKw),
|
2019-01-16 17:47:43 +03:00
|
|
|
CommitFee: feePerKw.FeeForWeight(input.CommitWeight),
|
2017-11-11 02:24:29 +03:00
|
|
|
CommitTx: aliceCommitTx,
|
|
|
|
CommitSig: bytes.Repeat([]byte{1}, 71),
|
|
|
|
}
|
|
|
|
bobCommit := channeldb.ChannelCommitment{
|
|
|
|
CommitHeight: 0,
|
|
|
|
LocalBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
|
|
|
RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
2018-02-13 17:15:14 +03:00
|
|
|
FeePerKw: btcutil.Amount(feePerKw),
|
2019-01-16 17:47:43 +03:00
|
|
|
CommitFee: feePerKw.FeeForWeight(input.CommitWeight),
|
2017-11-11 02:24:29 +03:00
|
|
|
CommitTx: bobCommitTx,
|
|
|
|
CommitSig: bytes.Repeat([]byte{1}, 71),
|
|
|
|
}
|
|
|
|
|
2018-03-05 19:20:36 +03:00
|
|
|
var chanIDBytes [8]byte
|
|
|
|
if _, err := io.ReadFull(crand.Reader, chanIDBytes[:]); err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
shortChanID := lnwire.NewShortChanIDFromInt(
|
|
|
|
binary.BigEndian.Uint64(chanIDBytes[:]),
|
|
|
|
)
|
|
|
|
|
2017-07-14 22:05:55 +03:00
|
|
|
aliceChannelState := &channeldb.OpenChannel{
|
|
|
|
LocalChanCfg: aliceCfg,
|
|
|
|
RemoteChanCfg: bobCfg,
|
|
|
|
IdentityPub: aliceKeyPub,
|
|
|
|
FundingOutpoint: *prevOut,
|
2018-05-02 02:27:20 +03:00
|
|
|
ShortChannelID: shortChanID,
|
2019-10-31 05:24:49 +03:00
|
|
|
ChanType: channeldb.SingleFunderTweaklessBit,
|
2017-07-14 22:05:55 +03:00
|
|
|
IsInitiator: true,
|
|
|
|
Capacity: channelCapacity,
|
|
|
|
RemoteCurrentRevocation: bobCommitPoint,
|
|
|
|
RevocationProducer: alicePreimageProducer,
|
|
|
|
RevocationStore: shachain.NewRevocationStore(),
|
2017-11-11 02:24:29 +03:00
|
|
|
LocalCommitment: aliceCommit,
|
|
|
|
RemoteCommitment: aliceCommit,
|
2017-07-14 22:05:55 +03:00
|
|
|
Db: dbAlice,
|
2018-03-05 19:20:36 +03:00
|
|
|
Packager: channeldb.NewChannelPackager(shortChanID),
|
2018-03-11 04:27:51 +03:00
|
|
|
FundingTxn: testTx,
|
2017-07-14 22:05:55 +03:00
|
|
|
}
|
|
|
|
bobChannelState := &channeldb.OpenChannel{
|
|
|
|
LocalChanCfg: bobCfg,
|
|
|
|
RemoteChanCfg: aliceCfg,
|
|
|
|
IdentityPub: bobKeyPub,
|
|
|
|
FundingOutpoint: *prevOut,
|
2019-10-31 05:24:49 +03:00
|
|
|
ChanType: channeldb.SingleFunderTweaklessBit,
|
2017-07-14 22:05:55 +03:00
|
|
|
IsInitiator: false,
|
|
|
|
Capacity: channelCapacity,
|
|
|
|
RemoteCurrentRevocation: aliceCommitPoint,
|
|
|
|
RevocationProducer: bobPreimageProducer,
|
|
|
|
RevocationStore: shachain.NewRevocationStore(),
|
2017-11-11 02:24:29 +03:00
|
|
|
LocalCommitment: bobCommit,
|
|
|
|
RemoteCommitment: bobCommit,
|
2017-07-14 22:05:55 +03:00
|
|
|
Db: dbBob,
|
2018-03-05 19:20:36 +03:00
|
|
|
Packager: channeldb.NewChannelPackager(shortChanID),
|
2017-07-14 22:05:55 +03:00
|
|
|
}
|
|
|
|
|
2019-12-09 16:44:00 +03:00
|
|
|
// Set custom values on the channel states.
|
|
|
|
updateChan(aliceChannelState, bobChannelState)
|
|
|
|
|
2018-09-06 04:22:29 +03:00
|
|
|
aliceAddr := &net.TCPAddr{
|
2017-11-11 02:24:29 +03:00
|
|
|
IP: net.ParseIP("127.0.0.1"),
|
|
|
|
Port: 18555,
|
|
|
|
}
|
|
|
|
|
2018-09-06 04:22:29 +03:00
|
|
|
if err := aliceChannelState.SyncPending(aliceAddr, 0); err != nil {
|
2017-11-11 02:24:29 +03:00
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
2018-09-06 04:22:29 +03:00
|
|
|
bobAddr := &net.TCPAddr{
|
2017-07-14 22:05:55 +03:00
|
|
|
IP: net.ParseIP("127.0.0.1"),
|
|
|
|
Port: 18556,
|
|
|
|
}
|
|
|
|
|
2018-09-06 04:22:29 +03:00
|
|
|
if err := bobChannelState.SyncPending(bobAddr, 0); err != nil {
|
2017-07-14 22:05:55 +03:00
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanUpFunc := func() {
|
|
|
|
os.RemoveAll(bobPath)
|
|
|
|
os.RemoveAll(alicePath)
|
|
|
|
}
|
|
|
|
|
|
|
|
aliceSigner := &mockSigner{aliceKeyPriv}
|
|
|
|
bobSigner := &mockSigner{bobKeyPriv}
|
|
|
|
|
multi: replace per channel sigPool with global daemon level sigPool
In this commit, we remove the per channel `sigPool` within the
`lnwallet.LightningChannel` struct. With this change, we ensure that as
the number of channels grows, the number of gouroutines idling in the
sigPool stays constant. It's the case that currently on the daemon, most
channels are likely inactive, with only a hand full actually
consistently carrying out channel updates. As a result, this change
should reduce the amount of idle CPU usage, as we have less active
goroutines in select loops.
In order to make this change, the `SigPool` itself has been publicly
exported such that outside callers can make a `SigPool` and pass it into
newly created channels. Since the sig pool now lives outside the
channel, we were also able to do away with the Stop() method on the
channel all together.
Finally, the server is the sub-system that is currently responsible for
managing the `SigPool` within lnd.
2018-12-15 03:35:07 +03:00
|
|
|
alicePool := lnwallet.NewSigPool(1, aliceSigner)
|
2018-01-17 07:56:51 +03:00
|
|
|
channelAlice, err := lnwallet.NewLightningChannel(
|
2019-04-15 15:24:43 +03:00
|
|
|
aliceSigner, aliceChannelState, alicePool,
|
2018-01-17 07:56:51 +03:00
|
|
|
)
|
2017-07-14 22:05:55 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
multi: replace per channel sigPool with global daemon level sigPool
In this commit, we remove the per channel `sigPool` within the
`lnwallet.LightningChannel` struct. With this change, we ensure that as
the number of channels grows, the number of gouroutines idling in the
sigPool stays constant. It's the case that currently on the daemon, most
channels are likely inactive, with only a hand full actually
consistently carrying out channel updates. As a result, this change
should reduce the amount of idle CPU usage, as we have less active
goroutines in select loops.
In order to make this change, the `SigPool` itself has been publicly
exported such that outside callers can make a `SigPool` and pass it into
newly created channels. Since the sig pool now lives outside the
channel, we were also able to do away with the Stop() method on the
channel all together.
Finally, the server is the sub-system that is currently responsible for
managing the `SigPool` within lnd.
2018-12-15 03:35:07 +03:00
|
|
|
alicePool.Start()
|
|
|
|
|
|
|
|
bobPool := lnwallet.NewSigPool(1, bobSigner)
|
2018-01-17 07:56:51 +03:00
|
|
|
channelBob, err := lnwallet.NewLightningChannel(
|
2019-04-15 15:24:43 +03:00
|
|
|
bobSigner, bobChannelState, bobPool,
|
2018-01-17 07:56:51 +03:00
|
|
|
)
|
2017-07-14 22:05:55 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
multi: replace per channel sigPool with global daemon level sigPool
In this commit, we remove the per channel `sigPool` within the
`lnwallet.LightningChannel` struct. With this change, we ensure that as
the number of channels grows, the number of gouroutines idling in the
sigPool stays constant. It's the case that currently on the daemon, most
channels are likely inactive, with only a hand full actually
consistently carrying out channel updates. As a result, this change
should reduce the amount of idle CPU usage, as we have less active
goroutines in select loops.
In order to make this change, the `SigPool` itself has been publicly
exported such that outside callers can make a `SigPool` and pass it into
newly created channels. Since the sig pool now lives outside the
channel, we were also able to do away with the Stop() method on the
channel all together.
Finally, the server is the sub-system that is currently responsible for
managing the `SigPool` within lnd.
2018-12-15 03:35:07 +03:00
|
|
|
bobPool.Start()
|
2017-07-14 22:05:55 +03:00
|
|
|
|
2018-10-23 13:08:03 +03:00
|
|
|
chainIO := &mockChainIO{
|
|
|
|
bestHeight: fundingBroadcastHeight,
|
|
|
|
}
|
2017-07-14 22:05:55 +03:00
|
|
|
wallet := &lnwallet.LightningWallet{
|
|
|
|
WalletController: &mockWalletController{
|
|
|
|
rootKey: aliceKeyPriv,
|
|
|
|
publishedTransactions: publTx,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
cc := &chainControl{
|
|
|
|
feeEstimator: estimator,
|
|
|
|
chainIO: chainIO,
|
|
|
|
chainNotifier: notifier,
|
|
|
|
wallet: wallet,
|
|
|
|
}
|
|
|
|
|
2018-01-21 07:27:25 +03:00
|
|
|
breachArbiter := &breachArbiter{}
|
2017-07-14 22:05:55 +03:00
|
|
|
|
2018-01-17 07:56:51 +03:00
|
|
|
chainArb := contractcourt.NewChainArbitrator(
|
breacharbiter: properly account for second-level spends during breach remedy
In this commit, we address an un accounted for case during the breach
remedy process. If the remote node actually went directly to the second
layer during a channel breach attempt, then we wouldn’t properly be
able to sweep with out justice transaction, as some HTLC inputs may
actually be spent at that point.
In order to address this case, we’ll now catch the transaction
rejection, then check to see which input was spent, promote that to a
second level spend, and repeat as necessary. At the end of this loop,
any inputs which have been spent to the second level will have had the
prevouts and witnesses updated.
In order to perform this transition, we now also store the second level
witness script in the database. This allow us to modify the sign desc
with the proper input value, as well as witness script.
2018-01-23 04:11:02 +03:00
|
|
|
contractcourt.ChainArbitratorConfig{
|
|
|
|
Notifier: notifier,
|
|
|
|
ChainIO: chainIO,
|
2020-02-03 13:52:22 +03:00
|
|
|
IsForwardedHTLC: func(chanID lnwire.ShortChannelID,
|
|
|
|
htlcIndex uint64) bool {
|
|
|
|
|
|
|
|
return true
|
|
|
|
},
|
|
|
|
Clock: clock.NewDefaultClock(),
|
breacharbiter: properly account for second-level spends during breach remedy
In this commit, we address an un accounted for case during the breach
remedy process. If the remote node actually went directly to the second
layer during a channel breach attempt, then we wouldn’t properly be
able to sweep with out justice transaction, as some HTLC inputs may
actually be spent at that point.
In order to address this case, we’ll now catch the transaction
rejection, then check to see which input was spent, promote that to a
second level spend, and repeat as necessary. At the end of this loop,
any inputs which have been spent to the second level will have had the
prevouts and witnesses updated.
In order to perform this transition, we now also store the second level
witness script in the database. This allow us to modify the sign desc
with the proper input value, as well as witness script.
2018-01-23 04:11:02 +03:00
|
|
|
}, dbAlice,
|
2018-01-17 07:56:51 +03:00
|
|
|
)
|
breacharbiter: properly account for second-level spends during breach remedy
In this commit, we address an un accounted for case during the breach
remedy process. If the remote node actually went directly to the second
layer during a channel breach attempt, then we wouldn’t properly be
able to sweep with out justice transaction, as some HTLC inputs may
actually be spent at that point.
In order to address this case, we’ll now catch the transaction
rejection, then check to see which input was spent, promote that to a
second level spend, and repeat as necessary. At the end of this loop,
any inputs which have been spent to the second level will have had the
prevouts and witnesses updated.
In order to perform this transition, we now also store the second level
witness script in the database. This allow us to modify the sign desc
with the proper input value, as well as witness script.
2018-01-23 04:11:02 +03:00
|
|
|
chainArb.WatchNewChannel(aliceChannelState)
|
2018-01-17 07:56:51 +03:00
|
|
|
|
2017-07-14 22:05:55 +03:00
|
|
|
s := &server{
|
|
|
|
chanDB: dbAlice,
|
|
|
|
cc: cc,
|
|
|
|
breachArbiter: breachArbiter,
|
2018-01-17 07:56:51 +03:00
|
|
|
chainArb: chainArb,
|
2017-07-14 22:05:55 +03:00
|
|
|
}
|
2018-06-01 06:31:40 +03:00
|
|
|
|
|
|
|
_, currentHeight, err := s.cc.chainIO.GetBestBlock()
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
|
2018-01-18 04:15:41 +03:00
|
|
|
htlcSwitch, err := htlcswitch.New(htlcswitch.Config{
|
2018-03-05 19:20:36 +03:00
|
|
|
DB: dbAlice,
|
|
|
|
SwitchPackager: channeldb.NewSwitchPackager(),
|
2018-06-01 06:31:40 +03:00
|
|
|
Notifier: notifier,
|
2018-08-01 07:01:45 +03:00
|
|
|
FwdEventTicker: ticker.New(
|
|
|
|
htlcswitch.DefaultFwdEventInterval),
|
|
|
|
LogEventTicker: ticker.New(
|
|
|
|
htlcswitch.DefaultLogInterval),
|
2019-05-30 19:26:24 +03:00
|
|
|
AckEventTicker: ticker.New(
|
|
|
|
htlcswitch.DefaultAckInterval),
|
2018-06-01 06:31:40 +03:00
|
|
|
}, uint32(currentHeight))
|
2018-01-18 04:15:41 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
2019-02-15 04:13:44 +03:00
|
|
|
if err = htlcSwitch.Start(); err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
2018-01-18 04:15:41 +03:00
|
|
|
s.htlcSwitch = htlcSwitch
|
2019-02-15 04:13:44 +03:00
|
|
|
|
2020-04-28 11:06:27 +03:00
|
|
|
nodeSignerAlice := netann.NewNodeSigner(aliceKeySigner)
|
2019-02-15 04:13:44 +03:00
|
|
|
|
|
|
|
const chanActiveTimeout = time.Minute
|
|
|
|
|
|
|
|
chanStatusMgr, err := netann.NewChanStatusManager(&netann.ChanStatusConfig{
|
|
|
|
ChanStatusSampleInterval: 30 * time.Second,
|
|
|
|
ChanEnableTimeout: chanActiveTimeout,
|
|
|
|
ChanDisableTimeout: 2 * time.Minute,
|
|
|
|
DB: dbAlice,
|
|
|
|
Graph: dbAlice.ChannelGraph(),
|
|
|
|
MessageSigner: nodeSignerAlice,
|
|
|
|
OurPubKey: aliceKeyPub,
|
|
|
|
IsChannelActive: s.htlcSwitch.HasActiveLink,
|
|
|
|
ApplyChannelUpdate: func(*lnwire.ChannelUpdate) error { return nil },
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
2019-03-13 03:34:57 +03:00
|
|
|
if err = chanStatusMgr.Start(); err != nil {
|
|
|
|
return nil, nil, nil, nil, err
|
|
|
|
}
|
2019-02-15 04:13:44 +03:00
|
|
|
s.chanStatusMgr = chanStatusMgr
|
2017-07-14 22:05:55 +03:00
|
|
|
|
|
|
|
alicePeer := &peer{
|
2018-09-06 04:22:29 +03:00
|
|
|
addr: &lnwire.NetAddress{
|
|
|
|
IdentityKey: aliceKeyPub,
|
|
|
|
Address: aliceAddr,
|
|
|
|
},
|
|
|
|
|
2017-07-14 22:05:55 +03:00
|
|
|
server: s,
|
2018-02-07 06:11:11 +03:00
|
|
|
sendQueue: make(chan outgoingMsg, 1),
|
|
|
|
outgoingQueue: make(chan outgoingMsg, outgoingQueueLen),
|
2017-07-14 22:05:55 +03:00
|
|
|
|
|
|
|
activeChannels: make(map[lnwire.ChannelID]*lnwallet.LightningChannel),
|
|
|
|
newChannels: make(chan *newChannelMsg, 1),
|
|
|
|
|
2020-06-17 03:33:06 +03:00
|
|
|
activeChanCloses: make(map[lnwire.ChannelID]*chancloser.ChanCloser),
|
2017-11-23 22:41:20 +03:00
|
|
|
localCloseChanReqs: make(chan *htlcswitch.ChanClose),
|
|
|
|
chanCloseMsgs: make(chan *closeMsg),
|
2017-07-14 22:05:55 +03:00
|
|
|
|
2019-02-15 04:13:44 +03:00
|
|
|
chanActiveTimeout: chanActiveTimeout,
|
|
|
|
|
2017-07-14 22:05:55 +03:00
|
|
|
queueQuit: make(chan struct{}),
|
|
|
|
quit: make(chan struct{}),
|
|
|
|
}
|
|
|
|
|
|
|
|
chanID := lnwire.NewChanIDFromOutPoint(channelAlice.ChannelPoint())
|
|
|
|
alicePeer.activeChannels[chanID] = channelAlice
|
|
|
|
|
2019-02-15 04:13:33 +03:00
|
|
|
alicePeer.wg.Add(1)
|
2017-07-14 22:05:55 +03:00
|
|
|
go alicePeer.channelManager()
|
|
|
|
|
|
|
|
return alicePeer, channelAlice, channelBob, cleanUpFunc, nil
|
|
|
|
}
|