github.com/decred/dcrlnd@v0.7.6/cmd/dcrlncli/cmd_open_channel.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto/rand"
     7  	"encoding/base64"
     8  	"encoding/hex"
     9  	"encoding/json"
    10  	"fmt"
    11  	"io"
    12  	"io/ioutil"
    13  	"os"
    14  	"strconv"
    15  	"strings"
    16  
    17  	"github.com/decred/dcrd/chaincfg/chainhash"
    18  	"github.com/decred/dcrd/dcrutil/v4"
    19  	"github.com/decred/dcrd/wire"
    20  	"github.com/decred/dcrlnd/lnrpc"
    21  	"github.com/decred/dcrlnd/lnwallet/chanfunding"
    22  	"github.com/urfave/cli"
    23  )
    24  
    25  const (
    26  	userMsgFund = `PSBT funding initiated with peer %x.
    27  Please create a PSBT that sends %v (%d satoshi) to the funding address %s.
    28  
    29  Note: The whole process should be completed within 10 minutes, otherwise there
    30  is a risk of the remote node timing out and canceling the funding process.
    31  
    32  Example with bitcoind:
    33  	bitcoin-cli walletcreatefundedpsbt [] '[{"%s":%.8f}]'
    34  
    35  If you are using a wallet that can fund a PSBT directly (currently not possible
    36  with bitcoind), you can use this PSBT that contains the same address and amount:
    37  %s
    38  
    39  !!! WARNING !!!
    40  DO NOT PUBLISH the finished transaction by yourself or with another tool.
    41  lnd MUST publish it in the proper funding flow order OR THE FUNDS CAN BE LOST!
    42  
    43  Paste the funded PSBT here to continue the funding flow.
    44  If your PSBT is very long (specifically, more than 4096 characters), please save
    45  it to a file and paste the full file path here instead as some terminals will
    46  truncate the pasted text if it's too long.
    47  Base64 encoded PSBT (or path to text file): `
    48  
    49  	userMsgSign = `
    50  PSBT verified by lnd, please continue the funding flow by signing the PSBT by
    51  all required parties/devices. Once the transaction is fully signed, paste it
    52  again here either in base64 PSBT or hex encoded raw wire TX format.
    53  
    54  Signed base64 encoded PSBT or hex encoded raw wire TX (or path to text file): `
    55  
    56  	// psbtMaxFileSize is the maximum file size we allow a PSBT file to be
    57  	// in case we want to read a PSBT from a file. This is mainly to protect
    58  	// the user from choosing a large file by accident and running into out
    59  	// of memory issues or other weird errors.
    60  	psbtMaxFileSize = 1024 * 1024
    61  
    62  	channelTypeTweakless = "tweakless"
    63  	channelTypeAnchors   = "anchors"
    64  )
    65  
    66  // TODO(roasbeef): change default number of confirmations
    67  var openChannelCommand = cli.Command{
    68  	Name:     "openchannel",
    69  	Category: "Channels",
    70  	Usage:    "Open a channel to a node or an existing peer.",
    71  	Description: `
    72  	Attempt to open a new channel to an existing peer with the key node-key
    73  	optionally blocking until the channel is 'open'.
    74  
    75  	One can also connect to a node before opening a new channel to it by
    76  	setting its host:port via the '--connect' argument. For this to work,
    77  	the 'node_key' must be provided, rather than the 'peer_id'. This is optional.
    78  
    79  	The channel will be initialized with 'local-amt' atoms locally and 'push-amt'
    80  	atoms for the remote node. Note that specifying push-amt means you give that
    81  	amount to the remote node as part of the channel opening. Once the channel is open,
    82  	a 'channelPoint' ('txid:vout') of the funding output is returned.
    83  
    84  	If the remote peer supports the option upfront shutdown feature bit (query
    85  	'listpeers' to see their supported feature bits), an address to enforce
    86  	payout of funds on cooperative close can optionally be provided. Note that
    87  	if you set this value, you will not be able to cooperatively close out to
    88  	another address.
    89  
    90  	One can manually set the fee to be used for the funding transaction via either
    91  	the '--conf_target' or '--atoms_per_byte' arguments. This is optional.`,
    92  	ArgsUsage: "node-key local-amt push-amt",
    93  	Flags: []cli.Flag{
    94  		cli.StringFlag{
    95  			Name: "node_key",
    96  			Usage: "The identity public key of the target node/peer " +
    97  				"serialized in compressed format",
    98  		},
    99  		cli.StringFlag{
   100  			Name:  "connect",
   101  			Usage: "The host:port of the target node (optional)",
   102  		},
   103  		cli.IntFlag{
   104  			Name:  "local_amt",
   105  			Usage: "The number of atoms the wallet should commit to the channel",
   106  		},
   107  		cli.IntFlag{
   108  			Name: "push_amt",
   109  			Usage: "The number of atoms to give the remote side " +
   110  				"as part of the initial commitment state, " +
   111  				"this is equivalent to first opening a " +
   112  				"channel and sending the remote party funds, " +
   113  				"but done all in one step",
   114  		},
   115  		cli.BoolFlag{
   116  			Name:  "block",
   117  			Usage: "Block and wait until the channel is fully open",
   118  		},
   119  		cli.Int64Flag{
   120  			Name: "conf_target",
   121  			Usage: "The number of blocks that the " +
   122  				"transaction *should* confirm in, will be " +
   123  				"used for fee estimation (optional)",
   124  		},
   125  		cli.Int64Flag{
   126  			Name: "atoms_per_byte",
   127  			Usage: "A manual fee expressed in " +
   128  				"atom/byte that should be used when crafting " +
   129  				"the transaction (optional)",
   130  		},
   131  		cli.BoolFlag{
   132  			Name: "private",
   133  			Usage: "Make the channel private, such that it won't " +
   134  				"be announced to the greater network, and " +
   135  				"nodes other than the two channel endpoints " +
   136  				"must be explicitly told about it to be able " +
   137  				"to route through it",
   138  		},
   139  		cli.Int64Flag{
   140  			Name: "min_htlc_m_atoms",
   141  			Usage: "The minimum value we will require " +
   142  				"for incoming HTLCs on the channel (optional)",
   143  		},
   144  		cli.Uint64Flag{
   145  			Name: "remote_csv_delay",
   146  			Usage: "The number of blocks we will require " +
   147  				"our channel counterparty to wait before accessing " +
   148  				"its funds in case of unilateral close. If this is " +
   149  				"not set, we will scale the value according to the " +
   150  				"channel size (optional)",
   151  		},
   152  		cli.Uint64Flag{
   153  			Name: "max_local_csv",
   154  			Usage: "(optional) the maximum number of blocks that " +
   155  				"we will allow the remote peer to require we " +
   156  				"wait before accessing our funds in the case " +
   157  				"of a unilateral close.",
   158  		},
   159  		cli.Uint64Flag{
   160  			Name: "min_confs",
   161  			Usage: "The minimum number of confirmations " +
   162  				"each one of your outputs used for the funding " +
   163  				"transaction must satisfy (optional)",
   164  			Value: defaultUtxoMinConf,
   165  		},
   166  		cli.StringFlag{
   167  			Name: "close_address",
   168  			Usage: "An address to enforce payout of our " +
   169  				"funds to on cooperative close. Note that if this " +
   170  				"value is set on channel open, you will *not* be " +
   171  				"able to cooperatively close to a different address (optional)",
   172  		},
   173  		cli.BoolFlag{
   174  			Name: "psbt",
   175  			Usage: "start an interactive mode that initiates " +
   176  				"funding through a partially signed bitcoin " +
   177  				"transaction (PSBT), allowing the channel " +
   178  				"funds to be added and signed from a hardware " +
   179  				"or other offline device.",
   180  		},
   181  		cli.StringFlag{
   182  			Name: "base_psbt",
   183  			Usage: "when using the interactive PSBT mode to open " +
   184  				"a new channel, use this base64 encoded PSBT " +
   185  				"as a base and add the new channel output to " +
   186  				"it instead of creating a new, empty one.",
   187  		},
   188  		cli.BoolFlag{
   189  			Name: "no_publish",
   190  			Usage: "when using the interactive PSBT mode to open " +
   191  				"multiple channels in a batch, this flag " +
   192  				"instructs lnd to not publish the full batch " +
   193  				"transaction just yet. For safety reasons " +
   194  				"this flag should be set for each of the " +
   195  				"batch's transactions except the very last",
   196  		},
   197  		cli.Uint64Flag{
   198  			Name: "remote_max_value_in_flight_m_atoms",
   199  			Usage: "The maximum value in matoms that " +
   200  				"can be pending within the channel at any " +
   201  				"given time (optional).",
   202  		},
   203  		cli.StringFlag{
   204  			Name: "channel_type",
   205  			Usage: fmt.Sprintf("(optional) the type of channel to "+
   206  				"propose to the remote peer (%q, %q)",
   207  				channelTypeTweakless, channelTypeAnchors),
   208  		},
   209  	},
   210  	Action: actionDecorator(openChannel),
   211  }
   212  
   213  func openChannel(ctx *cli.Context) error {
   214  	// TODO(roasbeef): add deadline to context
   215  	ctxc := getContext()
   216  	client, cleanUp := getClient(ctx)
   217  	defer cleanUp()
   218  
   219  	args := ctx.Args()
   220  	var err error
   221  
   222  	// Show command help if no arguments provided
   223  	if ctx.NArg() == 0 && ctx.NumFlags() == 0 {
   224  		_ = cli.ShowCommandHelp(ctx, "openchannel")
   225  		return nil
   226  	}
   227  
   228  	minConfs := int32(ctx.Uint64("min_confs"))
   229  	req := &lnrpc.OpenChannelRequest{
   230  		TargetConf:                   int32(ctx.Int64("conf_target")),
   231  		AtomsPerByte:                 ctx.Int64("atoms_per_byte"),
   232  		MinHtlcMAtoms:                ctx.Int64("min_htlc_m_atoms"),
   233  		RemoteCsvDelay:               uint32(ctx.Uint64("remote_csv_delay")),
   234  		MinConfs:                     minConfs,
   235  		SpendUnconfirmed:             minConfs == 0,
   236  		CloseAddress:                 ctx.String("close_address"),
   237  		RemoteMaxValueInFlightMAtoms: ctx.Uint64("remote_max_value_in_flight_m_atoms"),
   238  		MaxLocalCsv:                  uint32(ctx.Uint64("max_local_csv")),
   239  	}
   240  
   241  	switch {
   242  	case ctx.IsSet("node_key"):
   243  		nodePubHex, err := hex.DecodeString(ctx.String("node_key"))
   244  		if err != nil {
   245  			return fmt.Errorf("unable to decode node public key: %v", err)
   246  		}
   247  		req.NodePubkey = nodePubHex
   248  
   249  	case args.Present():
   250  		nodePubHex, err := hex.DecodeString(args.First())
   251  		if err != nil {
   252  			return fmt.Errorf("unable to decode node public key: %v", err)
   253  		}
   254  		args = args.Tail()
   255  		req.NodePubkey = nodePubHex
   256  	default:
   257  		return fmt.Errorf("node id argument missing")
   258  	}
   259  
   260  	// As soon as we can confirm that the node's node_key was set, rather
   261  	// than the peer_id, we can check if the host:port was also set to
   262  	// connect to it before opening the channel.
   263  	if req.NodePubkey != nil && ctx.IsSet("connect") {
   264  		addr := &lnrpc.LightningAddress{
   265  			Pubkey: hex.EncodeToString(req.NodePubkey),
   266  			Host:   ctx.String("connect"),
   267  		}
   268  
   269  		req := &lnrpc.ConnectPeerRequest{
   270  			Addr: addr,
   271  			Perm: false,
   272  		}
   273  
   274  		// Check if connecting to the node was successful.
   275  		// We discard the peer id returned as it is not needed.
   276  		_, err := client.ConnectPeer(ctxc, req)
   277  		if err != nil &&
   278  			!strings.Contains(err.Error(), "already connected") {
   279  			return err
   280  		}
   281  	}
   282  
   283  	switch {
   284  	case ctx.IsSet("local_amt"):
   285  		req.LocalFundingAmount = int64(ctx.Int("local_amt"))
   286  	case args.Present():
   287  		req.LocalFundingAmount, err = strconv.ParseInt(args.First(), 10, 64)
   288  		if err != nil {
   289  			return fmt.Errorf("unable to decode local amt: %v", err)
   290  		}
   291  		args = args.Tail()
   292  	default:
   293  		return fmt.Errorf("local amt argument missing")
   294  	}
   295  
   296  	if ctx.IsSet("push_amt") {
   297  		req.PushAtoms = int64(ctx.Int("push_amt"))
   298  	} else if args.Present() {
   299  		req.PushAtoms, err = strconv.ParseInt(args.First(), 10, 64)
   300  		if err != nil {
   301  			return fmt.Errorf("unable to decode push amt: %v", err)
   302  		}
   303  	}
   304  
   305  	req.Private = ctx.Bool("private")
   306  
   307  	// Parse the channel type and map it to its RPC representation.
   308  	channelType := ctx.String("channel_type")
   309  	switch channelType {
   310  	case "":
   311  		break
   312  	case channelTypeTweakless:
   313  		req.CommitmentType = lnrpc.CommitmentType_STATIC_REMOTE_KEY
   314  	case channelTypeAnchors:
   315  		req.CommitmentType = lnrpc.CommitmentType_ANCHORS
   316  	default:
   317  		return fmt.Errorf("unsupported channel type %v", channelType)
   318  	}
   319  
   320  	// PSBT funding is a more involved, interactive process that is too
   321  	// large to also fit into this already long function.
   322  	if ctx.Bool("psbt") {
   323  		return openChannelPsbt(ctxc, ctx, client, req)
   324  	}
   325  	if !ctx.Bool("psbt") && ctx.Bool("no_publish") {
   326  		return fmt.Errorf("the --no_publish flag can only be used in " +
   327  			"combination with the --psbt flag")
   328  	}
   329  
   330  	stream, err := client.OpenChannel(ctxc, req)
   331  	if err != nil {
   332  		return err
   333  	}
   334  
   335  	for {
   336  		resp, err := stream.Recv()
   337  		if err == io.EOF {
   338  			return nil
   339  		} else if err != nil {
   340  			return err
   341  		}
   342  
   343  		switch update := resp.Update.(type) {
   344  		case *lnrpc.OpenStatusUpdate_ChanPending:
   345  			err := printChanPending(update)
   346  			if err != nil {
   347  				return err
   348  			}
   349  
   350  			if !ctx.Bool("block") {
   351  				return nil
   352  			}
   353  
   354  		case *lnrpc.OpenStatusUpdate_ChanOpen:
   355  			return printChanOpen(update)
   356  		}
   357  	}
   358  }
   359  
   360  // openChannelPsbt starts an interactive channel open protocol that uses a
   361  // partially signed bitcoin transaction (PSBT) to fund the channel output. The
   362  // protocol involves several steps between the RPC server and the CLI client:
   363  //
   364  // RPC server                           CLI client
   365  //
   366  //	|                                    |
   367  //	|  |<------open channel (stream)-----|
   368  //	|  |-------ready for funding----->|  |
   369  //	|  |<------PSBT verify------------|  |
   370  //	|  |-------ready for signing----->|  |
   371  //	|  |<------PSBT finalize----------|  |
   372  //	|  |-------channel pending------->|  |
   373  //	|  |-------channel open------------->|
   374  //	|                                    |
   375  //
   376  //nolint:govet
   377  func openChannelPsbt(rpcCtx context.Context, ctx *cli.Context,
   378  	client lnrpc.LightningClient,
   379  	req *lnrpc.OpenChannelRequest) error {
   380  
   381  	return fmt.Errorf("psbt channel opening is not supported in dcrlnd yet")
   382  
   383  	var (
   384  		pendingChanID [32]byte
   385  		shimPending   = true
   386  		basePsbtBytes []byte
   387  		quit          = make(chan struct{})
   388  		srvMsg        = make(chan *lnrpc.OpenStatusUpdate, 1)
   389  		srvErr        = make(chan error, 1)
   390  		ctxc, cancel  = context.WithCancel(rpcCtx)
   391  	)
   392  	defer cancel()
   393  
   394  	// Make sure the user didn't supply any command line flags that are
   395  	// incompatible with PSBT funding.
   396  	err := checkPsbtFlags(req)
   397  	if err != nil {
   398  		return err
   399  	}
   400  
   401  	// If the user supplied a base PSBT, only make sure it's valid base64.
   402  	// The RPC server will make sure it's also a valid PSBT.
   403  	basePsbt := ctx.String("base_psbt")
   404  	if basePsbt != "" {
   405  		basePsbtBytes, err = base64.StdEncoding.DecodeString(basePsbt)
   406  		if err != nil {
   407  			return fmt.Errorf("error parsing base PSBT: %v", err)
   408  		}
   409  	}
   410  
   411  	// Generate a new, random pending channel ID that we'll use as the main
   412  	// identifier when sending update messages to the RPC server.
   413  	if _, err := rand.Read(pendingChanID[:]); err != nil {
   414  		return fmt.Errorf("unable to generate random chan ID: %v", err)
   415  	}
   416  	fmt.Printf("Starting PSBT funding flow with pending channel ID %x.\n",
   417  		pendingChanID)
   418  
   419  	// maybeCancelShim is a helper function that cancels the funding shim
   420  	// with the RPC server in case we end up aborting early.
   421  	maybeCancelShim := func() {
   422  		// If the user canceled while there was still a shim registered
   423  		// with the wallet, release the resources now.
   424  		if shimPending {
   425  			fmt.Printf("Canceling PSBT funding flow for pending "+
   426  				"channel ID %x.\n", pendingChanID)
   427  			cancelMsg := &lnrpc.FundingTransitionMsg{
   428  				Trigger: &lnrpc.FundingTransitionMsg_ShimCancel{
   429  					ShimCancel: &lnrpc.FundingShimCancel{
   430  						PendingChanId: pendingChanID[:],
   431  					},
   432  				},
   433  			}
   434  			err := sendFundingState(ctxc, ctx, cancelMsg)
   435  			if err != nil {
   436  				fmt.Printf("Error canceling shim: %v\n", err)
   437  			}
   438  			shimPending = false
   439  		}
   440  
   441  		// Abort the stream connection to the server.
   442  		cancel()
   443  	}
   444  	defer maybeCancelShim()
   445  
   446  	// Create the PSBT funding shim that will tell the funding manager we
   447  	// want to use a PSBT.
   448  	req.FundingShim = &lnrpc.FundingShim{
   449  		Shim: &lnrpc.FundingShim_PsbtShim{
   450  			PsbtShim: &lnrpc.PsbtShim{
   451  				PendingChanId: pendingChanID[:],
   452  				BasePsbt:      basePsbtBytes,
   453  				NoPublish:     ctx.Bool("no_publish"),
   454  			},
   455  		},
   456  	}
   457  
   458  	// Start the interactive process by opening the stream connection to the
   459  	// daemon. If the user cancels by pressing <Ctrl+C> we need to cancel
   460  	// the shim. To not just kill the process on interrupt, we need to
   461  	// explicitly capture the signal.
   462  	stream, err := client.OpenChannel(ctxc, req)
   463  	if err != nil {
   464  		return fmt.Errorf("opening stream to server failed: %v", err)
   465  	}
   466  
   467  	// We also need to spawn a goroutine that reads from the server. This
   468  	// will copy the messages to the channel as long as they come in or add
   469  	// exactly one error to the error stream and then bail out.
   470  	go func() {
   471  		for {
   472  			// Recv blocks until a message or error arrives.
   473  			resp, err := stream.Recv()
   474  			if err == io.EOF {
   475  				srvErr <- fmt.Errorf("lnd shutting down: %v",
   476  					err)
   477  				return
   478  			} else if err != nil {
   479  				srvErr <- fmt.Errorf("got error from server: "+
   480  					"%v", err)
   481  				return
   482  			}
   483  
   484  			// Don't block on sending in case of shutting down.
   485  			select {
   486  			case srvMsg <- resp:
   487  			case <-quit:
   488  				return
   489  			}
   490  		}
   491  	}()
   492  
   493  	// Spawn another goroutine that only handles abort from user or errors
   494  	// from the server. Both will trigger an attempt to cancel the shim with
   495  	// the server.
   496  	go func() {
   497  		select {
   498  		case <-rpcCtx.Done():
   499  			fmt.Printf("\nInterrupt signal received.\n")
   500  			close(quit)
   501  
   502  		case err := <-srvErr:
   503  			fmt.Printf("\nError received: %v\n", err)
   504  
   505  			// If the remote peer canceled on us, the reservation
   506  			// has already been deleted. We don't need to try to
   507  			// remove it again, this would just produce another
   508  			// error.
   509  			cancelErr := chanfunding.ErrRemoteCanceled.Error()
   510  			if err != nil && strings.Contains(err.Error(), cancelErr) {
   511  				shimPending = false
   512  			}
   513  			close(quit)
   514  
   515  		case <-quit:
   516  		}
   517  	}()
   518  
   519  	// Our main event loop where we wait for triggers
   520  	for {
   521  		var srvResponse *lnrpc.OpenStatusUpdate
   522  		select {
   523  		case srvResponse = <-srvMsg:
   524  		case <-quit:
   525  			return nil
   526  		}
   527  
   528  		switch update := srvResponse.Update.(type) {
   529  		case *lnrpc.OpenStatusUpdate_PsbtFund:
   530  			// First tell the user how to create the PSBT with the
   531  			// address and amount we now know.
   532  			amt := dcrutil.Amount(update.PsbtFund.FundingAmount)
   533  			addr := update.PsbtFund.FundingAddress
   534  			fmt.Printf(
   535  				userMsgFund, req.NodePubkey, amt, amt, addr,
   536  				addr, amt.ToCoin(),
   537  				base64.StdEncoding.EncodeToString(
   538  					update.PsbtFund.Psbt,
   539  				),
   540  			)
   541  
   542  			// Read the user's response and send it to the server to
   543  			// verify everything's correct before anything is
   544  			// signed.
   545  			psbtBase64, err := readTerminalOrFile(quit)
   546  			if err == io.EOF {
   547  				return nil
   548  			}
   549  			if err != nil {
   550  				return fmt.Errorf("reading from terminal or "+
   551  					"file failed: %v", err)
   552  			}
   553  			fundedPsbt, err := base64.StdEncoding.DecodeString(
   554  				strings.TrimSpace(psbtBase64),
   555  			)
   556  			if err != nil {
   557  				return fmt.Errorf("base64 decode failed: %v",
   558  					err)
   559  			}
   560  			verifyMsg := &lnrpc.FundingTransitionMsg{
   561  				Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{
   562  					PsbtVerify: &lnrpc.FundingPsbtVerify{
   563  						FundedPsbt:    fundedPsbt,
   564  						PendingChanId: pendingChanID[:],
   565  					},
   566  				},
   567  			}
   568  			err = sendFundingState(ctxc, ctx, verifyMsg)
   569  			if err != nil {
   570  				return fmt.Errorf("verifying PSBT by lnd "+
   571  					"failed: %v", err)
   572  			}
   573  
   574  			// Now that we know the PSBT looks good, we can let it
   575  			// be signed by the user.
   576  			fmt.Print(userMsgSign)
   577  
   578  			// Read the signed PSBT and send it to lnd.
   579  			finalTxStr, err := readTerminalOrFile(quit)
   580  			if err == io.EOF {
   581  				return nil
   582  			}
   583  			if err != nil {
   584  				return fmt.Errorf("reading from terminal or "+
   585  					"file failed: %v", err)
   586  			}
   587  			finalizeMsg, err := finalizeMsgFromString(
   588  				finalTxStr, pendingChanID[:],
   589  			)
   590  			if err != nil {
   591  				return err
   592  			}
   593  			transitionMsg := &lnrpc.FundingTransitionMsg{
   594  				Trigger: finalizeMsg,
   595  			}
   596  			err = sendFundingState(ctxc, ctx, transitionMsg)
   597  			if err != nil {
   598  				return fmt.Errorf("finalizing PSBT funding "+
   599  					"flow failed: %v", err)
   600  			}
   601  
   602  		case *lnrpc.OpenStatusUpdate_ChanPending:
   603  			// As soon as the channel is pending, there is no more
   604  			// shim that needs to be canceled. If the user
   605  			// interrupts now, we don't need to clean up anything.
   606  			shimPending = false
   607  
   608  			err := printChanPending(update)
   609  			if err != nil {
   610  				return err
   611  			}
   612  
   613  			if !ctx.Bool("block") {
   614  				return nil
   615  			}
   616  
   617  		case *lnrpc.OpenStatusUpdate_ChanOpen:
   618  			return printChanOpen(update)
   619  		}
   620  	}
   621  }
   622  
   623  var batchOpenChannelCommand = cli.Command{
   624  	Name:     "batchopenchannel",
   625  	Category: "Channels",
   626  	Usage: "Open multiple channels to existing peers in a single " +
   627  		"transaction.",
   628  	Description: `
   629  	Attempt to open one or more new channels to an existing peer with the
   630  	given node-keys.
   631  
   632  	Example:
   633  	lncli batchopenchannel --sat_per_vbyte=5 '[{
   634  		"node_pubkey": "02abcdef...",
   635  		"local_funding_amount": 500000,
   636  		"private": true,
   637  		"close_address": "bc1qxxx..."
   638  	}, {
   639  		"node_pubkey": "03fedcba...",
   640  		"local_funding_amount": 200000,
   641  		"remote_csv_delay": 288
   642  	}]'
   643  
   644  	All nodes listed must already be connected peers, otherwise funding will
   645  	fail.
   646  
   647  	The channel will be initialized with local-amt satoshis local and
   648  	push-amt satoshis for the remote node. Note that specifying push-amt
   649  	means you give that amount to the remote node as part of the channel
   650  	opening. Once the channel is open, a channelPoint (txid:vout) of the
   651  	funding output is returned.
   652  
   653  	If the remote peer supports the option upfront shutdown feature bit
   654  	(query listpeers to see their supported feature bits), an address to
   655  	enforce	payout of funds on cooperative close can optionally be provided.
   656  	Note that if you set this value, you will not be able to cooperatively
   657  	close out to another address.
   658  
   659  	One can manually set the fee to be used for the funding transaction via
   660  	either the --conf_target or --sat_per_vbyte arguments. This is optional.
   661  `,
   662  	ArgsUsage: "channels-json",
   663  	Flags: []cli.Flag{
   664  		cli.Int64Flag{
   665  			Name: "conf_target",
   666  			Usage: "(optional) the number of blocks that the " +
   667  				"transaction *should* confirm in, will be " +
   668  				"used for fee estimation",
   669  		},
   670  		cli.Int64Flag{
   671  			Name: "sat_per_vbyte",
   672  			Usage: "(optional) a manual fee expressed in " +
   673  				"sat/vByte that should be used when crafting " +
   674  				"the transaction",
   675  		},
   676  		cli.Uint64Flag{
   677  			Name: "min_confs",
   678  			Usage: "(optional) the minimum number of " +
   679  				"confirmations each one of your outputs used " +
   680  				"for the funding transaction must satisfy",
   681  			Value: defaultUtxoMinConf,
   682  		},
   683  		cli.StringFlag{
   684  			Name: "label",
   685  			Usage: "(optional) a label to attach to the batch " +
   686  				"transaction when storing it to the local " +
   687  				"wallet after publishing it",
   688  		},
   689  	},
   690  	Action: actionDecorator(batchOpenChannel),
   691  }
   692  
   693  type batchChannelJSON struct {
   694  	NodePubkey         string `json:"node_pubkey,omitempty"`
   695  	LocalFundingAmount int64  `json:"local_funding_amount,omitempty"`
   696  	PushAtoms          int64  `json:"push_sat,omitempty"`
   697  	Private            bool   `json:"private,omitempty"`
   698  	MinHtlcMAtoms      int64  `json:"min_htlc_msat,omitempty"`
   699  	RemoteCsvDelay     uint32 `json:"remote_csv_delay,omitempty"`
   700  	CloseAddress       string `json:"close_address,omitempty"`
   701  	PendingChanID      string `json:"pending_chan_id,omitempty"`
   702  }
   703  
   704  func batchOpenChannel(ctx *cli.Context) error {
   705  	ctxc := getContext()
   706  	client, cleanUp := getClient(ctx)
   707  	defer cleanUp()
   708  
   709  	args := ctx.Args()
   710  
   711  	// Show command help if no arguments provided
   712  	if ctx.NArg() == 0 {
   713  		_ = cli.ShowCommandHelp(ctx, "batchopenchannel")
   714  		return nil
   715  	}
   716  
   717  	minConfs := int32(ctx.Uint64("min_confs"))
   718  	req := &lnrpc.BatchOpenChannelRequest{
   719  		TargetConf:       int32(ctx.Int64("conf_target")),
   720  		AtomsPerByte:     int64(ctx.Uint64("sat_per_vbyte")),
   721  		MinConfs:         minConfs,
   722  		SpendUnconfirmed: minConfs == 0,
   723  		Label:            ctx.String("label"),
   724  	}
   725  
   726  	// Let's try and parse the JSON part of the CLI now. Fortunately we can
   727  	// parse it directly into the RPC struct if we use the correct
   728  	// marshaler that keeps the original snake case.
   729  	var jsonChannels []*batchChannelJSON
   730  	if err := json.Unmarshal([]byte(args.First()), &jsonChannels); err != nil {
   731  		return fmt.Errorf("error parsing channels JSON: %v", err)
   732  	}
   733  
   734  	req.Channels = make([]*lnrpc.BatchOpenChannel, len(jsonChannels))
   735  	for idx, jsonChannel := range jsonChannels {
   736  		pubKeyBytes, err := hex.DecodeString(jsonChannel.NodePubkey)
   737  		if err != nil {
   738  			return fmt.Errorf("error parsing node pubkey hex: %v",
   739  				err)
   740  		}
   741  		pendingChanBytes, err := hex.DecodeString(
   742  			jsonChannel.PendingChanID,
   743  		)
   744  		if err != nil {
   745  			return fmt.Errorf("error parsing pending chan ID: %v",
   746  				err)
   747  		}
   748  
   749  		req.Channels[idx] = &lnrpc.BatchOpenChannel{
   750  			NodePubkey:         pubKeyBytes,
   751  			LocalFundingAmount: jsonChannel.LocalFundingAmount,
   752  			PushAtoms:          jsonChannel.PushAtoms,
   753  			Private:            jsonChannel.Private,
   754  			MinHtlcMAtoms:      jsonChannel.MinHtlcMAtoms,
   755  			RemoteCsvDelay:     jsonChannel.RemoteCsvDelay,
   756  			CloseAddress:       jsonChannel.CloseAddress,
   757  			PendingChanId:      pendingChanBytes,
   758  		}
   759  	}
   760  
   761  	resp, err := client.BatchOpenChannel(ctxc, req)
   762  	if err != nil {
   763  		return err
   764  	}
   765  
   766  	for _, pending := range resp.PendingChannels {
   767  		txid, err := chainhash.NewHash(pending.Txid)
   768  		if err != nil {
   769  			return err
   770  		}
   771  
   772  		printJSON(struct {
   773  			FundingTxid        string `json:"funding_txid"`
   774  			FundingOutputIndex uint32 `json:"funding_output_index"`
   775  		}{
   776  			FundingTxid:        txid.String(),
   777  			FundingOutputIndex: pending.OutputIndex,
   778  		})
   779  	}
   780  
   781  	return nil
   782  }
   783  
   784  // printChanOpen prints the channel point of the channel open message.
   785  func printChanOpen(update *lnrpc.OpenStatusUpdate_ChanOpen) error {
   786  	channelPoint := update.ChanOpen.ChannelPoint
   787  
   788  	// A channel point's funding txid can be get/set as a
   789  	// byte slice or a string. In the case it is a string,
   790  	// decode it.
   791  	var txidHash []byte
   792  	switch channelPoint.GetFundingTxid().(type) {
   793  	case *lnrpc.ChannelPoint_FundingTxidBytes:
   794  		txidHash = channelPoint.GetFundingTxidBytes()
   795  	case *lnrpc.ChannelPoint_FundingTxidStr:
   796  		s := channelPoint.GetFundingTxidStr()
   797  		h, err := chainhash.NewHashFromStr(s)
   798  		if err != nil {
   799  			return err
   800  		}
   801  
   802  		txidHash = h[:]
   803  	}
   804  
   805  	txid, err := chainhash.NewHash(txidHash)
   806  	if err != nil {
   807  		return err
   808  	}
   809  
   810  	index := channelPoint.OutputIndex
   811  	printJSON(struct {
   812  		ChannelPoint string `json:"channel_point"`
   813  	}{
   814  		ChannelPoint: fmt.Sprintf("%v:%v", txid, index),
   815  	})
   816  	return nil
   817  }
   818  
   819  // printChanPending prints the funding transaction ID of the channel pending
   820  // message.
   821  func printChanPending(update *lnrpc.OpenStatusUpdate_ChanPending) error {
   822  	txid, err := chainhash.NewHash(update.ChanPending.Txid)
   823  	if err != nil {
   824  		return err
   825  	}
   826  
   827  	printJSON(struct {
   828  		FundingTxid string `json:"funding_txid"`
   829  	}{
   830  		FundingTxid: txid.String(),
   831  	})
   832  	return nil
   833  }
   834  
   835  // readTerminalOrFile reads a single line from the terminal. If the line read is
   836  // short enough to be a file and a file with that exact name exists, the content
   837  // of that file is read and returned as a string. If the content is longer or no
   838  // file exists, the string read from the terminal is returned directly. This
   839  // function can be used to circumvent the N_TTY_BUF_SIZE kernel parameter that
   840  // prevents pasting more than 4096 characters (on most systems) into a terminal.
   841  func readTerminalOrFile(quit chan struct{}) (string, error) {
   842  	maybeFile, err := readLine(quit)
   843  	if err != nil {
   844  		return "", err
   845  	}
   846  
   847  	// Absolute file paths normally can't be longer than 255 characters so
   848  	// we don't even check if it's a file in that case.
   849  	if len(maybeFile) > 255 {
   850  		return maybeFile, nil
   851  	}
   852  
   853  	// It might be a file since the length is small enough. Calling os.Stat
   854  	// should be safe with any arbitrary input as it will only query info
   855  	// about the file, not open or execute it directly.
   856  	stat, err := os.Stat(maybeFile)
   857  
   858  	// The file doesn't exist, we must assume this wasn't a file path after
   859  	// all.
   860  	if err != nil && os.IsNotExist(err) {
   861  		return maybeFile, nil
   862  	}
   863  
   864  	// Some other error, perhaps access denied or something similar, let's
   865  	// surface that to the user.
   866  	if err != nil {
   867  		return "", err
   868  	}
   869  
   870  	// Make sure we don't read a huge file by accident which might lead to
   871  	// undesired side effects. Even very large PSBTs should still only be a
   872  	// few hundred kilobytes so it makes sense to put a cap here.
   873  	if stat.Size() > psbtMaxFileSize {
   874  		return "", fmt.Errorf("error reading file %s: size of %d "+
   875  			"bytes exceeds max PSBT file size of %d", maybeFile,
   876  			stat.Size(), psbtMaxFileSize)
   877  	}
   878  
   879  	// If it's a path to an existing file and it's small enough, let's try
   880  	// to read its content now.
   881  	content, err := ioutil.ReadFile(maybeFile)
   882  	if err != nil {
   883  		return "", err
   884  	}
   885  
   886  	return string(content), nil
   887  }
   888  
   889  // readLine reads a line from standard in but does not block in case of a
   890  // system interrupt like syscall.SIGINT (Ctrl+C).
   891  func readLine(quit chan struct{}) (string, error) { // nolint: unused
   892  	msg := make(chan string, 1)
   893  
   894  	// In a normal console, reading from stdin won't signal EOF when the
   895  	// user presses Ctrl+C. That's why we need to put this in a separate
   896  	// goroutine so it doesn't block.
   897  	go func() {
   898  		for {
   899  			var str string
   900  			_, _ = fmt.Scan(&str)
   901  			msg <- str
   902  			return
   903  		}
   904  	}()
   905  	for {
   906  		select {
   907  		case <-quit:
   908  			return "", io.EOF
   909  
   910  		case str := <-msg:
   911  			return str, nil
   912  		}
   913  	}
   914  }
   915  
   916  // checkPsbtFlags make sure a request to open a channel doesn't set any
   917  // parameters that are incompatible with the PSBT funding flow.
   918  func checkPsbtFlags(req *lnrpc.OpenChannelRequest) error { // nolint: unused
   919  	if req.MinConfs != defaultUtxoMinConf || req.SpendUnconfirmed {
   920  		return fmt.Errorf("specifying minimum confirmations for PSBT " +
   921  			"funding is not supported")
   922  	}
   923  	if req.TargetConf != 0 || req.AtomsPerByte != 0 {
   924  		return fmt.Errorf("setting fee estimation parameters not " +
   925  			"supported for PSBT funding")
   926  	}
   927  	return nil
   928  }
   929  
   930  // sendFundingState sends a single funding state step message by using a new
   931  // client connection. This is necessary if the whole funding flow takes longer
   932  // than the default macaroon timeout, then we cannot use a single client
   933  // connection.
   934  func sendFundingState(cancelCtx context.Context, cliCtx *cli.Context,
   935  	msg *lnrpc.FundingTransitionMsg) error {
   936  
   937  	client, cleanUp := getClient(cliCtx)
   938  	defer cleanUp()
   939  
   940  	_, err := client.FundingStateStep(cancelCtx, msg)
   941  	return err
   942  }
   943  
   944  // finalizeMsgFromString creates the final message for the PsbtFinalize step
   945  // from either a hex encoded raw wire transaction or a base64 encoded PSBT
   946  // packet.
   947  //
   948  // nolint: unused
   949  func finalizeMsgFromString(tx string,
   950  	pendingChanID []byte) (*lnrpc.FundingTransitionMsg_PsbtFinalize, error) {
   951  
   952  	rawTx, err := hex.DecodeString(strings.TrimSpace(tx))
   953  	if err == nil {
   954  		// Hex decoding succeeded so we assume we have a raw wire format
   955  		// transaction. Let's submit that instead of a PSBT packet.
   956  		tx := &wire.MsgTx{}
   957  		err := tx.Deserialize(bytes.NewReader(rawTx))
   958  		if err != nil {
   959  			return nil, fmt.Errorf("deserializing as raw wire "+
   960  				"transaction failed: %v", err)
   961  		}
   962  		return &lnrpc.FundingTransitionMsg_PsbtFinalize{
   963  			PsbtFinalize: &lnrpc.FundingPsbtFinalize{
   964  				FinalRawTx:    rawTx,
   965  				PendingChanId: pendingChanID,
   966  			},
   967  		}, nil
   968  	}
   969  
   970  	// If the string isn't a hex encoded transaction, we assume it must be
   971  	// a base64 encoded PSBT packet.
   972  	psbtBytes, err := base64.StdEncoding.DecodeString(strings.TrimSpace(tx))
   973  	if err != nil {
   974  		return nil, fmt.Errorf("base64 decode failed: %v", err)
   975  	}
   976  	return &lnrpc.FundingTransitionMsg_PsbtFinalize{
   977  		PsbtFinalize: &lnrpc.FundingPsbtFinalize{
   978  			SignedPsbt:    psbtBytes,
   979  			PendingChanId: pendingChanID,
   980  		},
   981  	}, nil
   982  }