rpc+lnwallet: implement new FundingStateStep RPC method
In this commit, we implement the currently defined transition methods for the new `FundingStateStep` method. At this point, we're now able to serve the "responder" of the externally initiated channel funding flow by being able to register and cancel a funding flow according to its expected pending channel ID.
This commit is contained in:
parent
91bd56dbd1
commit
bc176b5aa3
@ -154,15 +154,9 @@ func NewCannedAssembler(chanPoint wire.OutPoint, fundingAmt btcutil.Amount,
|
||||
//
|
||||
// NOTE: This method satisfies the chanfunding.Assembler interface.
|
||||
func (c *CannedAssembler) ProvisionChannel(req *Request) (Intent, error) {
|
||||
switch {
|
||||
// A simple sanity check to ensure the provision request matches the
|
||||
// re-made shim intent.
|
||||
case req.LocalAmt != c.fundingAmt:
|
||||
return nil, fmt.Errorf("intent doesn't match canned assembler")
|
||||
|
||||
// We'll exit out if this field is set as the funding transaction has
|
||||
// already been assembled, so we don't influence coin selection..
|
||||
case req.SubtractFees:
|
||||
if req.SubtractFees {
|
||||
return nil, fmt.Errorf("SubtractFees ignored, funding " +
|
||||
"transaction is frozen")
|
||||
}
|
||||
@ -179,6 +173,14 @@ func (c *CannedAssembler) ProvisionChannel(req *Request) (Intent, error) {
|
||||
intent.remoteFundingAmt = c.fundingAmt
|
||||
}
|
||||
|
||||
// A simple sanity check to ensure the provisioned request matches the
|
||||
// re-made shim intent.
|
||||
if req.LocalAmt+req.RemoteAmt != c.fundingAmt {
|
||||
return nil, fmt.Errorf("intent doesn't match canned "+
|
||||
"assembler: local_amt=%v, remote_amt=%v, funding_amt=%v",
|
||||
req.LocalAmt, req.RemoteAmt, c.fundingAmt)
|
||||
}
|
||||
|
||||
return intent, nil
|
||||
}
|
||||
|
||||
|
@ -450,8 +450,30 @@ func (l *LightningWallet) RegisterFundingIntent(expectedID [32]byte,
|
||||
shimIntent chanfunding.Intent) error {
|
||||
|
||||
l.intentMtx.Lock()
|
||||
defer l.intentMtx.Unlock()
|
||||
|
||||
if _, ok := l.fundingIntents[expectedID]; ok {
|
||||
return fmt.Errorf("pendingChanID(%x) already has intent "+
|
||||
"registered", expectedID[:])
|
||||
}
|
||||
|
||||
l.fundingIntents[expectedID] = shimIntent
|
||||
l.intentMtx.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CancelFundingIntent allows a caller to cancel a previously registered
|
||||
// funding intent. If no intent was found, then an error will be returned.
|
||||
func (l *LightningWallet) CancelFundingIntent(pid [32]byte) error {
|
||||
l.intentMtx.Lock()
|
||||
defer l.intentMtx.Unlock()
|
||||
|
||||
if _, ok := l.fundingIntents[pid]; !ok {
|
||||
return fmt.Errorf("no funding intent found for "+
|
||||
"pendingChannelID(%x)", pid[:])
|
||||
}
|
||||
|
||||
delete(l.fundingIntents, pid)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
66
rpcserver.go
66
rpcserver.go
@ -5814,8 +5814,68 @@ func (r *rpcServer) BakeMacaroon(ctx context.Context,
|
||||
// ID, for which we need to use specific parameters. Alternatively, this can
|
||||
// be used to interactively drive PSBT signing for funding for partially
|
||||
// complete funding transactions.
|
||||
func (r *rpcServer) FundingStateStep(context.Context,
|
||||
*lnrpc.FundingTransitionMsg) (*lnrpc.FundingStateStepResp, error) {
|
||||
func (r *rpcServer) FundingStateStep(ctx context.Context,
|
||||
in *lnrpc.FundingTransitionMsg) (*lnrpc.FundingStateStepResp, error) {
|
||||
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
switch {
|
||||
|
||||
// If this is a message to register a new shim that is an external
|
||||
// channel point, then we'll contact the wallet to register this new
|
||||
// shim. A user will use this method to register a new channel funding
|
||||
// workflow which has already been partially negotiated outside of the
|
||||
// core protocol.
|
||||
case in.GetShimRegister() != nil &&
|
||||
in.GetShimRegister().GetChanPointShim() != nil:
|
||||
|
||||
rpcShimIntent := in.GetShimRegister().GetChanPointShim()
|
||||
|
||||
// Using the rpc shim as a template, we'll construct a new
|
||||
// chanfunding.Assembler that is able to express proper
|
||||
// formulation of this expected channel.
|
||||
shimAssembler, err := newFundingShimAssembler(
|
||||
rpcShimIntent, false, r.server.cc.keyRing,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := &chanfunding.Request{
|
||||
RemoteAmt: btcutil.Amount(rpcShimIntent.Amt),
|
||||
}
|
||||
shimIntent, err := shimAssembler.ProvisionChannel(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Once we have the intent, we'll register it with the wallet.
|
||||
// Once we receive an incoming funding request that uses this
|
||||
// pending channel ID, then this shim will be dispatched in
|
||||
// place of our regular funding workflow.
|
||||
var pendingChanID [32]byte
|
||||
copy(pendingChanID[:], rpcShimIntent.PendingChanId)
|
||||
err = r.server.cc.wallet.RegisterFundingIntent(
|
||||
pendingChanID, shimIntent,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If this is a transition to cancel an existing shim, then we'll pass
|
||||
// this message along to the wallet.
|
||||
case in.GetShimCancel() != nil:
|
||||
pid := in.GetShimCancel().PendingChanId
|
||||
|
||||
var pendingChanID [32]byte
|
||||
copy(pendingChanID[:], pid)
|
||||
|
||||
err := r.server.cc.wallet.CancelFundingIntent(pendingChanID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(roasbeef): extend PendingChannels to also show shims
|
||||
|
||||
// TODO(roasbeef): return resulting state? also add a method to query
|
||||
// current state?
|
||||
return &lnrpc.FundingStateStepResp{}, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user