@@ -18,6 +18,7 @@ import (
1818 "bytes"
1919 "context"
2020 "fmt"
21+ "sync"
2122
2223 "github.com/pkg/errors"
2324
@@ -140,13 +141,16 @@ func (c *Client) ProposeChannel(ctx context.Context, prop ChannelProposal) (*Cha
140141 }
141142
142143 // 2. send proposal, wait for response, create channel object
144+ c .enableVer1Cache () // cache version 1 updates until channel is opened
143145 ch , err := c .proposeTwoPartyChannel (ctx , prop )
144146 if err != nil {
145147 return nil , errors .WithMessage (err , "channel proposal" )
146148 }
147149
148150 // 3. fund
149- return ch , c .fundChannel (ctx , ch , prop )
151+ fundingErr := c .fundChannel (ctx , ch , prop )
152+ c .releaseVer1Cache () // replay cached version 1 updates
153+ return ch , fundingErr
150154}
151155
152156// handleChannelProposal implements the receiving side of the (currently)
@@ -175,11 +179,15 @@ func (c *Client) handleChannelProposalAcc(
175179 return ch , errors .WithMessage (err , "validating channel proposal acceptance" )
176180 }
177181
182+ c .enableVer1Cache () // cache version 1 updates
183+
178184 if ch , err = c .acceptChannelProposal (ctx , prop , p , acc ); err != nil {
179185 return ch , errors .WithMessage (err , "accept channel proposal" )
180186 }
181187
182- return ch , c .fundChannel (ctx , ch , prop )
188+ fundingErr := c .fundChannel (ctx , ch , prop )
189+ c .releaseVer1Cache () // replay cached version 1 updates
190+ return ch , fundingErr
183191}
184192
185193func (c * Client ) acceptChannelProposal (
@@ -549,6 +557,40 @@ func enableVer0Cache(ctx context.Context, c wire.Cacher) {
549557 })
550558}
551559
560+ func (c * Client ) enableVer1Cache () {
561+ c .log .Trace ("Enabling version 1 cache" )
562+
563+ c .version1Cache .mu .Lock ()
564+ defer c .version1Cache .mu .Unlock ()
565+
566+ c .version1Cache .enabled ++
567+ }
568+
569+ func (c * Client ) releaseVer1Cache () {
570+ c .log .Trace ("Releasing version 1 cache" )
571+
572+ c .version1Cache .mu .Lock ()
573+ defer c .version1Cache .mu .Unlock ()
574+
575+ c .version1Cache .enabled --
576+ for _ , u := range c .version1Cache .cache {
577+ go c .handleChannelUpdate (u .uh , u .p , u .m )
578+ }
579+ c .version1Cache .cache = nil
580+ }
581+
582+ type version1Cache struct {
583+ mu sync.Mutex
584+ enabled uint // counter to support concurrent channel openings
585+ cache []cachedUpdate
586+ }
587+
588+ type cachedUpdate struct {
589+ uh UpdateHandler
590+ p wire.Address
591+ m * msgChannelUpdate
592+ }
593+
552594// Error implements the error interface.
553595func (e PeerRejectedProposalError ) Error () string {
554596 return fmt .Sprintf ("channel proposal rejected: %s" , e .reason )
0 commit comments