multi: forward SendCoins call over RPC
This commit is contained in:
8 files changed
+117
-14
No files matched your search
@@ -642,7 +642,8 @@ func (b *BtcWallet) ImportPublicKey(pubKey *btcec.PublicKey,
|
||||
//
|
||||
// This is a part of the WalletController interface.
|
||||
func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
|
||||
feeRate chainfee.SatPerKWeight, minConfs int32, label string) (*wire.MsgTx, error) {
|
||||
feeRate chainfee.SatPerKWeight, minConfs int32,
|
||||
label string) (*wire.MsgTx, error) {
|
||||
|
||||
// Convert our fee rate from sat/kw to sat/kb since it's required by
|
||||
// SendOutputs.
|
||||
@@ -1080,7 +1081,7 @@ func (b *BtcWallet) ListTransactionDetails(startHeight, endHeight int32,
|
||||
// responsibility to lock the inputs before handing them out.
|
||||
//
|
||||
// This is a part of the WalletController interface.
|
||||
func (b *BtcWallet) FundPsbt(packet *psbt.Packet,
|
||||
func (b *BtcWallet) FundPsbt(packet *psbt.Packet, minConfs int32,
|
||||
feeRate chainfee.SatPerKWeight, accountName string) (int32, error) {
|
||||
|
||||
// The fee rate is passed in using units of sat/kw, so we'll convert
|
||||
@@ -1115,7 +1116,7 @@ func (b *BtcWallet) FundPsbt(packet *psbt.Packet,
|
||||
// Let the wallet handle coin selection and/or fee estimation based on
|
||||
// the partial TX information in the packet.
|
||||
return b.wallet.FundPsbt(
|
||||
packet, keyScope, accountNum, feeSatPerKB,
|
||||
packet, keyScope, minConfs, accountNum, feeSatPerKB,
|
||||
b.cfg.CoinSelectionStrategy,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -350,8 +350,8 @@ type WalletController interface {
|
||||
// fee rate, an error is returned. No lock lease is acquired for any of
|
||||
// the selected/validated inputs. It is in the caller's responsibility
|
||||
// to lock the inputs before handing them out.
|
||||
FundPsbt(packet *psbt.Packet, feeRate chainfee.SatPerKWeight,
|
||||
account string) (int32, error)
|
||||
FundPsbt(packet *psbt.Packet, minConfs int32,
|
||||
feeRate chainfee.SatPerKWeight, account string) (int32, error)
|
||||
|
||||
// FinalizePsbt expects a partial transaction with all inputs and
|
||||
// outputs fully declared and tries to sign all inputs that belong to
|
||||
|
||||
@@ -11,16 +11,20 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
"github.com/btcsuite/btcwallet/waddrmgr"
|
||||
btcwallet "github.com/btcsuite/btcwallet/wallet"
|
||||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lncfg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chanfunding"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"google.golang.org/grpc"
|
||||
@@ -139,6 +143,26 @@ func (r *RPCKeyRing) NewAddress(addrType lnwallet.AddressType, change bool,
|
||||
return localAddr, nil
|
||||
}
|
||||
|
||||
// LastUnusedAddress returns the last *unused* address known by the wallet. An
|
||||
// address is unused if it hasn't received any payments. This can be useful in
|
||||
// UIs in order to continually show the "freshest" address without having to
|
||||
// worry about "address inflation" caused by continual refreshing. Similar to
|
||||
// NewAddress it can derive a specified address type, and also optionally a
|
||||
// change address. The account parameter must be non-empty as it determines
|
||||
// which account the address should be generated from.
|
||||
func (r *RPCKeyRing) LastUnusedAddress(lnwallet.AddressType,
|
||||
string) (btcutil.Address, error) {
|
||||
|
||||
// Because the underlying wallet will create a new address if the last
|
||||
// derived address has been used in the meantime, we would need to proxy
|
||||
// that call as well. But since that's deep within the btcwallet code,
|
||||
// we cannot easily proxy it without more refactoring. Since this is an
|
||||
// address type that is probably not widely used we can probably get
|
||||
// away with not supporting it.
|
||||
return nil, fmt.Errorf("unused address types are not supported when " +
|
||||
"remote signing is enabled")
|
||||
}
|
||||
|
||||
// ImportAccount imports an account backed by an account extended public key.
|
||||
// The master key fingerprint denotes the fingerprint of the root key
|
||||
// corresponding to the account public key (also known as the key with
|
||||
@@ -265,6 +289,67 @@ func (r *RPCKeyRing) ImportPublicKey(pubKey *btcec.PublicKey,
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendOutputs funds, signs, and broadcasts a Bitcoin transaction paying out to
|
||||
// the specified outputs. In the case the wallet has insufficient funds, or the
|
||||
// outputs are non-standard, a non-nil error will be returned.
|
||||
//
|
||||
// NOTE: This method requires the global coin selection lock to be held.
|
||||
//
|
||||
// This is a part of the WalletController interface.
|
||||
func (r *RPCKeyRing) SendOutputs(outputs []*wire.TxOut,
|
||||
feeRate chainfee.SatPerKWeight, minConfs int32,
|
||||
label string) (*wire.MsgTx, error) {
|
||||
|
||||
tx, err := r.WalletController.SendOutputs(
|
||||
outputs, feeRate, minConfs, label,
|
||||
)
|
||||
if err != nil && err != btcwallet.ErrTxUnsigned {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil {
|
||||
// This shouldn't happen since our wallet controller is watch-
|
||||
// only and can't sign the TX.
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// We know at this point that we only have inputs from our own wallet.
|
||||
// So we can just compute the input script using the remote signer.
|
||||
signDesc := input.SignDescriptor{
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: txscript.NewTxSigHashes(tx),
|
||||
}
|
||||
for i, txIn := range tx.TxIn {
|
||||
// We can only sign this input if it's ours, so we'll ask the
|
||||
// watch-only wallet if it can map this outpoint into a coin we
|
||||
// own. If not, then we can't continue because our wallet state
|
||||
// is out of sync.
|
||||
info, err := r.coinFromOutPoint(txIn.PreviousOutPoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error looking up utxo: %v", err)
|
||||
}
|
||||
|
||||
// Now that we know the input is ours, we'll populate the
|
||||
// signDesc with the per input unique information.
|
||||
signDesc.Output = &wire.TxOut{
|
||||
Value: info.Value,
|
||||
PkScript: info.PkScript,
|
||||
}
|
||||
signDesc.InputIndex = i
|
||||
|
||||
// Finally, we'll sign the input as is, and populate the input
|
||||
// with the witness and sigScript (if needed).
|
||||
inputScript, err := r.ComputeInputScript(tx, &signDesc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txIn.SignatureScript = inputScript.SigScript
|
||||
txIn.Witness = inputScript.Witness
|
||||
}
|
||||
|
||||
return tx, r.WalletController.PublishTransaction(tx, label)
|
||||
}
|
||||
|
||||
// DeriveNextKey attempts to derive the *next* key within the key family
|
||||
// (account in BIP43) specified. This method should return the next external
|
||||
// child within this branch.
|
||||
@@ -534,6 +619,26 @@ func (r *RPCKeyRing) ComputeInputScript(tx *wire.MsgTx,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// coinFromOutPoint attempts to locate details pertaining to a coin based on
|
||||
// its outpoint. If the coin isn't under the control of the backing watch-only
|
||||
// wallet, then an error is returned.
|
||||
func (r *RPCKeyRing) coinFromOutPoint(op wire.OutPoint) (*chanfunding.Coin,
|
||||
error) {
|
||||
|
||||
inputInfo, err := r.WalletController.FetchInputInfo(&op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &chanfunding.Coin{
|
||||
TxOut: wire.TxOut{
|
||||
Value: int64(inputInfo.Value),
|
||||
PkScript: inputInfo.PkScript,
|
||||
},
|
||||
OutPoint: inputInfo.OutPoint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// toRPCSignReq converts the given raw transaction and sign descriptors into
|
||||
// their corresponding RPC counterparts.
|
||||
func toRPCSignReq(tx *wire.MsgTx,
|
||||
|
||||
Reference in new issue
Block a user