nsa
4 years ago
16 changed files with 903 additions and 547 deletions
@ -0,0 +1,40 @@
|
||||
package peer |
||||
|
||||
import ( |
||||
"github.com/btcsuite/btclog" |
||||
"github.com/lightningnetwork/lnd/build" |
||||
) |
||||
|
||||
// peerLog is a logger that is initialized with the btclog.Disabled logger.
|
||||
var peerLog btclog.Logger |
||||
|
||||
// The default amount of logging is none.
|
||||
func init() { |
||||
UseLogger(build.NewSubLogger("PEER", nil)) |
||||
} |
||||
|
||||
// DisableLog disables all logging output.
|
||||
func DisableLog() { |
||||
UseLogger(btclog.Disabled) |
||||
} |
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
func UseLogger(logger btclog.Logger) { |
||||
peerLog = logger |
||||
} |
||||
|
||||
// logClosure is used to provide a closure over expensive logging operations
|
||||
// so they aren't performed when the logging level doesn't warrant it.
|
||||
type logClosure func() string |
||||
|
||||
// String invokes the underlying function and returns the result.
|
||||
func (c logClosure) String() string { |
||||
return c() |
||||
} |
||||
|
||||
// newLogClosure returns a new closure over a function that returns a string
|
||||
// which itself provides a Stringer interface so that it can be used with the
|
||||
// logging system.
|
||||
func newLogClosure(c func() string) logClosure { |
||||
return logClosure(c) |
||||
} |
@ -0,0 +1,695 @@
|
||||
package peer |
||||
|
||||
import ( |
||||
"bytes" |
||||
crand "crypto/rand" |
||||
"encoding/binary" |
||||
"fmt" |
||||
"io" |
||||
"io/ioutil" |
||||
"math/rand" |
||||
"net" |
||||
"os" |
||||
"time" |
||||
|
||||
"github.com/btcsuite/btcd/btcec" |
||||
"github.com/btcsuite/btcd/chaincfg" |
||||
"github.com/btcsuite/btcd/chaincfg/chainhash" |
||||
"github.com/btcsuite/btcd/txscript" |
||||
"github.com/btcsuite/btcd/wire" |
||||
"github.com/btcsuite/btcutil" |
||||
"github.com/btcsuite/btcwallet/wallet/txauthor" |
||||
"github.com/btcsuite/btcwallet/wtxmgr" |
||||
"github.com/lightningnetwork/lnd/chainntnfs" |
||||
"github.com/lightningnetwork/lnd/channeldb" |
||||
"github.com/lightningnetwork/lnd/htlcswitch" |
||||
"github.com/lightningnetwork/lnd/input" |
||||
"github.com/lightningnetwork/lnd/keychain" |
||||
"github.com/lightningnetwork/lnd/lnwallet" |
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee" |
||||
"github.com/lightningnetwork/lnd/lnwire" |
||||
"github.com/lightningnetwork/lnd/netann" |
||||
"github.com/lightningnetwork/lnd/queue" |
||||
"github.com/lightningnetwork/lnd/shachain" |
||||
"github.com/lightningnetwork/lnd/ticker" |
||||
) |
||||
|
||||
const ( |
||||
broadcastHeight = 100 |
||||
) |
||||
|
||||
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 |
||||
|
||||
// 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, |
||||
} |
||||
) |
||||
|
||||
// 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) {} |
||||
|
||||
type mockSigner struct { |
||||
key *btcec.PrivateKey |
||||
} |
||||
|
||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, |
||||
signDesc *input.SignDescriptor) (input.Signature, error) { |
||||
amt := signDesc.Output.Value |
||||
witnessScript := signDesc.WitnessScript |
||||
privKey := m.key |
||||
|
||||
if !privKey.PubKey().IsEqual(signDesc.KeyDesc.PubKey) { |
||||
return nil, fmt.Errorf("incorrect key passed") |
||||
} |
||||
|
||||
switch { |
||||
case signDesc.SingleTweak != nil: |
||||
privKey = input.TweakPrivKey(privKey, |
||||
signDesc.SingleTweak) |
||||
case signDesc.DoubleTweak != nil: |
||||
privKey = input.DeriveRevocationPrivKey(privKey, |
||||
signDesc.DoubleTweak) |
||||
} |
||||
|
||||
sig, err := txscript.RawTxInWitnessSignature(tx, signDesc.SigHashes, |
||||
signDesc.InputIndex, amt, witnessScript, signDesc.HashType, |
||||
privKey) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return btcec.ParseDERSignature(sig[:len(sig)-1], btcec.S256()) |
||||
} |
||||
|
||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, |
||||
signDesc *input.SignDescriptor) (*input.Script, error) { |
||||
|
||||
// TODO(roasbeef): expose tweaked signer from lnwallet so don't need to
|
||||
// duplicate this code?
|
||||
|
||||
privKey := m.key |
||||
|
||||
switch { |
||||
case signDesc.SingleTweak != nil: |
||||
privKey = input.TweakPrivKey(privKey, |
||||
signDesc.SingleTweak) |
||||
case signDesc.DoubleTweak != nil: |
||||
privKey = input.DeriveRevocationPrivKey(privKey, |
||||
signDesc.DoubleTweak) |
||||
} |
||||
|
||||
witnessScript, err := txscript.WitnessSignature(tx, signDesc.SigHashes, |
||||
signDesc.InputIndex, signDesc.Output.Value, signDesc.Output.PkScript, |
||||
signDesc.HashType, privKey, true) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
return &input.Script{ |
||||
Witness: witnessScript, |
||||
}, nil |
||||
} |
||||
|
||||
var _ input.Signer = (*mockSigner)(nil) |
||||
|
||||
type mockChainIO struct { |
||||
bestHeight int32 |
||||
} |
||||
|
||||
func (m *mockChainIO) GetBestBlock() (*chainhash.Hash, int32, error) { |
||||
return nil, m.bestHeight, nil |
||||
} |
||||
|
||||
func (*mockChainIO) GetUtxo(op *wire.OutPoint, _ []byte, |
||||
heightHint uint32, _ <-chan struct{}) (*wire.TxOut, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockChainIO) GetBlockHash(blockHeight int64) (*chainhash.Hash, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockChainIO) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
var _ lnwallet.BlockChainIO = (*mockChainIO)(nil) |
||||
|
||||
type mockWalletController struct { |
||||
rootKey *btcec.PrivateKey |
||||
publishedTxns chan *wire.MsgTx |
||||
} |
||||
|
||||
func (*mockWalletController) FetchInputInfo(prevOut *wire.OutPoint) ( |
||||
*lnwallet.Utxo, error) { |
||||
|
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockWalletController) ConfirmedBalance(confs int32) (btcutil.Amount, |
||||
error) { |
||||
|
||||
return 0, nil |
||||
} |
||||
|
||||
func (m *mockWalletController) NewAddress(addrType lnwallet.AddressType, |
||||
change bool) (btcutil.Address, error) { |
||||
|
||||
addr, _ := btcutil.NewAddressPubKey( |
||||
m.rootKey.PubKey().SerializeCompressed(), &chaincfg.MainNetParams, |
||||
) |
||||
return addr, nil |
||||
} |
||||
|
||||
func (*mockWalletController) LastUnusedAddress(addrType lnwallet.AddressType) ( |
||||
btcutil.Address, error) { |
||||
|
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockWalletController) IsOurAddress(a btcutil.Address) bool { |
||||
return false |
||||
} |
||||
|
||||
func (*mockWalletController) SendOutputs(outputs []*wire.TxOut, |
||||
feeRate chainfee.SatPerKWeight, label string) (*wire.MsgTx, error) { |
||||
|
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockWalletController) CreateSimpleTx(outputs []*wire.TxOut, |
||||
feeRate chainfee.SatPerKWeight, dryRun bool) (*txauthor.AuthoredTx, error) { |
||||
|
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockWalletController) ListUnspentWitness(minconfirms, |
||||
maxconfirms int32) ([]*lnwallet.Utxo, error) { |
||||
|
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockWalletController) ListTransactionDetails(startHeight, |
||||
endHeight int32) ([]*lnwallet.TransactionDetail, error) { |
||||
|
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockWalletController) LockOutpoint(o wire.OutPoint) {} |
||||
|
||||
func (*mockWalletController) UnlockOutpoint(o wire.OutPoint) {} |
||||
|
||||
func (m *mockWalletController) PublishTransaction(tx *wire.MsgTx, |
||||
label string) error { |
||||
m.publishedTxns <- tx |
||||
return nil |
||||
} |
||||
|
||||
func (*mockWalletController) LabelTransaction(hash chainhash.Hash, |
||||
label string, overwrite bool) error { |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func (*mockWalletController) SubscribeTransactions() ( |
||||
lnwallet.TransactionSubscription, error) { |
||||
|
||||
return nil, nil |
||||
} |
||||
|
||||
func (*mockWalletController) IsSynced() (bool, int64, error) { |
||||
return false, 0, nil |
||||
} |
||||
|
||||
func (*mockWalletController) Start() error { |
||||
return nil |
||||
} |
||||
|
||||
func (*mockWalletController) Stop() error { |
||||
return nil |
||||
} |
||||
|
||||
func (*mockWalletController) BackEnd() string { |
||||
return "" |
||||
} |
||||
|
||||
func (*mockWalletController) LeaseOutput(wtxmgr.LockID, |
||||
wire.OutPoint) (time.Time, error) { |
||||
|
||||
return time.Now(), nil |
||||
} |
||||
|
||||
func (*mockWalletController) ReleaseOutput(wtxmgr.LockID, wire.OutPoint) error { |
||||
return nil |
||||
} |
||||
|
||||
func (*mockWalletController) GetRecoveryInfo() (bool, float64, error) { |
||||
return false, 0, nil |
||||
} |
||||
|
||||
var _ lnwallet.WalletController = (*mockWalletController)(nil) |
||||
|
||||
type mockNotifier struct { |
||||
confChannel chan *chainntnfs.TxConfirmation |
||||
} |
||||
|
||||
func (m *mockNotifier) RegisterConfirmationsNtfn(txid *chainhash.Hash, |
||||
_ []byte, numConfs, heightHint uint32) (*chainntnfs.ConfirmationEvent, |
||||
error) { |
||||
|
||||
return &chainntnfs.ConfirmationEvent{ |
||||
Confirmed: m.confChannel, |
||||
}, nil |
||||
} |
||||
|
||||
func (m *mockNotifier) RegisterSpendNtfn(outpoint *wire.OutPoint, _ []byte, |
||||
heightHint uint32) (*chainntnfs.SpendEvent, error) { |
||||
|
||||
return &chainntnfs.SpendEvent{ |
||||
Spend: make(chan *chainntnfs.SpendDetail), |
||||
Cancel: func() {}, |
||||
}, nil |
||||
} |
||||
|
||||
func (m *mockNotifier) RegisterBlockEpochNtfn( |
||||
bestBlock *chainntnfs.BlockEpoch) (*chainntnfs.BlockEpochEvent, error) { |
||||
|
||||
return &chainntnfs.BlockEpochEvent{ |
||||
Epochs: make(chan *chainntnfs.BlockEpoch), |
||||
Cancel: func() {}, |
||||
}, nil |
||||
} |
||||
|
||||
func (m *mockNotifier) Start() error { |
||||
return nil |
||||
} |
||||
|
||||
func (m *mockNotifier) Stop() error { |
||||
return nil |
||||
} |
||||
|
||||
func (m *mockNotifier) Started() bool { |
||||
return true |
||||
} |
||||
|
||||
var _ chainntnfs.ChainNotifier = (*mockNotifier)(nil) |
||||
|
||||
// createTestPeer creates a channel between two nodes, and returns a peer for
|
||||
// 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)) ( |
||||
*Brontide, *lnwallet.LightningChannel, func(), error) { |
||||
|
||||
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes( |
||||
btcec.S256(), alicesPrivKey, |
||||
) |
||||
aliceKeySigner := &keychain.PrivKeyDigestSigner{PrivKey: aliceKeyPriv} |
||||
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes( |
||||
btcec.S256(), bobsPrivKey, |
||||
) |
||||
|
||||
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, |
||||
MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()), |
||||
ChanReserve: btcutil.Amount(rand.Int63()), |
||||
MinHTLC: lnwire.MilliSatoshi(rand.Int63()), |
||||
MaxAcceptedHtlcs: uint16(rand.Int31()), |
||||
CsvDelay: uint16(csvTimeoutAlice), |
||||
}, |
||||
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, |
||||
}, |
||||
} |
||||
bobCfg := channeldb.ChannelConfig{ |
||||
ChannelConstraints: channeldb.ChannelConstraints{ |
||||
DustLimit: bobDustLimit, |
||||
MaxPendingAmount: lnwire.MilliSatoshi(rand.Int63()), |
||||
ChanReserve: btcutil.Amount(rand.Int63()), |
||||
MinHTLC: lnwire.MilliSatoshi(rand.Int63()), |
||||
MaxAcceptedHtlcs: uint16(rand.Int31()), |
||||
CsvDelay: uint16(csvTimeoutBob), |
||||
}, |
||||
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, |
||||
}, |
||||
} |
||||
|
||||
bobRoot, err := chainhash.NewHash(bobKeyPriv.Serialize()) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
bobPreimageProducer := shachain.NewRevocationProducer(*bobRoot) |
||||
bobFirstRevoke, err := bobPreimageProducer.AtIndex(0) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:]) |
||||
|
||||
aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize()) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
alicePreimageProducer := shachain.NewRevocationProducer(*aliceRoot) |
||||
aliceFirstRevoke, err := alicePreimageProducer.AtIndex(0) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:]) |
||||
|
||||
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns( |
||||
channelBal, channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, |
||||
bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit, |
||||
) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
alicePath, err := ioutil.TempDir("", "alicedb") |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
dbAlice, err := channeldb.Open(alicePath) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
bobPath, err := ioutil.TempDir("", "bobdb") |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
dbBob, err := channeldb.Open(bobPath) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
estimator := chainfee.NewStaticEstimator(12500, 0) |
||||
feePerKw, err := estimator.EstimateFeePerKW(1) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
// TODO(roasbeef): need to factor in commit fee?
|
||||
aliceCommit := channeldb.ChannelCommitment{ |
||||
CommitHeight: 0, |
||||
LocalBalance: lnwire.NewMSatFromSatoshis(channelBal), |
||||
RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal), |
||||
FeePerKw: btcutil.Amount(feePerKw), |
||||
CommitFee: feePerKw.FeeForWeight(input.CommitWeight), |
||||
CommitTx: aliceCommitTx, |
||||
CommitSig: bytes.Repeat([]byte{1}, 71), |
||||
} |
||||
bobCommit := channeldb.ChannelCommitment{ |
||||
CommitHeight: 0, |
||||
LocalBalance: lnwire.NewMSatFromSatoshis(channelBal), |
||||
RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal), |
||||
FeePerKw: btcutil.Amount(feePerKw), |
||||
CommitFee: feePerKw.FeeForWeight(input.CommitWeight), |
||||
CommitTx: bobCommitTx, |
||||
CommitSig: bytes.Repeat([]byte{1}, 71), |
||||
} |
||||
|
||||
var chanIDBytes [8]byte |
||||
if _, err := io.ReadFull(crand.Reader, chanIDBytes[:]); err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
shortChanID := lnwire.NewShortChanIDFromInt( |
||||
binary.BigEndian.Uint64(chanIDBytes[:]), |
||||
) |
||||
|
||||
aliceChannelState := &channeldb.OpenChannel{ |
||||
LocalChanCfg: aliceCfg, |
||||
RemoteChanCfg: bobCfg, |
||||
IdentityPub: aliceKeyPub, |
||||
FundingOutpoint: *prevOut, |
||||
ShortChannelID: shortChanID, |
||||
ChanType: channeldb.SingleFunderTweaklessBit, |
||||
IsInitiator: true, |
||||
Capacity: channelCapacity, |
||||
RemoteCurrentRevocation: bobCommitPoint, |
||||
RevocationProducer: alicePreimageProducer, |
||||
RevocationStore: shachain.NewRevocationStore(), |
||||
LocalCommitment: aliceCommit, |
||||
RemoteCommitment: aliceCommit, |
||||
Db: dbAlice, |
||||
Packager: channeldb.NewChannelPackager(shortChanID), |
||||
FundingTxn: testTx, |
||||
} |
||||
bobChannelState := &channeldb.OpenChannel{ |
||||
LocalChanCfg: bobCfg, |
||||
RemoteChanCfg: aliceCfg, |
||||
IdentityPub: bobKeyPub, |
||||
FundingOutpoint: *prevOut, |
||||
ChanType: channeldb.SingleFunderTweaklessBit, |
||||
IsInitiator: false, |
||||
Capacity: channelCapacity, |
||||
RemoteCurrentRevocation: aliceCommitPoint, |
||||
RevocationProducer: bobPreimageProducer, |
||||
RevocationStore: shachain.NewRevocationStore(), |
||||
LocalCommitment: bobCommit, |
||||
RemoteCommitment: bobCommit, |
||||
Db: dbBob, |
||||
Packager: channeldb.NewChannelPackager(shortChanID), |
||||
} |
||||
|
||||
// Set custom values on the channel states.
|
||||
updateChan(aliceChannelState, bobChannelState) |
||||
|
||||
aliceAddr := &net.TCPAddr{ |
||||
IP: net.ParseIP("127.0.0.1"), |
||||
Port: 18555, |
||||
} |
||||
|
||||
if err := aliceChannelState.SyncPending(aliceAddr, 0); err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
bobAddr := &net.TCPAddr{ |
||||
IP: net.ParseIP("127.0.0.1"), |
||||
Port: 18556, |
||||
} |
||||
|
||||
if err := bobChannelState.SyncPending(bobAddr, 0); err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
cleanUpFunc := func() { |
||||
os.RemoveAll(bobPath) |
||||
os.RemoveAll(alicePath) |
||||
} |
||||
|
||||
aliceSigner := &mockSigner{aliceKeyPriv} |
||||
bobSigner := &mockSigner{bobKeyPriv} |
||||
|
||||
alicePool := lnwallet.NewSigPool(1, aliceSigner) |
||||
channelAlice, err := lnwallet.NewLightningChannel( |
||||
aliceSigner, aliceChannelState, alicePool, |
||||
) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
_ = alicePool.Start() |
||||
|
||||
bobPool := lnwallet.NewSigPool(1, bobSigner) |
||||
channelBob, err := lnwallet.NewLightningChannel( |
||||
bobSigner, bobChannelState, bobPool, |
||||
) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
_ = bobPool.Start() |
||||
|
||||
chainIO := &mockChainIO{ |
||||
bestHeight: broadcastHeight, |
||||
} |
||||
wallet := &lnwallet.LightningWallet{ |
||||
WalletController: &mockWalletController{ |
||||
rootKey: aliceKeyPriv, |
||||
publishedTxns: publTx, |
||||
}, |
||||
} |
||||
|
||||
_, currentHeight, err := chainIO.GetBestBlock() |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
htlcSwitch, err := htlcswitch.New(htlcswitch.Config{ |
||||
DB: dbAlice, |
||||
SwitchPackager: channeldb.NewSwitchPackager(), |
||||
Notifier: notifier, |
||||
FwdEventTicker: ticker.New( |
||||
htlcswitch.DefaultFwdEventInterval), |
||||
LogEventTicker: ticker.New( |
||||
htlcswitch.DefaultLogInterval), |
||||
AckEventTicker: ticker.New( |
||||
htlcswitch.DefaultAckInterval), |
||||
}, uint32(currentHeight)) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
if err = htlcSwitch.Start(); err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
nodeSignerAlice := netann.NewNodeSigner(aliceKeySigner) |
||||
|
||||
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: htlcSwitch.HasActiveLink, |
||||
ApplyChannelUpdate: func(*lnwire.ChannelUpdate) error { return nil }, |
||||
}) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
if err = chanStatusMgr.Start(); err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
errBuffer, err := queue.NewCircularBuffer(ErrorBufferSize) |
||||
if err != nil { |
||||
return nil, nil, nil, err |
||||
} |
||||
|
||||
var pubKey [33]byte |
||||
copy(pubKey[:], aliceKeyPub.SerializeCompressed()) |
||||
|
||||
cfgAddr := &lnwire.NetAddress{ |
||||
IdentityKey: aliceKeyPub, |
||||
Address: aliceAddr, |
||||
ChainNet: wire.SimNet, |
||||
} |
||||
|
||||
cfg := &Config{ |
||||
Addr: cfgAddr, |
||||
PubKeyBytes: pubKey, |
||||
ErrorBuffer: errBuffer, |
||||
ChainIO: chainIO, |
||||
Switch: htlcSwitch, |
||||
|
||||
ChanActiveTimeout: chanActiveTimeout, |
||||
InterceptSwitch: htlcswitch.NewInterceptableSwitch(htlcSwitch), |
||||
|
||||
ChannelDB: dbAlice, |
||||
FeeEstimator: estimator, |
||||
Wallet: wallet, |
||||
ChainNotifier: notifier, |
||||
ChanStatusMgr: chanStatusMgr, |
||||
DisconnectPeer: func(b *btcec.PublicKey) error { return nil }, |
||||
} |
||||
|
||||
alicePeer := NewBrontide(*cfg) |
||||
|
||||
chanID := lnwire.NewChanIDFromOutPoint(channelAlice.ChannelPoint()) |
||||
alicePeer.activeChannels[chanID] = channelAlice |
||||
|
||||
alicePeer.wg.Add(1) |
||||
go alicePeer.channelManager() |
||||
|
||||
return alicePeer, channelBob, cleanUpFunc, nil |
||||
} |
Loading…
Reference in new issue