Skip to content

Commit 856384f

Browse files
authored
feat: Additional readAs fields (#784)
1 parent 3376efd commit 856384f

5 files changed

Lines changed: 55 additions & 7 deletions

File tree

chainwrappers/executors.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/json"
55
"fmt"
66

7-
"github.com/samber/lo"
87
chainsel "github.com/smartcontractkit/chain-selectors"
98

109
"github.com/smartcontractkit/mcms/sdk"
@@ -173,7 +172,7 @@ func BuildExecutor(
173172
return nil, fmt.Errorf("missing Canton chain participant for selector %d", rawSelector)
174173
}
175174
participant := ch.Participants[0]
176-
mcmsParties := lo.Map(ch.Participants, func(p cantonsdk.Participant, _ int) string { return p.PartyID })
175+
mcmsParties := cantonsdk.MCMSPartiesForChain(ch)
177176
cantonEncoder, ok := encoder.(*cantonsdk.Encoder)
178177
if !ok {
179178
return nil, fmt.Errorf("invalid encoder type for selector %d: %T", chainSelector, encoder)

chainwrappers/inspectors.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/json"
55
"fmt"
66

7-
"github.com/samber/lo"
87
chainsel "github.com/smartcontractkit/chain-selectors"
98

109
"github.com/smartcontractkit/mcms/sdk"
@@ -58,7 +57,7 @@ func BuildInspector(
5857
return nil, fmt.Errorf("missing Canton chain participant for selector %d", rawSelector)
5958
}
6059
participant := ch.Participants[0]
61-
mcmsParties := lo.Map(ch.Participants, func(p cantonsdk.Participant, _ int) string { return p.PartyID })
60+
mcmsParties := cantonsdk.MCMSPartiesForChain(ch)
6261
role, err := cantonsdk.CantonRoleFromAction(action)
6362
if err != nil {
6463
return nil, fmt.Errorf("error getting canton role from proposal: %w", err)

chainwrappers/timelock_executors.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/json"
55
"fmt"
66

7-
"github.com/samber/lo"
87
chainsel "github.com/smartcontractkit/chain-selectors"
98

109
"github.com/smartcontractkit/mcms/sdk"
@@ -142,7 +141,7 @@ func BuildTimelockExecutor(
142141
return nil, fmt.Errorf("missing Canton chain participant for selector %d", rawSelector)
143142
}
144143
participant := ch.Participants[0]
145-
mcmsParties := lo.Map(ch.Participants, func(p cantonsdk.Participant, _ int) string { return p.PartyID })
144+
mcmsParties := cantonsdk.MCMSPartiesForChain(ch)
146145

147146
return cantonsdk.NewTimelockExecutor(
148147
participant.LedgerServices.Command,

sdk/canton/chain.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ type LedgerServices struct {
1212

1313
// Participant is a Canton ledger participant used by MCMS.
1414
type Participant struct {
15-
PartyID string
15+
PartyID string
16+
// ReadAsPartyIDs lists parties this user may read as (CanReadAs). MCMS contracts are often
17+
// visible only under owner parties (for example ccipOwner), not the operator ActAs party alone.
18+
ReadAsPartyIDs []string
1619
LedgerServices LedgerServices
1720
}
1821

sdk/canton/ledger_query_parties.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package canton
2+
3+
// LedgerQueryParties builds the party list for ledger ACS reads (GetActiveContracts, etc.).
4+
//
5+
// The operator participant may ActAs one party while holding CanReadAs for others (for example
6+
// CCIP owner parties under MCMS). Contract visibility is per-party: an MCMS instance might only
7+
// be readable via ReadAs party B even when ActAs party A cannot see it.
8+
//
9+
// Order is ActAs party first, then ReadAs parties in config order. Duplicates and empty strings
10+
// are omitted.
11+
func LedgerQueryParties(participant Participant) []string {
12+
parties := make([]string, 0, 1+len(participant.ReadAsPartyIDs))
13+
seen := make(map[string]struct{}, 1+len(participant.ReadAsPartyIDs))
14+
add := func(party string) {
15+
if party == "" {
16+
return
17+
}
18+
if _, ok := seen[party]; ok {
19+
return
20+
}
21+
seen[party] = struct{}{}
22+
parties = append(parties, party)
23+
}
24+
add(participant.PartyID)
25+
for _, party := range participant.ReadAsPartyIDs {
26+
add(party)
27+
}
28+
29+
return parties
30+
}
31+
32+
// MCMSPartiesForChain returns the deduplicated party list for MCMS ledger queries across all
33+
// chain participants.
34+
func MCMSPartiesForChain(ch Chain) []string {
35+
parties := make([]string, 0)
36+
seen := make(map[string]struct{})
37+
for _, participant := range ch.Participants {
38+
for _, party := range LedgerQueryParties(participant) {
39+
if _, ok := seen[party]; ok {
40+
continue
41+
}
42+
seen[party] = struct{}{}
43+
parties = append(parties, party)
44+
}
45+
}
46+
47+
return parties
48+
}

0 commit comments

Comments
 (0)