Merge pull request #4455 from cfromknecht/psbt-no-publish

PSBT: add no_publish flag for safe batch channel opens v2
This commit is contained in:
Olaoluwa Osuntokun authored and GitHub committed 2020-07-20 12:04:10 -07:00
commit 14a047ffba
11 files changed
+988 -751

No files matched your search

+15
View File
@@ -135,3 +135,18 @@ type FundingTxAssembler interface {
// transaction for the channel via the intent it returns.
FundingTxAvailable()
}
// ConditionalPublishAssembler is an assembler that can dynamically define if
// the funding transaction should be published after channel negotiations or
// not. Not publishing the transaction is only useful if the particular channel
// the assembler is in charge of is part of a batch of channels. In that case
// it is only safe to wait for all channel negotiations of the batch to complete
// before publishing the batch transaction.
type ConditionalPublishAssembler interface {
Assembler
// ShouldPublishFundingTx is a method of the assembler that signals if
// the funding transaction should be published after the channel
// negotiations are completed with the remote peer.
ShouldPublishFundingTx() bool
}
+19 -12
View File
@@ -387,6 +387,10 @@ type PsbtAssembler struct {
// netParams are the network parameters used to encode the P2WSH funding
// address.
netParams *chaincfg.Params
// shouldPublish specifies if the assembler should publish the
// transaction once the channel funding has completed.
shouldPublish bool
}
// NewPsbtAssembler creates a new CannedAssembler from the material required
@@ -394,12 +398,13 @@ type PsbtAssembler struct {
// be supplied which will be used to add the channel output to instead of
// creating a new one.
func NewPsbtAssembler(fundingAmt btcutil.Amount, basePsbt *psbt.Packet,
netParams *chaincfg.Params) *PsbtAssembler {
netParams *chaincfg.Params, shouldPublish bool) *PsbtAssembler {
return &PsbtAssembler{
fundingAmt: fundingAmt,
basePsbt: basePsbt,
netParams: netParams,
fundingAmt: fundingAmt,
basePsbt: basePsbt,
netParams: netParams,
shouldPublish: shouldPublish,
}
}
@@ -436,16 +441,18 @@ func (p *PsbtAssembler) ProvisionChannel(req *Request) (Intent, error) {
return intent, nil
}
// FundingTxAvailable is an empty method that an assembler can implement to
// signal to callers that its able to provide the funding transaction for the
// channel via the intent it returns.
// ShouldPublishFundingTx is a method of the assembler that signals if the
// funding transaction should be published after the channel negotiations are
// completed with the remote peer.
//
// NOTE: This method is a part of the FundingTxAssembler interface.
func (p *PsbtAssembler) FundingTxAvailable() {}
// NOTE: This method is a part of the ConditionalPublishAssembler interface.
func (p *PsbtAssembler) ShouldPublishFundingTx() bool {
return p.shouldPublish
}
// A compile-time assertion to ensure PsbtAssembler meets the Assembler
// interface.
var _ Assembler = (*PsbtAssembler)(nil)
// A compile-time assertion to ensure PsbtAssembler meets the
// ConditionalPublishAssembler interface.
var _ ConditionalPublishAssembler = (*PsbtAssembler)(nil)
// sumUtxoInputValues tries to extract the sum of all inputs specified in the
// UTXO fields of the PSBT. An error is returned if an input is specified that
+4 -4
View File
@@ -34,7 +34,7 @@ func TestPsbtIntent(t *testing.T) {
// Create a simple assembler and ask it to provision a channel to get
// the funding intent.
a := NewPsbtAssembler(chanCapacity, nil, &params)
a := NewPsbtAssembler(chanCapacity, nil, &params, true)
intent, err := a.ProvisionChannel(&Request{LocalAmt: chanCapacity})
if err != nil {
t.Fatalf("error provisioning channel: %v", err)
@@ -215,7 +215,7 @@ func TestPsbtIntentBasePsbt(t *testing.T) {
// Now as the next step, create a new assembler/intent pair with a base
// PSBT to see that we can add an additional output to it.
a := NewPsbtAssembler(chanCapacity, pendingPsbt, &params)
a := NewPsbtAssembler(chanCapacity, pendingPsbt, &params, true)
intent, err := a.ProvisionChannel(&Request{LocalAmt: chanCapacity})
if err != nil {
t.Fatalf("error provisioning channel: %v", err)
@@ -373,7 +373,7 @@ func TestPsbtVerify(t *testing.T) {
// Create a simple assembler and ask it to provision a channel to get
// the funding intent.
a := NewPsbtAssembler(chanCapacity, nil, &params)
a := NewPsbtAssembler(chanCapacity, nil, &params, true)
intent, err := a.ProvisionChannel(&Request{LocalAmt: chanCapacity})
if err != nil {
t.Fatalf("error provisioning channel: %v", err)
@@ -500,7 +500,7 @@ func TestPsbtFinalize(t *testing.T) {
// Create a simple assembler and ask it to provision a channel to get
// the funding intent.
a := NewPsbtAssembler(chanCapacity, nil, &params)
a := NewPsbtAssembler(chanCapacity, nil, &params, true)
intent, err := a.ProvisionChannel(&Request{LocalAmt: chanCapacity})
if err != nil {
t.Fatalf("error provisioning channel: %v", err)
+15 -1
View File
@@ -287,10 +287,24 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
chanType |= channeldb.SingleFunderBit
}
switch a := fundingAssembler.(type) {
// The first channels of a batch shouldn't publish the batch TX
// to avoid problems if some of the funding flows can't be
// completed. Only the last channel of a batch should publish.
case chanfunding.ConditionalPublishAssembler:
if !a.ShouldPublishFundingTx() {
chanType |= channeldb.NoFundingTxBit
}
// Normal funding flow, the assembler creates a TX from the
// internal wallet.
case chanfunding.FundingTxAssembler:
// Do nothing, a FundingTxAssembler has the transaction.
// If this intent isn't one that's able to provide us with a
// funding transaction, then we'll set the chanType bit to
// signal that we don't have access to one.
if _, ok := fundingAssembler.(chanfunding.FundingTxAssembler); !ok {
default:
chanType |= channeldb.NoFundingTxBit
}