@@ -27,7 +27,7 @@ import (
27
27
"github.com/pkg/errors"
28
28
29
29
"perun.network/go-perun/backend/ethereum/bindings/assetholder"
30
- cherrors "perun.network/go-perun/backend/ethereum/channel/errors "
30
+ "perun.network/go-perun/backend/ethereum/subscription "
31
31
"perun.network/go-perun/backend/ethereum/wallet"
32
32
"perun.network/go-perun/channel"
33
33
"perun.network/go-perun/client"
@@ -184,7 +184,7 @@ func (f *Funder) sendFundingTx(ctx context.Context, request channel.FundingReq,
184
184
// nolint: gocritic
185
185
if bal == nil || bal .Sign () <= 0 {
186
186
f .log .WithFields (log.Fields {"channel" : request .Params .ID (), "idx" : request .Idx }).Debug ("Skipped zero funding." )
187
- } else if alreadyFunded , err := checkFunded (ctx , bal , contract , fundingID ); err != nil {
187
+ } else if alreadyFunded , err := f . checkFunded (ctx , bal , contract , fundingID ); err != nil {
188
188
return nil , errors .WithMessage (err , "checking funded" )
189
189
} else if alreadyFunded {
190
190
f .log .WithFields (log.Fields {"channel" : request .Params .ID (), "idx" : request .Idx }).Debug ("Skipped second funding." )
@@ -210,76 +210,61 @@ func (f *Funder) deposit(ctx context.Context, bal *big.Int, asset Asset, funding
210
210
}
211
211
212
212
// checkFunded returns whether `fundingID` holds at least `amount` funds.
213
- func checkFunded (ctx context.Context , amount * big.Int , asset assetHolder , fundingID [32 ]byte ) (bool , error ) {
214
- iter , err := filterFunds (ctx , asset , fundingID )
213
+ func (f * Funder ) checkFunded (ctx context.Context , amount * big.Int , asset assetHolder , fundingID [32 ]byte ) (bool , error ) {
214
+ deposited := make (chan * subscription.Event , 10 )
215
+ subErr := make (chan error , 1 )
216
+ // Subscribe to events.
217
+ sub , err := f .depositedSub (ctx , asset .contract , fundingID )
215
218
if err != nil {
216
- return false , errors .WithMessagef (err , "filtering old Funding events for asset %d" , asset . assetIndex )
219
+ return false , errors .WithMessage (err , "subscribing to deposited event" )
217
220
}
218
- // nolint:errcheck
219
- defer iter .Close ()
221
+ defer sub .Close ()
222
+ // Read from the sub.
223
+ go func () {
224
+ defer close (deposited )
225
+ subErr <- sub .ReadPast (ctx , deposited )
226
+ }()
220
227
221
228
left := new (big.Int ).Set (amount )
222
- for iter .Next () {
223
- left .Sub (left , iter .Event .Amount )
229
+ for _event := range deposited {
230
+ event := _event .Data .(* assetholder.AssetHolderDeposited )
231
+ left .Sub (left , event .Amount )
224
232
}
225
- return left .Sign () != 1 , errors .Wrap ( iter . Error () , "iterator" )
233
+ return left .Sign () != 1 , errors .WithMessagef ( <- subErr , "filtering old Funding events for asset %d" , asset . assetIndex )
226
234
}
227
235
228
- func filterFunds (ctx context.Context , asset assetHolder , fundingIDs ... [32 ]byte ) (* assetholder.AssetHolderDepositedIterator , error ) {
229
- // Filter
230
- filterOpts := bind.FilterOpts {
231
- Start : uint64 (1 ),
232
- End : nil ,
233
- Context : ctx }
234
- iter , err := asset .FilterDeposited (& filterOpts , fundingIDs )
235
- if err != nil {
236
- err = cherrors .CheckIsChainNotReachableError (err )
237
- return nil , errors .WithMessage (err , "filtering deposited events" )
236
+ func (f * Funder ) depositedSub (ctx context.Context , contract * bind.BoundContract , fundingIDs ... [32 ]byte ) (* subscription.EventSub , error ) {
237
+ filter := make ([]interface {}, len (fundingIDs ))
238
+ for i , fundingID := range fundingIDs {
239
+ filter [i ] = fundingID
238
240
}
239
-
240
- return iter , nil
241
+ event := func () * subscription.Event {
242
+ return & subscription.Event {
243
+ Name : "Deposited" ,
244
+ Data : new (assetholder.AssetHolderDeposited ),
245
+ Filter : [][]interface {}{filter },
246
+ }
247
+ }
248
+ sub , err := subscription .NewEventSub (ctx , f , contract , event , startBlockOffset )
249
+ return sub , errors .WithMessage (err , "subscribing to deposited event" )
241
250
}
242
251
243
252
// waitForFundingConfirmation waits for the confirmation events on the blockchain that
244
253
// both we and all peers successfully funded the channel for the specified asset
245
254
// according to the funding agreement.
246
255
// nolint: funlen
247
256
func (f * Funder ) waitForFundingConfirmation (ctx context.Context , request channel.FundingReq , asset assetHolder , fundingIDs [][32 ]byte ) error {
248
- deposited := make (chan * assetholder.AssetHolderDeposited )
249
- // Watch new events
250
- watchOpts , err := f .NewWatchOpts (ctx )
251
- if err != nil {
252
- return errors .WithMessage (err , "error creating watchopts" )
253
- }
254
- sub , err := asset .WatchDeposited (watchOpts , deposited , fundingIDs )
257
+ deposited := make (chan * subscription.Event )
258
+ subErr := make (chan error , 1 )
259
+ // Subscribe to events.
260
+ sub , err := f .depositedSub (ctx , asset .contract , fundingIDs ... )
255
261
if err != nil {
256
- err = cherrors .CheckIsChainNotReachableError (err )
257
- return errors .WithMessagef (err , "WatchDeposit on asset %d failed" , asset .assetIndex )
262
+ return errors .WithMessage (err , "subscribing to deposited event" )
258
263
}
259
- defer sub .Unsubscribe ()
260
-
261
- // we let the filter queries and all subscription errors write into this error
262
- // channel.
263
- errChan := make (chan error , 1 )
264
+ defer sub .Close ()
265
+ // Read from the sub.
264
266
go func () {
265
- err := <- sub .Err ()
266
- if err != nil {
267
- err = cherrors .CheckIsChainNotReachableError (err )
268
- }
269
- errChan <- errors .WithMessagef (err , "subscription for asset %d" , asset .assetIndex )
270
- }()
271
-
272
- // Query all old funding events
273
- go func () {
274
- iter , err := filterFunds (ctx , asset , fundingIDs ... )
275
- if err != nil {
276
- errChan <- errors .WithMessagef (err , "filtering old Deposited events for asset %d" , asset .assetIndex )
277
- return
278
- }
279
- defer iter .Close () // nolint: errcheck
280
- for iter .Next () {
281
- deposited <- iter .Event
282
- }
267
+ subErr <- sub .ReadAll (ctx , deposited )
283
268
}()
284
269
285
270
// The allocation that all participants agreed on.
@@ -290,7 +275,8 @@ func (f *Funder) waitForFundingConfirmation(ctx context.Context, request channel
290
275
// Wait for all non-zero funding requests
291
276
for N > 0 {
292
277
select {
293
- case event := <- deposited :
278
+ case rawEvent := <- deposited :
279
+ event := rawEvent .Data .(* assetholder.AssetHolderDeposited )
294
280
log := f .log .WithField ("fundingID" , event .FundingID )
295
281
296
282
// Calculate the position in the participant array.
@@ -320,7 +306,7 @@ func (f *Funder) waitForFundingConfirmation(ctx context.Context, request channel
320
306
return & channel.AssetFundingError {Asset : asset .assetIndex , TimedOutPeers : indices }
321
307
}
322
308
return nil
323
- case err := <- errChan :
309
+ case err := <- subErr :
324
310
return err
325
311
}
326
312
}
0 commit comments