github.com/decred/dcrlnd@v0.7.6/lnrpc/walletrpc/walletkit_server.go (about)

     1  //go:build !no_walletrpc
     2  // +build !no_walletrpc
     3  
     4  package walletrpc
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"errors"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"path/filepath"
    14  	"time"
    15  
    16  	"decred.org/dcrwallet/v4/wallet"
    17  	"github.com/decred/dcrd/blockchain/standalone/v2"
    18  	"github.com/decred/dcrd/chaincfg/chainhash"
    19  	"github.com/decred/dcrd/dcrec"
    20  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    21  	"github.com/decred/dcrd/dcrutil/v4"
    22  	"github.com/decred/dcrd/hdkeychain/v3"
    23  	"github.com/decred/dcrd/txscript/v4"
    24  	"github.com/decred/dcrd/txscript/v4/sign"
    25  	"github.com/decred/dcrd/txscript/v4/stdaddr"
    26  	"github.com/decred/dcrd/wire"
    27  	"github.com/decred/dcrlnd/input"
    28  	"github.com/decred/dcrlnd/internal/psbt"
    29  	"github.com/decred/dcrlnd/keychain"
    30  	"github.com/decred/dcrlnd/labels"
    31  	"github.com/decred/dcrlnd/lnrpc"
    32  	"github.com/decred/dcrlnd/lnrpc/signrpc"
    33  	"github.com/decred/dcrlnd/lnwallet"
    34  	"github.com/decred/dcrlnd/lnwallet/chainfee"
    35  	"github.com/decred/dcrlnd/lnwallet/dcrwallet"
    36  	"github.com/decred/dcrlnd/macaroons"
    37  	"github.com/decred/dcrlnd/sweep"
    38  	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    39  	"google.golang.org/grpc"
    40  	"gopkg.in/macaroon-bakery.v2/bakery"
    41  )
    42  
    43  const (
    44  	// importedAddrsAccountName is the name of the account with imported
    45  	// scripts/pubkeys.
    46  	importedAddrsAccountName = "imported"
    47  )
    48  
    49  var (
    50  	// macaroonOps are the set of capabilities that our minted macaroon (if
    51  	// it doesn't already exist) will have.
    52  	macaroonOps = []bakery.Op{
    53  		{
    54  			Entity: "address",
    55  			Action: "write",
    56  		},
    57  		{
    58  			Entity: "address",
    59  			Action: "read",
    60  		},
    61  		{
    62  			Entity: "onchain",
    63  			Action: "write",
    64  		},
    65  		{
    66  			Entity: "onchain",
    67  			Action: "read",
    68  		},
    69  	}
    70  
    71  	// macPermissions maps RPC calls to the permissions they require.
    72  	macPermissions = map[string][]bakery.Op{
    73  		"/walletrpc.WalletKit/DeriveNextKey": {{
    74  			Entity: "address",
    75  			Action: "read",
    76  		}},
    77  		"/walletrpc.WalletKit/DeriveKey": {{
    78  			Entity: "address",
    79  			Action: "read",
    80  		}},
    81  		"/walletrpc.WalletKit/NextAddr": {{
    82  			Entity: "address",
    83  			Action: "read",
    84  		}},
    85  		"/walletrpc.WalletKit/PublishTransaction": {{
    86  			Entity: "onchain",
    87  			Action: "write",
    88  		}},
    89  		"/walletrpc.WalletKit/SendOutputs": {{
    90  			Entity: "onchain",
    91  			Action: "write",
    92  		}},
    93  		"/walletrpc.WalletKit/EstimateFee": {{
    94  			Entity: "onchain",
    95  			Action: "read",
    96  		}},
    97  		"/walletrpc.WalletKit/PendingSweeps": {{
    98  			Entity: "onchain",
    99  			Action: "read",
   100  		}},
   101  		"/walletrpc.WalletKit/BumpFee": {{
   102  			Entity: "onchain",
   103  			Action: "write",
   104  		}},
   105  		"/walletrpc.WalletKit/ListSweeps": {{
   106  			Entity: "onchain",
   107  			Action: "read",
   108  		}},
   109  		"/walletrpc.WalletKit/DeriveNextAccount": {{
   110  			Entity: "onchain",
   111  			Action: "write",
   112  		}},
   113  		"/walletrpc.WalletKit/ExportPrivateKey": {{
   114  			Entity: "onchain",
   115  			Action: "write",
   116  		}},
   117  		"/walletrpc.WalletKit/RescanWallet": {{
   118  			Entity: "onchain",
   119  			Action: "read",
   120  		}},
   121  		"/walletrpc.WalletKit/SpendUTXOs": {{
   122  			Entity: "onchain",
   123  			Action: "write",
   124  		}},
   125  		"/walletrpc.WalletKit/GetWalletTx": {{
   126  			Entity: "onchain",
   127  			Action: "read",
   128  		}},
   129  		"/walletrpc.WalletKit/LabelTransaction": {{
   130  			Entity: "onchain",
   131  			Action: "write",
   132  		}},
   133  		"/walletrpc.WalletKit/LeaseOutput": {{
   134  			Entity: "onchain",
   135  			Action: "write",
   136  		}},
   137  		"/walletrpc.WalletKit/ReleaseOutput": {{
   138  			Entity: "onchain",
   139  			Action: "write",
   140  		}},
   141  		"/walletrpc.WalletKit/ListLeases": {{
   142  			Entity: "onchain",
   143  			Action: "read",
   144  		}},
   145  		"/walletrpc.WalletKit/ListUnspent": {{
   146  			Entity: "onchain",
   147  			Action: "read",
   148  		}},
   149  		"/walletrpc.WalletKit/FundPsbt": {{
   150  			Entity: "onchain",
   151  			Action: "write",
   152  		}},
   153  		"/walletrpc.WalletKit/SignPsbt": {{
   154  			Entity: "onchain",
   155  			Action: "write",
   156  		}},
   157  		"/walletrpc.WalletKit/FinalizePsbt": {{
   158  			Entity: "onchain",
   159  			Action: "write",
   160  		}},
   161  		"/walletrpc.WalletKit/ListAccounts": {{
   162  			Entity: "onchain",
   163  			Action: "read",
   164  		}},
   165  		"/walletrpc.WalletKit/ImportAccount": {{
   166  			Entity: "onchain",
   167  			Action: "write",
   168  		}},
   169  		"/walletrpc.WalletKit/ImportPublicKey": {{
   170  			Entity: "onchain",
   171  			Action: "write",
   172  		}},
   173  	}
   174  
   175  	// DefaultWalletKitMacFilename is the default name of the wallet kit
   176  	// macaroon that we expect to find via a file handle within the main
   177  	// configuration file in this package.
   178  	DefaultWalletKitMacFilename = "walletkit.macaroon"
   179  
   180  	// LndInternalLockID is the binary representation of the SHA256 hash of
   181  	// the string "lnd-internal-lock-id" and is used for UTXO lock leases to
   182  	// identify that we ourselves are locking an UTXO, for example when
   183  	// giving out a funded PSBT. The ID corresponds to the hex value of
   184  	// ede19a92ed321a4705f8a1cccc1d4f6182545d4bb4fae08bd5937831b7e38f98.
   185  	LndInternalLockID = lnwallet.LockID{
   186  		0xed, 0xe1, 0x9a, 0x92, 0xed, 0x32, 0x1a, 0x47,
   187  		0x05, 0xf8, 0xa1, 0xcc, 0xcc, 0x1d, 0x4f, 0x61,
   188  		0x82, 0x54, 0x5d, 0x4b, 0xb4, 0xfa, 0xe0, 0x8b,
   189  		0xd5, 0x93, 0x78, 0x31, 0xb7, 0xe3, 0x8f, 0x98,
   190  	}
   191  )
   192  
   193  // ErrZeroLabel is returned when an attempt is made to label a transaction with
   194  // an empty label.
   195  var ErrZeroLabel = errors.New("cannot label transaction with empty label")
   196  
   197  // ServerShell is a shell struct holding a reference to the actual sub-server.
   198  // It is used to register the gRPC sub-server with the root server before we
   199  // have the necessary dependencies to populate the actual sub-server.
   200  type ServerShell struct {
   201  	WalletKitServer
   202  }
   203  
   204  // WalletKit is a sub-RPC server that exposes a tool kit which allows clients
   205  // to execute common wallet operations. This includes requesting new addresses,
   206  // keys (for contracts!), and publishing transactions.
   207  type WalletKit struct {
   208  	cfg *Config
   209  }
   210  
   211  // A compile time check to ensure that WalletKit fully implements the
   212  // WalletKitServer gRPC service.
   213  var _ WalletKitServer = (*WalletKit)(nil)
   214  
   215  // New creates a new instance of the WalletKit sub-RPC server.
   216  func New(cfg *Config) (*WalletKit, lnrpc.MacaroonPerms, error) {
   217  	// If the path of the wallet kit macaroon wasn't specified, then we'll
   218  	// assume that it's found at the default network directory.
   219  	if cfg.WalletKitMacPath == "" {
   220  		cfg.WalletKitMacPath = filepath.Join(
   221  			cfg.NetworkDir, DefaultWalletKitMacFilename,
   222  		)
   223  	}
   224  
   225  	// Now that we know the full path of the wallet kit macaroon, we can
   226  	// check to see if we need to create it or not. If stateless_init is set
   227  	// then we don't write the macaroons.
   228  	macFilePath := cfg.WalletKitMacPath
   229  	if cfg.MacService != nil && !cfg.MacService.StatelessInit &&
   230  		!lnrpc.FileExists(macFilePath) {
   231  
   232  		log.Infof("Baking macaroons for WalletKit RPC Server at: %v",
   233  			macFilePath)
   234  
   235  		// At this point, we know that the wallet kit macaroon doesn't
   236  		// yet, exist, so we need to create it with the help of the
   237  		// main macaroon service.
   238  		walletKitMac, err := cfg.MacService.NewMacaroon(
   239  			context.Background(), macaroons.DefaultRootKeyID,
   240  			macaroonOps...,
   241  		)
   242  		if err != nil {
   243  			return nil, nil, err
   244  		}
   245  		walletKitMacBytes, err := walletKitMac.M().MarshalBinary()
   246  		if err != nil {
   247  			return nil, nil, err
   248  		}
   249  		err = ioutil.WriteFile(macFilePath, walletKitMacBytes, 0644)
   250  		if err != nil {
   251  			_ = os.Remove(macFilePath)
   252  			return nil, nil, err
   253  		}
   254  	}
   255  
   256  	walletKit := &WalletKit{
   257  		cfg: cfg,
   258  	}
   259  
   260  	return walletKit, macPermissions, nil
   261  }
   262  
   263  // Start launches any helper goroutines required for the sub-server to function.
   264  //
   265  // NOTE: This is part of the lnrpc.SubServer interface.
   266  func (w *WalletKit) Start() error {
   267  	return nil
   268  }
   269  
   270  // Stop signals any active goroutines for a graceful closure.
   271  //
   272  // NOTE: This is part of the lnrpc.SubServer interface.
   273  func (w *WalletKit) Stop() error {
   274  	return nil
   275  }
   276  
   277  // Name returns a unique string representation of the sub-server. This can be
   278  // used to identify the sub-server and also de-duplicate them.
   279  //
   280  // NOTE: This is part of the lnrpc.SubServer interface.
   281  func (w *WalletKit) Name() string {
   282  	return SubServerName
   283  }
   284  
   285  // RegisterWithRootServer will be called by the root gRPC server to direct a
   286  // sub RPC server to register itself with the main gRPC root server. Until this
   287  // is called, each sub-server won't be able to have requests routed towards it.
   288  //
   289  // NOTE: This is part of the lnrpc.GrpcHandler interface.
   290  func (r *ServerShell) RegisterWithRootServer(grpcServer *grpc.Server) error {
   291  	// We make sure that we register it with the main gRPC server to ensure
   292  	// all our methods are routed properly.
   293  	RegisterWalletKitServer(grpcServer, r)
   294  
   295  	log.Debugf("WalletKit RPC server successfully registered with " +
   296  		"root gRPC server")
   297  
   298  	return nil
   299  }
   300  
   301  // RegisterWithRestServer will be called by the root REST mux to direct a sub
   302  // RPC server to register itself with the main REST mux server. Until this is
   303  // called, each sub-server won't be able to have requests routed towards it.
   304  //
   305  // NOTE: This is part of the lnrpc.GrpcHandler interface.
   306  func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
   307  	mux *runtime.ServeMux, dest string, opts []grpc.DialOption) error {
   308  
   309  	// We make sure that we register it with the main REST server to ensure
   310  	// all our methods are routed properly.
   311  	err := RegisterWalletKitHandlerFromEndpoint(ctx, mux, dest, opts)
   312  	if err != nil {
   313  		log.Errorf("Could not register WalletKit REST server "+
   314  			"with root REST server: %v", err)
   315  		return err
   316  	}
   317  
   318  	log.Debugf("WalletKit REST server successfully registered with " +
   319  		"root REST server")
   320  	return nil
   321  }
   322  
   323  // CreateSubServer populates the subserver's dependencies using the passed
   324  // SubServerConfigDispatcher. This method should fully initialize the
   325  // sub-server instance, making it ready for action. It returns the macaroon
   326  // permissions that the sub-server wishes to pass on to the root server for all
   327  // methods routed towards it.
   328  //
   329  // NOTE: This is part of the lnrpc.GrpcHandler interface.
   330  func (r *ServerShell) CreateSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
   331  	lnrpc.SubServer, lnrpc.MacaroonPerms, error) {
   332  
   333  	subServer, macPermissions, err := createNewSubServer(configRegistry)
   334  	if err != nil {
   335  		return nil, nil, err
   336  	}
   337  
   338  	r.WalletKitServer = subServer
   339  	return subServer, macPermissions, nil
   340  }
   341  
   342  // ListUnspent returns useful information about each unspent output owned by the
   343  // wallet, as reported by the underlying `ListUnspentWitness`; the information
   344  // returned is: outpoint, amount in satoshis, address, address type,
   345  // scriptPubKey in hex and number of confirmations.  The result is filtered to
   346  // contain outputs whose number of confirmations is between a
   347  // minimum and maximum number of confirmations specified by the user, with 0
   348  // meaning unconfirmed.
   349  func (w *WalletKit) ListUnspent(ctx context.Context,
   350  	req *ListUnspentRequest) (*ListUnspentResponse, error) {
   351  
   352  	// Validate the confirmation arguments.
   353  	minConfs, maxConfs, err := lnrpc.ParseConfs(req.MinConfs, req.MaxConfs)
   354  	if err != nil {
   355  		return nil, err
   356  	}
   357  
   358  	// With our arguments validated, we'll query the internal wallet for
   359  	// the set of UTXOs that match our query.
   360  	//
   361  	// We'll acquire the global coin selection lock to ensure there aren't
   362  	// any other concurrent processes attempting to lock any UTXOs which may
   363  	// be shown available to us.
   364  	var utxos []*lnwallet.Utxo
   365  	err = w.cfg.CoinSelectionLocker.WithCoinSelectLock(func() error {
   366  		utxos, err = w.cfg.Wallet.ListUnspentWitness(
   367  			minConfs, maxConfs, req.Account,
   368  		)
   369  		return err
   370  	})
   371  	if err != nil {
   372  		return nil, err
   373  	}
   374  
   375  	rpcUtxos, err := lnrpc.MarshalUtxos(utxos, w.cfg.ChainParams)
   376  	if err != nil {
   377  		return nil, err
   378  	}
   379  
   380  	return &ListUnspentResponse{
   381  		Utxos: rpcUtxos,
   382  	}, nil
   383  }
   384  
   385  // LeaseOutput locks an output to the given ID, preventing it from being
   386  // available for any future coin selection attempts. The absolute time of the
   387  // lock's expiration is returned. The expiration of the lock can be extended by
   388  // successive invocations of this call. Outputs can be unlocked before their
   389  // expiration through `ReleaseOutput`.
   390  //
   391  // If the output is not known, wtxmgr.ErrUnknownOutput is returned. If the
   392  // output has already been locked to a different ID, then
   393  // wtxmgr.ErrOutputAlreadyLocked is returned.
   394  func (w *WalletKit) LeaseOutput(ctx context.Context,
   395  	req *LeaseOutputRequest) (*LeaseOutputResponse, error) {
   396  
   397  	if len(req.Id) != 32 {
   398  		return nil, errors.New("id must be 32 random bytes")
   399  	}
   400  	var lockID lnwallet.LockID
   401  	copy(lockID[:], req.Id)
   402  
   403  	// Don't allow ID's of 32 bytes, but all zeros.
   404  	if lockID == (lnwallet.LockID{}) {
   405  		return nil, errors.New("id must be 32 random bytes")
   406  	}
   407  
   408  	// Don't allow our internal ID to be used externally for locking. Only
   409  	// unlocking is allowed.
   410  	if lockID == LndInternalLockID {
   411  		return nil, errors.New("reserved id cannot be used")
   412  	}
   413  
   414  	op, err := unmarshallOutPoint(req.Outpoint)
   415  	if err != nil {
   416  		return nil, err
   417  	}
   418  
   419  	// Use the specified lock duration or fall back to the default.
   420  	duration := DefaultLockDuration
   421  	if req.ExpirationSeconds != 0 {
   422  		duration = time.Duration(req.ExpirationSeconds) * time.Second
   423  	}
   424  
   425  	// Acquire the global coin selection lock to ensure there aren't any
   426  	// other concurrent processes attempting to lease the same UTXO.
   427  	var expiration time.Time
   428  	err = w.cfg.CoinSelectionLocker.WithCoinSelectLock(func() error {
   429  		expiration, err = w.cfg.Wallet.LeaseOutput(
   430  			lockID, *op, duration,
   431  		)
   432  		return err
   433  	})
   434  	if err != nil {
   435  		return nil, err
   436  	}
   437  
   438  	return &LeaseOutputResponse{
   439  		Expiration: uint64(expiration.Unix()),
   440  	}, nil
   441  }
   442  
   443  // ReleaseOutput unlocks an output, allowing it to be available for coin
   444  // selection if it remains unspent. The ID should match the one used to
   445  // originally lock the output.
   446  func (w *WalletKit) ReleaseOutput(ctx context.Context,
   447  	req *ReleaseOutputRequest) (*ReleaseOutputResponse, error) {
   448  
   449  	if len(req.Id) != 32 {
   450  		return nil, errors.New("id must be 32 random bytes")
   451  	}
   452  	var lockID lnwallet.LockID
   453  	copy(lockID[:], req.Id)
   454  
   455  	op, err := unmarshallOutPoint(req.Outpoint)
   456  	if err != nil {
   457  		return nil, err
   458  	}
   459  
   460  	// Acquire the global coin selection lock to maintain consistency as
   461  	// it's acquired when we initially leased the output.
   462  	err = w.cfg.CoinSelectionLocker.WithCoinSelectLock(func() error {
   463  		return w.cfg.Wallet.ReleaseOutput(lockID, *op)
   464  	})
   465  	if err != nil {
   466  		return nil, err
   467  	}
   468  
   469  	return &ReleaseOutputResponse{}, nil
   470  }
   471  
   472  // ListLeases returns a list of all currently locked utxos.
   473  func (w *WalletKit) ListLeases(ctx context.Context,
   474  	req *ListLeasesRequest) (*ListLeasesResponse, error) {
   475  
   476  	leases, err := w.cfg.Wallet.ListLeasedOutputs()
   477  	if err != nil {
   478  		return nil, err
   479  	}
   480  
   481  	return &ListLeasesResponse{
   482  		LockedUtxos: marshallLeases(leases),
   483  	}, nil
   484  }
   485  
   486  // DeriveNextKey attempts to derive the *next* key within the key family
   487  // (account in BIP43) specified. This method should return the next external
   488  // child within this branch.
   489  func (w *WalletKit) DeriveNextKey(ctx context.Context,
   490  	req *KeyReq) (*signrpc.KeyDescriptor, error) {
   491  
   492  	nextKeyDesc, err := w.cfg.KeyRing.DeriveNextKey(
   493  		keychain.KeyFamily(req.KeyFamily),
   494  	)
   495  	if err != nil {
   496  		return nil, err
   497  	}
   498  
   499  	return &signrpc.KeyDescriptor{
   500  		KeyLoc: &signrpc.KeyLocator{
   501  			KeyFamily: int32(nextKeyDesc.Family),
   502  			KeyIndex:  int32(nextKeyDesc.Index),
   503  		},
   504  		RawKeyBytes: nextKeyDesc.PubKey.SerializeCompressed(),
   505  	}, nil
   506  }
   507  
   508  // DeriveKey attempts to derive an arbitrary key specified by the passed
   509  // KeyLocator.
   510  func (w *WalletKit) DeriveKey(ctx context.Context,
   511  	req *signrpc.KeyLocator) (*signrpc.KeyDescriptor, error) {
   512  
   513  	keyDesc, err := w.cfg.KeyRing.DeriveKey(keychain.KeyLocator{
   514  		Family: keychain.KeyFamily(req.KeyFamily),
   515  		Index:  uint32(req.KeyIndex),
   516  	})
   517  	if err != nil {
   518  		return nil, err
   519  	}
   520  
   521  	return &signrpc.KeyDescriptor{
   522  		KeyLoc: &signrpc.KeyLocator{
   523  			KeyFamily: int32(keyDesc.Family),
   524  			KeyIndex:  int32(keyDesc.Index),
   525  		},
   526  		RawKeyBytes: keyDesc.PubKey.SerializeCompressed(),
   527  	}, nil
   528  }
   529  
   530  // NextAddr returns the next unused address within the wallet.
   531  func (w *WalletKit) NextAddr(ctx context.Context,
   532  	req *AddrRequest) (*AddrResponse, error) {
   533  
   534  	account := lnwallet.DefaultAccountName
   535  	if req.Account != "" {
   536  		account = req.Account
   537  	}
   538  
   539  	addrType := lnwallet.PubKeyHash
   540  	if req.Type != AddressType_UNKNOWN {
   541  		return nil, fmt.Errorf("only the default address type (0) is supported")
   542  	}
   543  
   544  	addr, err := w.cfg.Wallet.NewAddress(addrType, req.Change, account)
   545  	if err != nil {
   546  		return nil, err
   547  	}
   548  
   549  	return &AddrResponse{
   550  		Addr: addr.String(),
   551  	}, nil
   552  }
   553  
   554  // Attempts to publish the passed transaction to the network. Once this returns
   555  // without an error, the wallet will continually attempt to re-broadcast the
   556  // transaction on start up, until it enters the chain.
   557  func (w *WalletKit) PublishTransaction(ctx context.Context,
   558  	req *Transaction) (*PublishResponse, error) {
   559  
   560  	switch {
   561  	// If the client doesn't specify a transaction, then there's nothing to
   562  	// publish.
   563  	case len(req.TxHex) == 0:
   564  		return nil, fmt.Errorf("must provide a transaction to " +
   565  			"publish")
   566  	}
   567  
   568  	tx := &wire.MsgTx{}
   569  	txReader := bytes.NewReader(req.TxHex)
   570  	if err := tx.Deserialize(txReader); err != nil {
   571  		return nil, err
   572  	}
   573  
   574  	label, err := labels.ValidateAPI(req.Label)
   575  	if err != nil {
   576  		return nil, err
   577  	}
   578  
   579  	err = w.cfg.Wallet.PublishTransaction(tx, label)
   580  	if err != nil {
   581  		return nil, err
   582  	}
   583  
   584  	return &PublishResponse{}, nil
   585  }
   586  
   587  // SendOutputs is similar to the existing sendmany call in Bitcoind, and allows
   588  // the caller to create a transaction that sends to several outputs at once.
   589  // This is ideal when wanting to batch create a set of transactions.
   590  func (w *WalletKit) SendOutputs(ctx context.Context,
   591  	req *SendOutputsRequest) (*SendOutputsResponse, error) {
   592  
   593  	switch {
   594  	// If the client didn't specify any outputs to create, then  we can't
   595  	// proceed .
   596  	case len(req.Outputs) == 0:
   597  		return nil, fmt.Errorf("must specify at least one output " +
   598  			"to create")
   599  	}
   600  
   601  	// Before we can request this transaction to be created, we'll need to
   602  	// amp the protos back into the format that the internal wallet will
   603  	// recognize.
   604  	outputsToCreate := make([]*wire.TxOut, 0, len(req.Outputs))
   605  	for _, output := range req.Outputs {
   606  		outputsToCreate = append(outputsToCreate, &wire.TxOut{
   607  			Value:    output.Value,
   608  			PkScript: output.PkScript,
   609  		})
   610  	}
   611  
   612  	// Then, we'll extract the minimum number of confirmations that each
   613  	// output we use to fund the transaction should satisfy.
   614  	minConfs, err := lnrpc.ExtractMinConfs(req.MinConfs, req.SpendUnconfirmed)
   615  	if err != nil {
   616  		return nil, err
   617  	}
   618  
   619  	label, err := labels.ValidateAPI(req.Label)
   620  	if err != nil {
   621  		return nil, err
   622  	}
   623  
   624  	// Now that we have the outputs mapped, we can request that the wallet
   625  	// attempt to create this transaction.
   626  	tx, err := w.cfg.Wallet.SendOutputs(
   627  		outputsToCreate, chainfee.AtomPerKByte(req.AtomsPerKb), minConfs, label,
   628  		req.Account,
   629  	)
   630  	if err != nil {
   631  		return nil, err
   632  	}
   633  
   634  	var b bytes.Buffer
   635  	if err := tx.Serialize(&b); err != nil {
   636  		return nil, err
   637  	}
   638  
   639  	return &SendOutputsResponse{
   640  		RawTx: b.Bytes(),
   641  	}, nil
   642  }
   643  
   644  // EstimateFee attempts to query the internal fee estimator of the wallet to
   645  // determine the fee (in atom/kB) to attach to a transaction in order to achieve
   646  // the confirmation target.
   647  func (w *WalletKit) EstimateFee(ctx context.Context,
   648  	req *EstimateFeeRequest) (*EstimateFeeResponse, error) {
   649  
   650  	switch {
   651  	// A confirmation target of zero doesn't make any sense. Similarly, we
   652  	// reject confirmation targets of 1 as they're unreasonable.
   653  	case req.ConfTarget == 0 || req.ConfTarget == 1:
   654  		return nil, fmt.Errorf("confirmation target must be greater " +
   655  			"than 1")
   656  	}
   657  
   658  	atPerKB, err := w.cfg.FeeEstimator.EstimateFeePerKB(
   659  		uint32(req.ConfTarget),
   660  	)
   661  	if err != nil {
   662  		return nil, err
   663  	}
   664  
   665  	return &EstimateFeeResponse{
   666  		AtomsPerKb: int64(atPerKB),
   667  	}, nil
   668  }
   669  
   670  // PendingSweeps returns lists of on-chain outputs that lnd is currently
   671  // attempting to sweep within its central batching engine. Outputs with similar
   672  // fee rates are batched together in order to sweep them within a single
   673  // transaction. The fee rate of each sweeping transaction is determined by
   674  // taking the average fee rate of all the outputs it's trying to sweep.
   675  func (w *WalletKit) PendingSweeps(ctx context.Context,
   676  	in *PendingSweepsRequest) (*PendingSweepsResponse, error) {
   677  
   678  	// Retrieve all of the outputs the UtxoSweeper is currently trying to
   679  	// sweep.
   680  	pendingInputs, err := w.cfg.Sweeper.PendingInputs()
   681  	if err != nil {
   682  		return nil, err
   683  	}
   684  
   685  	// Convert them into their respective RPC format.
   686  	rpcPendingSweeps := make([]*PendingSweep, 0, len(pendingInputs))
   687  	for _, pendingInput := range pendingInputs {
   688  		var witnessType WitnessType
   689  		switch pendingInput.WitnessType {
   690  		case input.CommitmentTimeLock:
   691  			witnessType = WitnessType_COMMITMENT_TIME_LOCK
   692  		case input.CommitmentNoDelay:
   693  			witnessType = WitnessType_COMMITMENT_NO_DELAY
   694  		case input.CommitmentRevoke:
   695  			witnessType = WitnessType_COMMITMENT_REVOKE
   696  		case input.HtlcOfferedRevoke:
   697  			witnessType = WitnessType_HTLC_OFFERED_REVOKE
   698  		case input.HtlcAcceptedRevoke:
   699  			witnessType = WitnessType_HTLC_ACCEPTED_REVOKE
   700  		case input.HtlcOfferedTimeoutSecondLevel:
   701  			witnessType = WitnessType_HTLC_OFFERED_TIMEOUT_SECOND_LEVEL
   702  		case input.HtlcAcceptedSuccessSecondLevel:
   703  			witnessType = WitnessType_HTLC_ACCEPTED_SUCCESS_SECOND_LEVEL
   704  		case input.HtlcOfferedRemoteTimeout:
   705  			witnessType = WitnessType_HTLC_OFFERED_REMOTE_TIMEOUT
   706  		case input.HtlcAcceptedRemoteSuccess:
   707  			witnessType = WitnessType_HTLC_ACCEPTED_REMOTE_SUCCESS
   708  		case input.HtlcSecondLevelRevoke:
   709  			witnessType = WitnessType_HTLC_SECOND_LEVEL_REVOKE
   710  		case input.WitnessKeyHash:
   711  			witnessType = WitnessType_WITNESS_KEY_HASH
   712  		case input.NestedWitnessKeyHash:
   713  			witnessType = WitnessType_NESTED_WITNESS_KEY_HASH
   714  		case input.CommitmentAnchor:
   715  			witnessType = WitnessType_COMMITMENT_ANCHOR
   716  
   717  		// Decred-specific.
   718  		case input.PublicKeyHash:
   719  			witnessType = WitnessType_PUBKEY_HASH
   720  		default:
   721  			log.Warnf("Unhandled witness type %v for input %v",
   722  				pendingInput.WitnessType, pendingInput.OutPoint)
   723  		}
   724  
   725  		op := &lnrpc.OutPoint{
   726  			TxidBytes:   pendingInput.OutPoint.Hash[:],
   727  			OutputIndex: pendingInput.OutPoint.Index,
   728  		}
   729  		amountAtoms := uint32(pendingInput.Amount)
   730  		atomsPerByte := uint32(pendingInput.LastFeeRate / 1000)
   731  		broadcastAttempts := uint32(pendingInput.BroadcastAttempts)
   732  		nextBroadcastHeight := pendingInput.NextBroadcastHeight
   733  
   734  		requestedFee := pendingInput.Params.Fee
   735  		requestedFeeRate := uint32(requestedFee.FeeRate / 1000)
   736  
   737  		rpcPendingSweeps = append(rpcPendingSweeps, &PendingSweep{
   738  			Outpoint:              op,
   739  			WitnessType:           witnessType,
   740  			AmountAtoms:           amountAtoms,
   741  			AtomsPerByte:          atomsPerByte,
   742  			BroadcastAttempts:     broadcastAttempts,
   743  			NextBroadcastHeight:   nextBroadcastHeight,
   744  			RequestedAtomsPerByte: requestedFeeRate,
   745  			RequestedConfTarget:   requestedFee.ConfTarget,
   746  			Force:                 pendingInput.Params.Force,
   747  		})
   748  	}
   749  
   750  	return &PendingSweepsResponse{
   751  		PendingSweeps: rpcPendingSweeps,
   752  	}, nil
   753  }
   754  
   755  // unmarshallOutPoint converts an outpoint from its lnrpc type to its canonical
   756  // type.
   757  func unmarshallOutPoint(op *lnrpc.OutPoint) (*wire.OutPoint, error) {
   758  	if op == nil {
   759  		return nil, fmt.Errorf("empty outpoint provided")
   760  	}
   761  
   762  	var hash chainhash.Hash
   763  	switch {
   764  	case len(op.TxidBytes) == 0 && len(op.TxidStr) == 0:
   765  		fallthrough
   766  
   767  	case len(op.TxidBytes) != 0 && len(op.TxidStr) != 0:
   768  		return nil, fmt.Errorf("either TxidBytes or TxidStr must be " +
   769  			"specified, but not both")
   770  
   771  	// The hash was provided as raw bytes.
   772  	case len(op.TxidBytes) != 0:
   773  		copy(hash[:], op.TxidBytes)
   774  
   775  	// The hash was provided as a hex-encoded string.
   776  	case len(op.TxidStr) != 0:
   777  		h, err := chainhash.NewHashFromStr(op.TxidStr)
   778  		if err != nil {
   779  			return nil, err
   780  		}
   781  		hash = *h
   782  	}
   783  
   784  	return &wire.OutPoint{
   785  		Hash:  hash,
   786  		Index: op.OutputIndex,
   787  	}, nil
   788  }
   789  
   790  // BumpFee allows bumping the fee rate of an arbitrary input. A fee preference
   791  // can be expressed either as a specific fee rate or a delta of blocks in which
   792  // the output should be swept on-chain within. If a fee preference is not
   793  // explicitly specified, then an error is returned. The status of the input
   794  // sweep can be checked through the PendingSweeps RPC.
   795  func (w *WalletKit) BumpFee(ctx context.Context,
   796  	in *BumpFeeRequest) (*BumpFeeResponse, error) {
   797  
   798  	// Parse the outpoint from the request.
   799  	op, err := unmarshallOutPoint(in.Outpoint)
   800  	if err != nil {
   801  		return nil, err
   802  	}
   803  
   804  	// Construct the request's fee preference.
   805  	atomsPerKB := chainfee.AtomPerKByte(in.AtomsPerByte * 1000)
   806  	feePreference := sweep.FeePreference{
   807  		ConfTarget: in.TargetConf,
   808  		FeeRate:    atomsPerKB,
   809  	}
   810  
   811  	// We'll attempt to bump the fee of the input through the UtxoSweeper.
   812  	// If it is currently attempting to sweep the input, then it'll simply
   813  	// bump its fee, which will result in a replacement transaction (RBF)
   814  	// being broadcast. If it is not aware of the input however,
   815  	// lnwallet.ErrNotMine is returned.
   816  	params := sweep.ParamsUpdate{
   817  		Fee:   feePreference,
   818  		Force: in.Force,
   819  	}
   820  
   821  	_, err = w.cfg.Sweeper.UpdateParams(*op, params)
   822  	switch err {
   823  	case nil:
   824  		return &BumpFeeResponse{}, nil
   825  	case lnwallet.ErrNotMine:
   826  		break
   827  	default:
   828  		return nil, err
   829  	}
   830  
   831  	log.Debugf("Attempting to CPFP outpoint %s", op)
   832  
   833  	// Since we're unable to perform a bump through RBF, we'll assume the
   834  	// user is attempting to bump an unconfirmed transaction's fee rate by
   835  	// sweeping an output within it under control of the wallet with a
   836  	// higher fee rate, essentially performing a Child-Pays-For-Parent
   837  	// (CPFP).
   838  	//
   839  	// We'll gather all of the information required by the UtxoSweeper in
   840  	// order to sweep the output.
   841  	utxo, err := w.cfg.Wallet.FetchInputInfo(op)
   842  	if err != nil {
   843  		return nil, err
   844  	}
   845  
   846  	// We're only able to bump the fee of unconfirmed transactions.
   847  	if utxo.Confirmations > 0 {
   848  		return nil, errors.New("unable to bump fee of a confirmed " +
   849  			"transaction")
   850  	}
   851  
   852  	var witnessType input.WitnessType
   853  	switch utxo.AddressType {
   854  	case lnwallet.PubKeyHash:
   855  		witnessType = input.PublicKeyHash
   856  	default:
   857  		return nil, fmt.Errorf("unknown input witness %v", op)
   858  	}
   859  
   860  	signDesc := &input.SignDescriptor{
   861  		Output: &wire.TxOut{
   862  			PkScript: utxo.PkScript,
   863  			Value:    int64(utxo.Value),
   864  		},
   865  		HashType: txscript.SigHashAll,
   866  	}
   867  
   868  	// We'll use the current height as the height hint since we're dealing
   869  	// with an unconfirmed transaction.
   870  	_, currentHeight, err := w.cfg.Chain.GetBestBlock()
   871  	if err != nil {
   872  		return nil, fmt.Errorf("unable to retrieve current height: %v",
   873  			err)
   874  	}
   875  
   876  	input := input.NewBaseInput(op, witnessType, signDesc, uint32(currentHeight))
   877  	if _, err = w.cfg.Sweeper.SweepInput(input, sweep.Params{Fee: feePreference}); err != nil {
   878  		return nil, err
   879  	}
   880  
   881  	return &BumpFeeResponse{}, nil
   882  }
   883  
   884  // ListSweeps returns a list of the sweeps that our node has published.
   885  func (w *WalletKit) ListSweeps(ctx context.Context,
   886  	in *ListSweepsRequest) (*ListSweepsResponse, error) {
   887  
   888  	sweeps, err := w.cfg.Sweeper.ListSweeps()
   889  	if err != nil {
   890  		return nil, err
   891  	}
   892  
   893  	sweepTxns := make(map[string]bool)
   894  	for _, sweep := range sweeps {
   895  		sweepTxns[sweep.String()] = true
   896  	}
   897  
   898  	// Some of our sweeps could have been replaced by fee, or dropped out
   899  	// of the mempool. Here, we lookup our wallet transactions so that we
   900  	// can match our list of sweeps against the list of transactions that
   901  	// the wallet is still tracking.
   902  	transactions, err := w.cfg.Wallet.ListTransactionDetails(
   903  		0, dcrwallet.UnconfirmedHeight, lnwallet.DefaultAccountName,
   904  	)
   905  	if err != nil {
   906  		return nil, err
   907  	}
   908  
   909  	var (
   910  		txids     []string
   911  		txDetails []*lnwallet.TransactionDetail
   912  	)
   913  
   914  	for _, tx := range transactions {
   915  		_, ok := sweepTxns[tx.Hash.String()]
   916  		if !ok {
   917  			continue
   918  		}
   919  
   920  		// Add the txid or full tx details depending on whether we want
   921  		// verbose output or not.
   922  		if in.Verbose {
   923  			txDetails = append(txDetails, tx)
   924  		} else {
   925  			txids = append(txids, tx.Hash.String())
   926  		}
   927  	}
   928  
   929  	if in.Verbose {
   930  		return &ListSweepsResponse{
   931  			Sweeps: &ListSweepsResponse_TransactionDetails{
   932  				TransactionDetails: lnrpc.RPCTransactionDetails(
   933  					txDetails,
   934  				),
   935  			},
   936  		}, nil
   937  	}
   938  
   939  	return &ListSweepsResponse{
   940  		Sweeps: &ListSweepsResponse_TransactionIds{
   941  			TransactionIds: &ListSweepsResponse_TransactionIDs{
   942  				TransactionIds: txids,
   943  			},
   944  		},
   945  	}, nil
   946  }
   947  
   948  func (w *WalletKit) extendedWallet() (lnwallet.ExtendedWalletController, error) {
   949  	if ewc, ok := w.cfg.Wallet.(lnwallet.ExtendedWalletController); ok {
   950  		return ewc, nil
   951  	}
   952  
   953  	if lnw, ok := w.cfg.Wallet.(*lnwallet.LightningWallet); ok {
   954  		if ewc, ok := lnw.WalletController.(lnwallet.ExtendedWalletController); ok {
   955  			return ewc, nil
   956  		}
   957  	}
   958  
   959  	return nil, fmt.Errorf("underlying WalletController %T not an ExtendedWalletController",
   960  		w.cfg.Wallet)
   961  }
   962  
   963  // DeriveNextAccount generates the next account of the wallet.
   964  func (w *WalletKit) DeriveNextAccount(_ context.Context, req *DeriveNextAccountRequest) (*DeriveNextAccountResponse, error) {
   965  	ewc, err := w.extendedWallet()
   966  	if err != nil {
   967  		return nil, err
   968  	}
   969  	return &DeriveNextAccountResponse{}, ewc.DeriveNextAccount(req.Name)
   970  }
   971  
   972  // ExportPrivateKey exports a private key that is derived from a wallet address.
   973  func (w *WalletKit) ExportPrivateKey(_ context.Context, req *ExportPrivateKeyRequest) (*ExportPrivateKeyResponse, error) {
   974  	ewc, err := w.extendedWallet()
   975  	if err != nil {
   976  		return nil, err
   977  	}
   978  	addr, err := stdaddr.DecodeAddress(req.Address, w.cfg.ChainParams)
   979  	if err != nil {
   980  		return nil, err
   981  	}
   982  	pk, err := ewc.ExportPrivKey(addr)
   983  	if err != nil {
   984  		return nil, err
   985  	}
   986  	wif, err := dcrutil.NewWIF(pk.Serialize(), w.cfg.ChainParams.PrivateKeyID,
   987  		dcrec.STEcdsaSecp256k1)
   988  	if err != nil {
   989  		return nil, err
   990  	}
   991  	res := &ExportPrivateKeyResponse{
   992  		Wif: wif.String(),
   993  	}
   994  	return res, nil
   995  }
   996  
   997  func (w *WalletKit) RescanWallet(req *RescanWalletRequest,
   998  	server WalletKit_RescanWalletServer) error {
   999  
  1000  	progressFunc := func(scannedThrough int32) error {
  1001  		return server.Send(&RescanWalletResponse{ScannedThroughHeight: scannedThrough})
  1002  	}
  1003  	ewc, err := w.extendedWallet()
  1004  	if err != nil {
  1005  		return err
  1006  	}
  1007  	return ewc.RescanWallet(req.BeginHeight, progressFunc)
  1008  }
  1009  
  1010  // SpendUTXOs performs a custom on-chain spend of UTXOs.
  1011  func (w *WalletKit) SpendUTXOs(ctx context.Context, req *SpendUTXOsRequest) (*SpendUTXOsResponse, error) {
  1012  
  1013  	// An empty sigScript, to help in sizing the tx for fee determination.
  1014  	pseudoSigScript := make([]byte, input.P2PKHSigScriptSize)
  1015  
  1016  	type sigPK struct {
  1017  		Version  uint16
  1018  		PKScript []byte
  1019  		PrivKey  []byte
  1020  	}
  1021  	sigPKs := make([]sigPK, 0, len(req.Utxos))
  1022  
  1023  	// Build the tx.
  1024  	var totalIn, totalOut int64
  1025  	tx := wire.NewMsgTx()
  1026  	for _, utxo := range req.Utxos {
  1027  		wif, err := dcrutil.DecodeWIF(utxo.PrivateKeyWif, w.cfg.ChainParams.PrivateKeyID)
  1028  		if err != nil {
  1029  			return nil, fmt.Errorf("%s is not a valid wif: %s",
  1030  				utxo.PrivateKeyWif, err)
  1031  		}
  1032  
  1033  		txid, err := chainhash.NewHash(utxo.Txid)
  1034  		if err != nil {
  1035  			return nil, fmt.Errorf("%x is not a chainhash.Hash: %v",
  1036  				utxo.Txid, err)
  1037  		}
  1038  		outp := &wire.OutPoint{Hash: *txid, Index: utxo.Index, Tree: int8(utxo.Tree)}
  1039  
  1040  		addr, err := stdaddr.DecodeAddress(utxo.Address, w.cfg.ChainParams)
  1041  		if err != nil {
  1042  			return nil, fmt.Errorf("utxo address %s is not a stdaddr: %v",
  1043  				utxo.Address, err)
  1044  		}
  1045  
  1046  		_, script := addr.PaymentScript()
  1047  
  1048  		txout, err := w.cfg.Chain.GetUtxo(outp, script, utxo.HeightHint, ctx.Done())
  1049  		if err != nil {
  1050  			return nil, fmt.Errorf("unable to query for utxo %s: %v",
  1051  				outp, err)
  1052  		}
  1053  
  1054  		totalIn += txout.Value
  1055  		txin := wire.NewTxIn(outp, txout.Value, pseudoSigScript)
  1056  		tx.AddTxIn(txin)
  1057  
  1058  		pk := sigPK{PKScript: script, PrivKey: wif.PrivKey(), Version: txout.Version}
  1059  		sigPKs = append(sigPKs, pk)
  1060  	}
  1061  
  1062  	for _, out := range req.Outputs {
  1063  		addr, err := stdaddr.DecodeAddress(out.Address, w.cfg.ChainParams)
  1064  		if err != nil {
  1065  			return nil, fmt.Errorf("output address %s is not a stdaddr: %v", out.Address, err)
  1066  		}
  1067  
  1068  		version, script := addr.PaymentScript()
  1069  
  1070  		txout := wire.NewTxOut(out.Amount, script)
  1071  		txout.Version = version
  1072  		tx.AddTxOut(txout)
  1073  		totalOut += out.Amount
  1074  	}
  1075  
  1076  	sizeNoChange := int64(tx.SerializeSize())
  1077  	feeRate := w.cfg.FeeEstimator.RelayFeePerKB()
  1078  	feeNoChange := int64(feeRate.FeeForSize(sizeNoChange))
  1079  	dustLimit := int64(lnwallet.DustThresholdForRelayFee(feeRate))
  1080  
  1081  	if totalIn-totalOut < feeNoChange {
  1082  		return nil, fmt.Errorf("total input amount %d cannot be spent to "+
  1083  			"to total output %d and fee %d", totalIn, totalOut, feeNoChange)
  1084  	}
  1085  
  1086  	// If the change (after fees) is > than the dustLimit, create a change
  1087  	// output.
  1088  	if totalIn-totalOut-feeNoChange > dustLimit {
  1089  		// Send change to a wallet address.
  1090  		addr, err := w.cfg.Wallet.NewAddress(lnwallet.PubKeyHash, true, lnwallet.DefaultAccountName)
  1091  		if err != nil {
  1092  			return nil, fmt.Errorf("unable to generate change address: %v", err)
  1093  		}
  1094  		version, script := addr.PaymentScript()
  1095  
  1096  		// Create the txOut with zero amount to recalculate the fee
  1097  		// below.
  1098  		txout := wire.NewTxOut(0, script)
  1099  		txout.Version = version
  1100  		tx.AddTxOut(txout)
  1101  
  1102  		// Recalculate fee.
  1103  		size := int64(tx.SerializeSize())
  1104  		fee := int64(feeRate.FeeForSize(size))
  1105  		changeAmt := totalIn - totalOut - fee
  1106  		if changeAmt < dustLimit {
  1107  			// Adding the change output made change < dust, so
  1108  			// remove the change output and proceed with higher fee.
  1109  			tx.TxOut = tx.TxOut[:len(tx.TxOut)-1]
  1110  		} else {
  1111  			txout.Value = changeAmt
  1112  		}
  1113  	}
  1114  
  1115  	// Sign it.
  1116  	for i := range req.Utxos {
  1117  		sigScript, err := sign.SignatureScript(tx, i, sigPKs[i].PKScript,
  1118  			txscript.SigHashAll, sigPKs[i].PrivKey, dcrec.STEcdsaSecp256k1,
  1119  			true)
  1120  		if err != nil {
  1121  			return nil, fmt.Errorf("unable to sign input %d: %v",
  1122  				i, err)
  1123  		}
  1124  		tx.TxIn[i].SignatureScript = sigScript
  1125  	}
  1126  
  1127  	// Double check tx is valid.
  1128  	err := standalone.CheckTransactionSanity(tx, uint64(w.cfg.ChainParams.MaxTxSize))
  1129  	if err != nil {
  1130  		return nil, fmt.Errorf("signed transaction not sane: %v", err)
  1131  	}
  1132  	for i := range tx.TxIn {
  1133  		vm, err := txscript.NewEngine(
  1134  			sigPKs[i].PKScript, tx, i,
  1135  			input.ScriptVerifyFlags, sigPKs[i].Version, nil,
  1136  		)
  1137  		if err != nil {
  1138  			return nil, fmt.Errorf("unable to create VM to check input %d: %v",
  1139  				i, err)
  1140  		}
  1141  		if err = vm.Execute(); err != nil {
  1142  			return nil, fmt.Errorf("tx input %d failed script execution: %v",
  1143  				i, err)
  1144  		}
  1145  	}
  1146  
  1147  	// Broadcast it
  1148  	err = w.cfg.Wallet.PublishTransaction(tx, "")
  1149  	if err != nil {
  1150  		return nil, fmt.Errorf("unable to publish tx: %v", err)
  1151  	}
  1152  	rawTx, err := tx.Bytes()
  1153  	if err != nil {
  1154  		return nil, err
  1155  	}
  1156  	txId := tx.TxHash()
  1157  	res := &SpendUTXOsResponse{
  1158  		Txid:  txId[:],
  1159  		RawTx: rawTx,
  1160  	}
  1161  	return res, nil
  1162  }
  1163  
  1164  func (w *WalletKit) GetWalletTx(ctx context.Context, req *GetWalletTxRequest) (
  1165  	*GetWalletTxResponse, error) {
  1166  	ewc, err := w.extendedWallet()
  1167  	if err != nil {
  1168  		return nil, err
  1169  	}
  1170  
  1171  	txh, err := chainhash.NewHash(req.Txid)
  1172  	if err != nil {
  1173  		return nil, err
  1174  	}
  1175  
  1176  	tx, err := ewc.GetWalletTransaction(*txh)
  1177  	if err != nil {
  1178  		return nil, err
  1179  	}
  1180  	res := &GetWalletTxResponse{
  1181  		RawTx:         tx.RawTx,
  1182  		Confirmations: tx.Confirmations,
  1183  	}
  1184  	if tx.BlockHash != nil {
  1185  		res.BlockHash = tx.BlockHash[:]
  1186  	}
  1187  	return res, nil
  1188  }
  1189  
  1190  // LabelTransaction adds a label to a transaction.
  1191  func (w *WalletKit) LabelTransaction(ctx context.Context,
  1192  	req *LabelTransactionRequest) (*LabelTransactionResponse, error) {
  1193  
  1194  	// Check that the label provided in non-zero.
  1195  	if len(req.Label) == 0 {
  1196  		return nil, ErrZeroLabel
  1197  	}
  1198  
  1199  	// Validate the length of the non-zero label. We do not need to use the
  1200  	// label returned here, because the original is non-zero so will not
  1201  	// be replaced.
  1202  	if _, err := labels.ValidateAPI(req.Label); err != nil {
  1203  		return nil, err
  1204  	}
  1205  
  1206  	hash, err := chainhash.NewHash(req.Txid)
  1207  	if err != nil {
  1208  		return nil, err
  1209  	}
  1210  
  1211  	err = w.cfg.Wallet.LabelTransaction(*hash, req.Label, req.Overwrite)
  1212  	return &LabelTransactionResponse{}, err
  1213  }
  1214  
  1215  // FundPsbt creates a fully populated PSBT that contains enough inputs to fund
  1216  // the outputs specified in the template. There are two ways of specifying a
  1217  // template: Either by passing in a PSBT with at least one output declared or
  1218  // by passing in a raw TxTemplate message. If there are no inputs specified in
  1219  // the template, coin selection is performed automatically. If the template does
  1220  // contain any inputs, it is assumed that full coin selection happened
  1221  // externally and no additional inputs are added. If the specified inputs aren't
  1222  // enough to fund the outputs with the given fee rate, an error is returned.
  1223  // After either selecting or verifying the inputs, all input UTXOs are locked
  1224  // with an internal app ID.
  1225  //
  1226  // NOTE: If this method returns without an error, it is the caller's
  1227  // responsibility to either spend the locked UTXOs (by finalizing and then
  1228  // publishing the transaction) or to unlock/release the locked UTXOs in case of
  1229  // an error on the caller's side.
  1230  func (w *WalletKit) FundPsbt(_ context.Context,
  1231  	req *FundPsbtRequest) (*FundPsbtResponse, error) {
  1232  
  1233  	var (
  1234  		err           error
  1235  		packet        *psbt.Packet
  1236  		feeAtomsPerKB chainfee.AtomPerKByte
  1237  		locks         []*lnwallet.LockedOutput
  1238  		rawPsbt       bytes.Buffer
  1239  	)
  1240  
  1241  	// There are two ways a user can specify what we call the template (a
  1242  	// list of inputs and outputs to use in the PSBT): Either as a PSBT
  1243  	// packet directly or as a special RPC message. Find out which one the
  1244  	// user wants to use, they are mutually exclusive.
  1245  	switch {
  1246  	// The template is specified as a PSBT. All we have to do is parse it.
  1247  	case req.GetPsbt() != nil:
  1248  		r := bytes.NewReader(req.GetPsbt())
  1249  		packet, err = psbt.NewFromRawBytes(r, false)
  1250  		if err != nil {
  1251  			return nil, fmt.Errorf("could not parse PSBT: %v", err)
  1252  		}
  1253  
  1254  	// The template is specified as a RPC message. We need to create a new
  1255  	// PSBT and copy the RPC information over.
  1256  	case req.GetRaw() != nil:
  1257  		tpl := req.GetRaw()
  1258  
  1259  		txOut := make([]*wire.TxOut, 0, len(tpl.Outputs))
  1260  		for addrStr, amt := range tpl.Outputs {
  1261  			addr, err := stdaddr.DecodeAddress(
  1262  				addrStr, w.cfg.ChainParams,
  1263  			)
  1264  			if err != nil {
  1265  				return nil, fmt.Errorf("error parsing address "+
  1266  					"%s for network %s: %v", addrStr,
  1267  					w.cfg.ChainParams.Name, err)
  1268  			}
  1269  			scriptVersion, pkScript := addr.PaymentScript()
  1270  			txOut = append(txOut, &wire.TxOut{
  1271  				Value:    int64(amt),
  1272  				PkScript: pkScript,
  1273  				Version:  scriptVersion,
  1274  			})
  1275  		}
  1276  
  1277  		txIn := make([]*wire.OutPoint, len(tpl.Inputs))
  1278  		for idx, in := range tpl.Inputs {
  1279  			op, err := unmarshallOutPoint(in)
  1280  			if err != nil {
  1281  				return nil, fmt.Errorf("error parsing "+
  1282  					"outpoint: %v", err)
  1283  			}
  1284  			txIn[idx] = op
  1285  		}
  1286  
  1287  		sequences := make([]uint32, len(txIn))
  1288  		packet, err = psbt.New(txIn, txOut, 2, 0, sequences)
  1289  		if err != nil {
  1290  			return nil, fmt.Errorf("could not create PSBT: %v", err)
  1291  		}
  1292  
  1293  	default:
  1294  		return nil, fmt.Errorf("transaction template missing, need " +
  1295  			"to specify either PSBT or raw TX template")
  1296  	}
  1297  
  1298  	// Determine the desired transaction fee.
  1299  	switch {
  1300  	// Estimate the fee by the target number of blocks to confirmation.
  1301  	case req.GetTargetConf() != 0:
  1302  		targetConf := req.GetTargetConf()
  1303  		if targetConf < 2 {
  1304  			return nil, fmt.Errorf("confirmation target must be " +
  1305  				"greater than 1")
  1306  		}
  1307  
  1308  		feeAtomsPerKB, err = w.cfg.FeeEstimator.EstimateFeePerKB(
  1309  			targetConf,
  1310  		)
  1311  		if err != nil {
  1312  			return nil, fmt.Errorf("could not estimate fee: %v",
  1313  				err)
  1314  		}
  1315  
  1316  	// Convert the fee to sat/kW from the specified sat/vByte.
  1317  	case req.GetAtomsPerByte() != 0:
  1318  		feeAtomsPerKB = chainfee.AtomPerKByte(
  1319  			req.GetAtomsPerByte() * 1000,
  1320  		)
  1321  
  1322  	default:
  1323  		return nil, fmt.Errorf("fee definition missing, need to " +
  1324  			"specify either target_conf or sat_per_vbyte")
  1325  	}
  1326  
  1327  	// Then, we'll extract the minimum number of confirmations that each
  1328  	// output we use to fund the transaction should satisfy.
  1329  	minConfs, err := lnrpc.ExtractMinConfs(
  1330  		req.GetMinConfs(), req.GetSpendUnconfirmed(),
  1331  	)
  1332  	if err != nil {
  1333  		return nil, err
  1334  	}
  1335  
  1336  	// The RPC parsing part is now over. Several of the following operations
  1337  	// require us to hold the global coin selection lock so we do the rest
  1338  	// of the tasks while holding the lock. The result is a list of locked
  1339  	// UTXOs.
  1340  	changeIndex := int32(-1)
  1341  	err = w.cfg.CoinSelectionLocker.WithCoinSelectLock(func() error {
  1342  		// In case the user did specify inputs, we need to make sure
  1343  		// they are known to us, still unspent and not yet locked.
  1344  		if len(packet.UnsignedTx.TxIn) > 0 {
  1345  			// Get a list of all unspent witness outputs.
  1346  			utxos, err := w.cfg.Wallet.ListUnspentWitness(
  1347  				minConfs, defaultMaxConf, req.Account,
  1348  			)
  1349  			if err != nil {
  1350  				return err
  1351  			}
  1352  
  1353  			// Validate all inputs against our known list of UTXOs
  1354  			// now.
  1355  			err = verifyInputsUnspent(packet.UnsignedTx.TxIn, utxos)
  1356  			if err != nil {
  1357  				return err
  1358  			}
  1359  		}
  1360  
  1361  		// We made sure the input from the user is as sane as possible.
  1362  		// We can now ask the wallet to fund the TX. This will not yet
  1363  		// lock any coins but might still change the wallet DB by
  1364  		// generating a new change address.
  1365  		changeIndex, err = w.cfg.Wallet.FundPsbt(
  1366  			packet, minConfs, feeAtomsPerKB, req.Account,
  1367  		)
  1368  		if err != nil {
  1369  			return fmt.Errorf("wallet couldn't fund PSBT: %v", err)
  1370  		}
  1371  
  1372  		// Make sure we can properly serialize the packet. If this goes
  1373  		// wrong then something isn't right with the inputs and we
  1374  		// probably shouldn't try to lock any of them.
  1375  		err = packet.Serialize(&rawPsbt)
  1376  		if err != nil {
  1377  			return fmt.Errorf("error serializing funded PSBT: %v",
  1378  				err)
  1379  		}
  1380  
  1381  		// Now we have obtained a set of coins that can be used to fund
  1382  		// the TX. Let's lock them to be sure they aren't spent by the
  1383  		// time the PSBT is published. This is the action we do here
  1384  		// that could cause an error. Therefore if some of the UTXOs
  1385  		// cannot be locked, the rollback of the other's locks also
  1386  		// happens in this function. If we ever need to do more after
  1387  		// this function, we need to extract the rollback needs to be
  1388  		// extracted into a defer.
  1389  		locks, err = lockInputs(w.cfg.Wallet, packet)
  1390  		if err != nil {
  1391  			return fmt.Errorf("could not lock inputs: %v", err)
  1392  		}
  1393  
  1394  		return nil
  1395  	})
  1396  	if err != nil {
  1397  		return nil, err
  1398  	}
  1399  
  1400  	// Convert the lock leases to the RPC format.
  1401  	rpcLocks := marshallLeases(locks)
  1402  
  1403  	return &FundPsbtResponse{
  1404  		FundedPsbt:        rawPsbt.Bytes(),
  1405  		ChangeOutputIndex: changeIndex,
  1406  		LockedUtxos:       rpcLocks,
  1407  	}, nil
  1408  }
  1409  
  1410  // marshallLeases converts the lock leases to the RPC format.
  1411  func marshallLeases(locks []*lnwallet.LockedOutput) []*UtxoLease {
  1412  	rpcLocks := make([]*UtxoLease, len(locks))
  1413  	for idx, lock := range locks {
  1414  		rpcLocks[idx] = &UtxoLease{
  1415  			Id: lock.LockID[:],
  1416  			Outpoint: &lnrpc.OutPoint{
  1417  				TxidBytes:   lock.Outpoint.Hash[:],
  1418  				TxidStr:     lock.Outpoint.Hash.String(),
  1419  				OutputIndex: lock.Outpoint.Index,
  1420  			},
  1421  			Expiration: uint64(lock.Expiration.Unix()),
  1422  		}
  1423  	}
  1424  
  1425  	return rpcLocks
  1426  }
  1427  
  1428  // SignPsbt expects a partial transaction with all inputs and outputs fully
  1429  // declared and tries to sign all unsigned inputs that have all required fields
  1430  // (UTXO information, BIP32 derivation information, witness or sig scripts)
  1431  // set.
  1432  // If no error is returned, the PSBT is ready to be given to the next signer or
  1433  // to be finalized if lnd was the last signer.
  1434  //
  1435  // NOTE: This RPC only signs inputs (and only those it can sign), it does not
  1436  // perform any other tasks (such as coin selection, UTXO locking or
  1437  // input/output/fee value validation, PSBT finalization). Any input that is
  1438  // incomplete will be skipped.
  1439  func (w *WalletKit) SignPsbt(_ context.Context, req *SignPsbtRequest) (
  1440  	*SignPsbtResponse, error) {
  1441  
  1442  	packet, err := psbt.NewFromRawBytes(
  1443  		bytes.NewReader(req.FundedPsbt), false,
  1444  	)
  1445  	if err != nil {
  1446  		log.Debugf("Error parsing PSBT: %v, raw input: %x", err,
  1447  			req.FundedPsbt)
  1448  		return nil, fmt.Errorf("error parsing PSBT: %v", err)
  1449  	}
  1450  
  1451  	// Let the wallet do the heavy lifting. This will sign all inputs that
  1452  	// we have the UTXO for. If some inputs can't be signed and don't have
  1453  	// witness data attached, they will just be skipped.
  1454  	err = w.cfg.Wallet.SignPsbt(packet)
  1455  	if err != nil {
  1456  		return nil, fmt.Errorf("error signing PSBT: %v", err)
  1457  	}
  1458  
  1459  	// Serialize the signed PSBT in both the packet and wire format.
  1460  	var signedPsbtBytes bytes.Buffer
  1461  	err = packet.Serialize(&signedPsbtBytes)
  1462  	if err != nil {
  1463  		return nil, fmt.Errorf("error serializing PSBT: %v", err)
  1464  	}
  1465  
  1466  	return &SignPsbtResponse{
  1467  		SignedPsbt: signedPsbtBytes.Bytes(),
  1468  	}, nil
  1469  }
  1470  
  1471  // FinalizePsbt expects a partial transaction with all inputs and outputs fully
  1472  // declared and tries to sign all inputs that belong to the wallet. Lnd must be
  1473  // the last signer of the transaction. That means, if there are any unsigned
  1474  // non-witness inputs or inputs without UTXO information attached or inputs
  1475  // without witness data that do not belong to lnd's wallet, this method will
  1476  // fail. If no error is returned, the PSBT is ready to be extracted and the
  1477  // final TX within to be broadcast.
  1478  //
  1479  // NOTE: This method does NOT publish the transaction once finalized. It is the
  1480  // caller's responsibility to either publish the transaction on success or
  1481  // unlock/release any locked UTXOs in case of an error in this method.
  1482  func (w *WalletKit) FinalizePsbt(_ context.Context,
  1483  	req *FinalizePsbtRequest) (*FinalizePsbtResponse, error) {
  1484  
  1485  	// Parse the funded PSBT. No additional checks are required at this
  1486  	// level as the wallet will perform all of them.
  1487  	packet, err := psbt.NewFromRawBytes(
  1488  		bytes.NewReader(req.FundedPsbt), false,
  1489  	)
  1490  	if err != nil {
  1491  		return nil, fmt.Errorf("error parsing PSBT: %v", err)
  1492  	}
  1493  
  1494  	// Let the wallet do the heavy lifting. This will sign all inputs that
  1495  	// we have the UTXO for. If some inputs can't be signed and don't have
  1496  	// witness data attached, this will fail.
  1497  	err = w.cfg.Wallet.FinalizePsbt(packet)
  1498  	if err != nil {
  1499  		return nil, fmt.Errorf("error finalizing PSBT: %v", err)
  1500  	}
  1501  
  1502  	var (
  1503  		finalPsbtBytes bytes.Buffer
  1504  		finalTxBytes   bytes.Buffer
  1505  	)
  1506  
  1507  	// Serialize the finalized PSBT in both the packet and wire format.
  1508  	err = packet.Serialize(&finalPsbtBytes)
  1509  	if err != nil {
  1510  		return nil, fmt.Errorf("error serializing PSBT: %v", err)
  1511  	}
  1512  	finalTx, err := psbt.Extract(packet)
  1513  	if err != nil {
  1514  		return nil, fmt.Errorf("unable to extract final TX: %v", err)
  1515  	}
  1516  	err = finalTx.Serialize(&finalTxBytes)
  1517  	if err != nil {
  1518  		return nil, fmt.Errorf("error serializing final TX: %v", err)
  1519  	}
  1520  
  1521  	return &FinalizePsbtResponse{
  1522  		SignedPsbt: finalPsbtBytes.Bytes(),
  1523  		RawFinalTx: finalTxBytes.Bytes(),
  1524  	}, nil
  1525  }
  1526  
  1527  // marshalWalletAccount converts the properties of an account into its RPC
  1528  // representation.
  1529  func marshalWalletAccount(account *wallet.AccountProperties) (*Account, error) {
  1530  	rpcAccount := &Account{
  1531  		Name:             account.AccountName,
  1532  		ExternalKeyCount: account.LastReturnedExternalIndex + 1,
  1533  		InternalKeyCount: account.LastReturnedInternalIndex + 1,
  1534  		// WatchOnly:        account.IsWatchOnly,
  1535  	}
  1536  
  1537  	return rpcAccount, nil
  1538  }
  1539  
  1540  // ListAccounts retrieves all accounts belonging to the wallet by default. A
  1541  // name and key scope filter can be provided to filter through all of the wallet
  1542  // accounts and return only those matching.
  1543  func (w *WalletKit) ListAccounts(ctx context.Context,
  1544  	req *ListAccountsRequest) (*ListAccountsResponse, error) {
  1545  
  1546  	accounts, err := w.cfg.Wallet.ListAccounts(req.Name)
  1547  	if err != nil {
  1548  		return nil, err
  1549  	}
  1550  
  1551  	rpcAccounts := make([]*Account, 0, len(accounts))
  1552  	for _, account := range accounts {
  1553  		// Don't include the default imported accounts created by the
  1554  		// wallet in the response if they don't have any keys imported.
  1555  		if account.AccountName == importedAddrsAccountName &&
  1556  			account.ImportedKeyCount == 0 {
  1557  			continue
  1558  		}
  1559  
  1560  		rpcAccount, err := marshalWalletAccount(&account)
  1561  		if err != nil {
  1562  			return nil, err
  1563  		}
  1564  		rpcAccounts = append(rpcAccounts, rpcAccount)
  1565  	}
  1566  
  1567  	return &ListAccountsResponse{Accounts: rpcAccounts}, nil
  1568  }
  1569  
  1570  // ImportAccount imports an account backed by an account extended public key.
  1571  func (w *WalletKit) ImportAccount(ctx context.Context,
  1572  	req *ImportAccountRequest) (*ImportAccountResponse, error) {
  1573  
  1574  	accountPubKey, err := hdkeychain.NewKeyFromString(req.ExtendedPublicKey,
  1575  		w.cfg.ChainParams)
  1576  
  1577  	if err != nil {
  1578  		return nil, err
  1579  	}
  1580  
  1581  	accountProps, extAddrs, intAddrs, err := w.cfg.Wallet.ImportAccount(
  1582  		req.Name, accountPubKey, req.DryRun,
  1583  	)
  1584  	if err != nil {
  1585  		return nil, err
  1586  	}
  1587  
  1588  	rpcAccount, err := marshalWalletAccount(accountProps)
  1589  	if err != nil {
  1590  		return nil, err
  1591  	}
  1592  
  1593  	resp := &ImportAccountResponse{Account: rpcAccount}
  1594  	if !req.DryRun {
  1595  		return resp, nil
  1596  	}
  1597  
  1598  	resp.DryRunExternalAddrs = make([]string, len(extAddrs))
  1599  	for i := 0; i < len(extAddrs); i++ {
  1600  		resp.DryRunExternalAddrs[i] = extAddrs[i].String()
  1601  	}
  1602  	resp.DryRunInternalAddrs = make([]string, len(intAddrs))
  1603  	for i := 0; i < len(intAddrs); i++ {
  1604  		resp.DryRunInternalAddrs[i] = intAddrs[i].String()
  1605  	}
  1606  
  1607  	return resp, nil
  1608  }
  1609  
  1610  // ImportPublicKey imports a single derived public key into the wallet.
  1611  func (w *WalletKit) ImportPublicKey(ctx context.Context,
  1612  	req *ImportPublicKeyRequest) (*ImportPublicKeyResponse, error) {
  1613  
  1614  	pubKey, err := secp256k1.ParsePubKey(req.PublicKey)
  1615  	if err != nil {
  1616  		return nil, err
  1617  	}
  1618  	if err := w.cfg.Wallet.ImportPublicKey(pubKey); err != nil {
  1619  		return nil, err
  1620  	}
  1621  
  1622  	return &ImportPublicKeyResponse{}, nil
  1623  }