rpc: refactor request validation and response marshal into functions
This commit is contained in:
parent
9dcaf4fbc6
commit
7616a3dc7f
@ -1,9 +1,14 @@
|
|||||||
package lnrpc
|
package lnrpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
|
fmt "fmt"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -54,3 +59,88 @@ func UnmarshallAmt(amtSat, amtMsat int64) (lnwire.MilliSatoshi, error) {
|
|||||||
|
|
||||||
return lnwire.MilliSatoshi(amtMsat), nil
|
return lnwire.MilliSatoshi(amtMsat), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseConfs validates the minimum and maximum confirmation arguments of a
|
||||||
|
// ListUnspent request.
|
||||||
|
func ParseConfs(min, max int32) (int32, int32, error) {
|
||||||
|
switch {
|
||||||
|
// Ensure that the user didn't attempt to specify a negative number of
|
||||||
|
// confirmations, as that isn't possible.
|
||||||
|
case min < 0:
|
||||||
|
return 0, 0, fmt.Errorf("min confirmations must be >= 0")
|
||||||
|
|
||||||
|
// We'll also ensure that the min number of confs is strictly less than
|
||||||
|
// or equal to the max number of confs for sanity.
|
||||||
|
case min > max:
|
||||||
|
return 0, 0, fmt.Errorf("max confirmations must be >= min " +
|
||||||
|
"confirmations")
|
||||||
|
|
||||||
|
default:
|
||||||
|
return min, max, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalUtxos translates a []*lnwallet.Utxo into a []*lnrpc.Utxo.
|
||||||
|
func MarshalUtxos(utxos []*lnwallet.Utxo, activeNetParams *chaincfg.Params) (
|
||||||
|
[]*Utxo, error) {
|
||||||
|
|
||||||
|
res := make([]*Utxo, 0, len(utxos))
|
||||||
|
for _, utxo := range utxos {
|
||||||
|
// Translate lnwallet address type to the proper gRPC proto
|
||||||
|
// address type.
|
||||||
|
var addrType AddressType
|
||||||
|
switch utxo.AddressType {
|
||||||
|
|
||||||
|
case lnwallet.WitnessPubKey:
|
||||||
|
addrType = AddressType_WITNESS_PUBKEY_HASH
|
||||||
|
|
||||||
|
case lnwallet.NestedWitnessPubKey:
|
||||||
|
addrType = AddressType_NESTED_PUBKEY_HASH
|
||||||
|
|
||||||
|
case lnwallet.UnknownAddressType:
|
||||||
|
continue
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid utxo address type")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we know we have a proper mapping to an address,
|
||||||
|
// we'll convert the regular outpoint to an lnrpc variant.
|
||||||
|
outpoint := &OutPoint{
|
||||||
|
TxidBytes: utxo.OutPoint.Hash[:],
|
||||||
|
TxidStr: utxo.OutPoint.Hash.String(),
|
||||||
|
OutputIndex: utxo.OutPoint.Index,
|
||||||
|
}
|
||||||
|
|
||||||
|
utxoResp := Utxo{
|
||||||
|
AddressType: addrType,
|
||||||
|
AmountSat: int64(utxo.Value),
|
||||||
|
PkScript: hex.EncodeToString(utxo.PkScript),
|
||||||
|
Outpoint: outpoint,
|
||||||
|
Confirmations: utxo.Confirmations,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we'll attempt to extract the raw address from the
|
||||||
|
// script so we can display a human friendly address to the end
|
||||||
|
// user.
|
||||||
|
_, outAddresses, _, err := txscript.ExtractPkScriptAddrs(
|
||||||
|
utxo.PkScript, activeNetParams,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we can't properly locate a single address, then this was
|
||||||
|
// an error in our mapping, and we'll return an error back to
|
||||||
|
// the user.
|
||||||
|
if len(outAddresses) != 1 {
|
||||||
|
return nil, fmt.Errorf("an output was unexpectedly " +
|
||||||
|
"multisig")
|
||||||
|
}
|
||||||
|
utxoResp.Address = outAddresses[0].String()
|
||||||
|
|
||||||
|
res = append(res, &utxoResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
98
rpcserver.go
98
rpcserver.go
@ -924,30 +924,20 @@ func (r *rpcServer) sendCoinsOnChain(paymentMap map[string]int64,
|
|||||||
return &txHash, nil
|
return &txHash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListUnspent returns useful information about each unspent output owned by
|
// ListUnspent returns useful information about each unspent output owned by the
|
||||||
// the wallet, as reported by the underlying `ListUnspentWitness`; the
|
// wallet, as reported by the underlying `ListUnspentWitness`; the information
|
||||||
// information returned is: outpoint, amount in satoshis, address, address
|
// returned is: outpoint, amount in satoshis, address, address type,
|
||||||
// type, scriptPubKey in hex and number of confirmations. The result is
|
// scriptPubKey in hex and number of confirmations. The result is filtered to
|
||||||
// filtered to contain outputs whose number of confirmations is between a
|
// contain outputs whose number of confirmations is between a minimum and
|
||||||
// minimum and maximum number of confirmations specified by the user, with 0
|
// maximum number of confirmations specified by the user, with 0 meaning
|
||||||
// meaning unconfirmed.
|
// unconfirmed.
|
||||||
func (r *rpcServer) ListUnspent(ctx context.Context,
|
func (r *rpcServer) ListUnspent(ctx context.Context,
|
||||||
in *lnrpc.ListUnspentRequest) (*lnrpc.ListUnspentResponse, error) {
|
in *lnrpc.ListUnspentRequest) (*lnrpc.ListUnspentResponse, error) {
|
||||||
|
|
||||||
minConfs := in.MinConfs
|
// Validate the confirmation arguments.
|
||||||
maxConfs := in.MaxConfs
|
minConfs, maxConfs, err := lnrpc.ParseConfs(in.MinConfs, in.MaxConfs)
|
||||||
|
if err != nil {
|
||||||
switch {
|
return nil, err
|
||||||
// Ensure that the user didn't attempt to specify a negative number of
|
|
||||||
// confirmations, as that isn't possible.
|
|
||||||
case minConfs < 0:
|
|
||||||
return nil, fmt.Errorf("min confirmations must be >= 0")
|
|
||||||
|
|
||||||
// We'll also ensure that the min number of confs is strictly less than
|
|
||||||
// or equal to the max number of confs for sanity.
|
|
||||||
case minConfs > maxConfs:
|
|
||||||
return nil, fmt.Errorf("max confirmations must be >= min " +
|
|
||||||
"confirmations")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// With our arguments validated, we'll query the internal wallet for
|
// With our arguments validated, we'll query the internal wallet for
|
||||||
@ -957,71 +947,11 @@ func (r *rpcServer) ListUnspent(ctx context.Context,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := &lnrpc.ListUnspentResponse{
|
rpcUtxos, err := lnrpc.MarshalUtxos(utxos, activeNetParams.Params)
|
||||||
Utxos: make([]*lnrpc.Utxo, 0, len(utxos)),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, utxo := range utxos {
|
|
||||||
// Translate lnwallet address type to the proper gRPC proto
|
|
||||||
// address type.
|
|
||||||
var addrType lnrpc.AddressType
|
|
||||||
switch utxo.AddressType {
|
|
||||||
|
|
||||||
case lnwallet.WitnessPubKey:
|
|
||||||
addrType = lnrpc.AddressType_WITNESS_PUBKEY_HASH
|
|
||||||
|
|
||||||
case lnwallet.NestedWitnessPubKey:
|
|
||||||
addrType = lnrpc.AddressType_NESTED_PUBKEY_HASH
|
|
||||||
|
|
||||||
case lnwallet.UnknownAddressType:
|
|
||||||
rpcsLog.Warnf("[listunspent] utxo with address of "+
|
|
||||||
"unknown type ignored: %v",
|
|
||||||
utxo.OutPoint.String())
|
|
||||||
continue
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("invalid utxo address type")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that we know we have a proper mapping to an address,
|
|
||||||
// we'll convert the regular outpoint to an lnrpc variant.
|
|
||||||
outpoint := &lnrpc.OutPoint{
|
|
||||||
TxidBytes: utxo.OutPoint.Hash[:],
|
|
||||||
TxidStr: utxo.OutPoint.Hash.String(),
|
|
||||||
OutputIndex: utxo.OutPoint.Index,
|
|
||||||
}
|
|
||||||
|
|
||||||
utxoResp := lnrpc.Utxo{
|
|
||||||
AddressType: addrType,
|
|
||||||
AmountSat: int64(utxo.Value),
|
|
||||||
PkScript: hex.EncodeToString(utxo.PkScript),
|
|
||||||
Outpoint: outpoint,
|
|
||||||
Confirmations: utxo.Confirmations,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we'll attempt to extract the raw address from the
|
|
||||||
// script so we can display a human friendly address to the end
|
|
||||||
// user.
|
|
||||||
_, outAddresses, _, err := txscript.ExtractPkScriptAddrs(
|
|
||||||
utxo.PkScript, activeNetParams.Params,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we can't properly locate a single address, then this was
|
|
||||||
// an error in our mapping, and we'll return an error back to
|
|
||||||
// the user.
|
|
||||||
if len(outAddresses) != 1 {
|
|
||||||
return nil, fmt.Errorf("an output was unexpectedly " +
|
|
||||||
"multisig")
|
|
||||||
}
|
|
||||||
|
|
||||||
utxoResp.Address = outAddresses[0].String()
|
|
||||||
|
|
||||||
resp.Utxos = append(resp.Utxos, &utxoResp)
|
|
||||||
}
|
|
||||||
|
|
||||||
maxStr := ""
|
maxStr := ""
|
||||||
if maxConfs != math.MaxInt32 {
|
if maxConfs != math.MaxInt32 {
|
||||||
maxStr = " max=" + fmt.Sprintf("%d", maxConfs)
|
maxStr = " max=" + fmt.Sprintf("%d", maxConfs)
|
||||||
@ -1030,7 +960,9 @@ func (r *rpcServer) ListUnspent(ctx context.Context,
|
|||||||
rpcsLog.Debugf("[listunspent] min=%v%v, generated utxos: %v", minConfs,
|
rpcsLog.Debugf("[listunspent] min=%v%v, generated utxos: %v", minConfs,
|
||||||
maxStr, utxos)
|
maxStr, utxos)
|
||||||
|
|
||||||
return resp, nil
|
return &lnrpc.ListUnspentResponse{
|
||||||
|
Utxos: rpcUtxos,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EstimateFee handles a request for estimating the fee for sending a
|
// EstimateFee handles a request for estimating the fee for sending a
|
||||||
|
Loading…
Reference in New Issue
Block a user