multi: add open channel utility
This commit is contained in:
parent
35fa9fa540
commit
e3d06ebd64
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Mine n blocks using bitcoin cli.
|
||||
func Mine(n int) error {
|
||||
// Santiy check for fat fingering to stop us setting our laptops on
|
||||
// fire, can be removed.
|
||||
if n > 1000{
|
||||
return fmt.Errorf("trying to mine: %v blocks failed "+
|
||||
"santiy check", n)
|
||||
}
|
||||
|
||||
cmd := exec.Command("bitcoin-cli", "-generate", strconv.Itoa(n))
|
||||
|
||||
_, err := cmd.Output()
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
)
|
||||
|
||||
// GraphHarness is responsible for all graph related operations (P2P, channels,
|
||||
// gossip etc).
|
||||
type GraphHarness struct {
|
||||
LndNodes Nodes
|
||||
}
|
||||
|
||||
type OpenChannelReq struct {
|
||||
Source int
|
||||
Dest route.Vertex
|
||||
// Host is an optional host address for the node, we'll lookup in our
|
||||
// graph if this value is empty.
|
||||
Host string
|
||||
CapacitySat btcutil.Amount
|
||||
PushAmt btcutil.Amount
|
||||
Private bool
|
||||
}
|
||||
|
||||
// OpenChannel is a blocking call that opens a channel from the source node
|
||||
// provided to the target:
|
||||
// - looks up a node in the graph
|
||||
// - connects to it if we are not currently connected
|
||||
// - opens a channel with the parameters provided
|
||||
// - opens a channel and mines block to confirm it
|
||||
// - waits for the channel to be active
|
||||
func (c *GraphHarness) OpenChannel(ctx context.Context,
|
||||
req OpenChannelReq) (*wire.OutPoint, error) {
|
||||
|
||||
connected, err := c.PeerConnected(ctx, req.Source, req.Dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !connected {
|
||||
host := req.Host
|
||||
if host == "" {
|
||||
node, err := c.LookupNode(
|
||||
ctx, req.Source, req.Dest, false,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(node.Addresses) == 0 {
|
||||
return nil, fmt.Errorf("no public address "+
|
||||
"for: %v", req.Dest)
|
||||
}
|
||||
|
||||
host = node.Addresses[0]
|
||||
}
|
||||
|
||||
err = c.ConnectPeer(ctx, req.Source, req.Dest, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
sourceNode := c.LndNodes.GetNode(req.Source)
|
||||
streamChan, errChan, err := sourceNode.Client.OpenChannelStream(
|
||||
ctx, req.Dest, req.CapacitySat, req.PushAmt, req.Private,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case update := <-streamChan:
|
||||
// Wait for the channel to be pending before we mine.
|
||||
if update.ChanPending != nil {
|
||||
if err := Mine(6); err != nil {
|
||||
return nil, fmt.Errorf("could not "+
|
||||
"mine: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if update.ChanOpen != nil {
|
||||
return outpointFromRPC(
|
||||
update.ChanOpen.ChannelPoint,
|
||||
), nil
|
||||
}
|
||||
|
||||
case e := <-errChan:
|
||||
return nil, e
|
||||
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (c *GraphHarness) LookupNode(ctx context.Context, source int,
|
||||
dest route.Vertex, includeChannels bool) (*lndclient.NodeInfo, error) {
|
||||
|
||||
sourceNode := c.LndNodes.GetNode(source)
|
||||
destNode, err := sourceNode.Client.GetNodeInfo(
|
||||
ctx, dest, includeChannels,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return destNode, nil
|
||||
}
|
||||
|
||||
func (c *GraphHarness) ConnectPeer(ctx context.Context, source int,
|
||||
dest route.Vertex, addr string) error {
|
||||
|
||||
sourceNode := c.LndNodes.GetNode(source)
|
||||
if err := sourceNode.Client.Connect(ctx, dest, addr, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
connected, err := c.PeerConnected(ctx, source, dest)
|
||||
if err != nil || connected {
|
||||
return err
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second):
|
||||
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("timeout waiting for peer: %v to connect", dest)
|
||||
}
|
||||
|
||||
func (c *GraphHarness) PeerConnected(ctx context.Context, source int,
|
||||
target route.Vertex) (bool, error) {
|
||||
|
||||
sourceNode := c.LndNodes.GetNode(source)
|
||||
|
||||
peers, err := sourceNode.Client.ListPeers(ctx)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for _, peer := range peers {
|
||||
if peer.Pubkey == target {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
|
@ -3,6 +3,9 @@ package main
|
|||
import (
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
)
|
||||
|
||||
|
@ -16,10 +19,34 @@ func genPreimage() lntypes.Preimage {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
preimage, err:= lntypes.MakePreimage(randomBytes)
|
||||
if err!=nil{
|
||||
panic(err)
|
||||
}
|
||||
preimage, err := lntypes.MakePreimage(randomBytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return preimage
|
||||
return preimage
|
||||
}
|
||||
|
||||
func outpointFromRPC(rpc *lnrpc.ChannelPoint) *wire.OutPoint {
|
||||
var (
|
||||
hash *chainhash.Hash
|
||||
err error
|
||||
)
|
||||
|
||||
switch h := rpc.FundingTxid.(type) {
|
||||
case *lnrpc.ChannelPoint_FundingTxidBytes:
|
||||
hash, err = chainhash.NewHash(h.FundingTxidBytes)
|
||||
|
||||
case *lnrpc.ChannelPoint_FundingTxidStr:
|
||||
hash, err = chainhash.NewHashFromStr(h.FundingTxidStr)
|
||||
|
||||
default:
|
||||
panic("Unknown channel point type")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return wire.NewOutPoint(hash, rpc.OutputIndex)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue