@@ -23,20 +23,30 @@ import (
2323)
2424
2525// Funder is a multi-ledger funder.
26+ // funders is a map of LedgerIDs corresponding to a funder on some chain.
27+ // egoisticChains is a map of LedgerIDs corresponding to a boolean indicating whether the chain should be funded last.
2628type Funder struct {
27- funders map [LedgerIDMapKey ]channel.Funder
29+ funders map [LedgerIDMapKey ]channel.Funder
30+ egoisticChains map [LedgerIDMapKey ]bool
2831}
2932
3033// NewFunder creates a new funder.
3134func NewFunder () * Funder {
3235 return & Funder {
33- funders : make (map [LedgerIDMapKey ]channel.Funder ),
36+ funders : make (map [LedgerIDMapKey ]channel.Funder ),
37+ egoisticChains : make (map [LedgerIDMapKey ]bool ),
3438 }
3539}
3640
3741// RegisterFunder registers a funder for a given ledger.
3842func (f * Funder ) RegisterFunder (l LedgerID , lf channel.Funder ) {
3943 f .funders [l .MapKey ()] = lf
44+ f .egoisticChains [l .MapKey ()] = false
45+ }
46+
47+ // SetEgoisticChain sets the egoistic chain flag for a given ledger.
48+ func (f * Funder ) SetEgoisticChain (l LedgerID , egoistic bool ) {
49+ f .egoisticChains [l .MapKey ()] = egoistic
4050}
4151
4252// Fund funds a multi-ledger channel. It dispatches funding calls to all
@@ -53,21 +63,48 @@ func (f *Funder) Fund(ctx context.Context, request channel.FundingReq) error {
5363 return err
5464 }
5565
66+ var egoisticLedgers []LedgerID
67+ var nonEgoisticLedgers []LedgerID
68+
69+ for _ , l := range ledgers {
70+ if f .egoisticChains [l .MapKey ()] {
71+ egoisticLedgers = append (egoisticLedgers , l )
72+ } else {
73+ nonEgoisticLedgers = append (nonEgoisticLedgers , l )
74+ }
75+ }
76+
77+ // First fund with Funders that are not egoistic.
78+ err = fundLedgers (ctx , request , nonEgoisticLedgers , f .funders )
79+ if err != nil {
80+ return err
81+ }
82+
83+ // Then fund with egoistic Funders.
84+ err = fundLedgers (ctx , request , egoisticLedgers , f .funders )
85+ if err != nil {
86+ return err
87+ }
88+
89+ return nil
90+ }
91+
92+ func fundLedgers (ctx context.Context , request channel.FundingReq , ledgers []LedgerID , funders map [LedgerIDMapKey ]channel.Funder ) error {
5693 n := len (ledgers )
5794 errs := make (chan error , n )
58- for _ , l := range ledgers {
59- go func (l LedgerID ) {
95+ for _ , le := range ledgers {
96+ go func (le LedgerID ) {
6097 errs <- func () error {
61- id := l .MapKey ()
62- lf , ok := f . funders [id ]
98+ id := le .MapKey ()
99+ lf , ok := funders [id ]
63100 if ! ok {
64101 return fmt .Errorf ("Funder not found for ledger %v" , id )
65102 }
66103
67104 err := lf .Fund (ctx , request )
68105 return err
69106 }()
70- }(l )
107+ }(le )
71108 }
72109
73110 for i := 0 ; i < n ; i ++ {
@@ -76,6 +113,5 @@ func (f *Funder) Fund(ctx context.Context, request channel.FundingReq) error {
76113 return err
77114 }
78115 }
79-
80116 return nil
81117}
0 commit comments