Skip to content

Commit dbff21e

Browse files
authored
feat: changes the data structure of operations and it's use in proposals (#140)
This is a large change that changes the data structure of operations. The current implementation promotes confusion with the usage of terms operations and transactions. This change aims to make the codebase more readable and maintainable, and provide a clear distinction between operations and transactions. Operations are now a separate entity from transactions. Operations are defined as a piece of work that the MCMS can execute, while transactions are the low level chain specific data structure that the MCMS can hash, sign and execute on chain.
1 parent f7f7670 commit dbff21e

37 files changed

+553
-468
lines changed

builder.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func NewProposalBuilder() *ProposalBuilder {
7373
Kind: types.KindProposal,
7474
ChainMetadata: make(map[types.ChainSelector]types.ChainMetadata),
7575
},
76-
Transactions: []types.ChainOperation{},
76+
Operations: []types.Operation{},
7777
},
7878
}
7979
// Initialize the BaseProposalBuilder with a reference to the base proposal and the builder itself.
@@ -85,16 +85,16 @@ func NewProposalBuilder() *ProposalBuilder {
8585
return builder
8686
}
8787

88-
// AddTransaction adds a transaction to the Proposal.
89-
func (b *ProposalBuilder) AddTransaction(transaction types.ChainOperation) *ProposalBuilder {
90-
b.proposal.Transactions = append(b.proposal.Transactions, transaction)
88+
// AddOperation adds an operation to the Proposal.
89+
func (b *ProposalBuilder) AddOperation(op types.Operation) *ProposalBuilder {
90+
b.proposal.Operations = append(b.proposal.Operations, op)
9191

9292
return b
9393
}
9494

95-
// SetTransactions sets all the transactions of the Proposal.
96-
func (b *ProposalBuilder) SetTransactions(transaction []types.ChainOperation) *ProposalBuilder {
97-
b.proposal.Transactions = transaction
95+
// SetOperations sets all the operations of the Proposal.
96+
func (b *ProposalBuilder) SetOperations(ops []types.Operation) *ProposalBuilder {
97+
b.proposal.Operations = ops
9898

9999
return b
100100
}

builder_test.go

+23-23
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ func TestProposalBuilder(t *testing.T) {
4242
SetDescription("Valid Proposal").
4343
SetOverridePreviousRoot(false).
4444
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
45-
AddTransaction(types.ChainOperation{
45+
AddOperation(types.Operation{
4646
ChainSelector: types.ChainSelector(SepoliaSelector),
47-
Operation: types.Operation{Data: []byte{0x01}},
47+
Transaction: types.Transaction{Data: []byte{0x01}},
4848
})
4949
},
5050
want: &mcms.Proposal{
@@ -58,10 +58,10 @@ func TestProposalBuilder(t *testing.T) {
5858
types.ChainSelector(SepoliaSelector): {StartingOpCount: 0},
5959
},
6060
},
61-
Transactions: []types.ChainOperation{
61+
Operations: []types.Operation{
6262
{
6363
ChainSelector: types.ChainSelector(SepoliaSelector),
64-
Operation: types.Operation{Data: []byte{0x01}},
64+
Transaction: types.Transaction{Data: []byte{0x01}},
6565
},
6666
},
6767
},
@@ -75,14 +75,14 @@ func TestProposalBuilder(t *testing.T) {
7575
SetDescription("Valid Proposal").
7676
SetOverridePreviousRoot(false).
7777
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
78-
SetTransactions([]types.ChainOperation{
78+
SetOperations([]types.Operation{
7979
{
8080
ChainSelector: types.ChainSelector(SepoliaSelector),
81-
Operation: types.Operation{Data: []byte{0x01}},
81+
Transaction: types.Transaction{Data: []byte{0x01}},
8282
},
8383
{
8484
ChainSelector: types.ChainSelector(SepoliaSelector),
85-
Operation: types.Operation{Data: []byte{0x02}},
85+
Transaction: types.Transaction{Data: []byte{0x02}},
8686
},
8787
})
8888
},
@@ -97,14 +97,14 @@ func TestProposalBuilder(t *testing.T) {
9797
types.ChainSelector(SepoliaSelector): {StartingOpCount: 0},
9898
},
9999
},
100-
Transactions: []types.ChainOperation{
100+
Operations: []types.Operation{
101101
{
102102
ChainSelector: types.ChainSelector(SepoliaSelector),
103-
Operation: types.Operation{Data: []byte{0x01}},
103+
Transaction: types.Transaction{Data: []byte{0x01}},
104104
},
105105
{
106106
ChainSelector: types.ChainSelector(SepoliaSelector),
107-
Operation: types.Operation{Data: []byte{0x02}},
107+
Transaction: types.Transaction{Data: []byte{0x02}},
108108
},
109109
},
110110
},
@@ -120,14 +120,14 @@ func TestProposalBuilder(t *testing.T) {
120120
SetChainMetadata(map[types.ChainSelector]types.ChainMetadata{
121121
types.ChainSelector(SepoliaSelector): {StartingOpCount: 0},
122122
}).
123-
SetTransactions([]types.ChainOperation{
123+
SetOperations([]types.Operation{
124124
{
125125
ChainSelector: types.ChainSelector(SepoliaSelector),
126-
Operation: types.Operation{Data: []byte{0x01}},
126+
Transaction: types.Transaction{Data: []byte{0x01}},
127127
},
128128
{
129129
ChainSelector: types.ChainSelector(SepoliaSelector),
130-
Operation: types.Operation{Data: []byte{0x02}},
130+
Transaction: types.Transaction{Data: []byte{0x02}},
131131
},
132132
}).
133133
AddSignature(types.Signature{
@@ -152,14 +152,14 @@ func TestProposalBuilder(t *testing.T) {
152152
types.ChainSelector(SepoliaSelector): {StartingOpCount: 0},
153153
},
154154
},
155-
Transactions: []types.ChainOperation{
155+
Operations: []types.Operation{
156156
{
157157
ChainSelector: types.ChainSelector(SepoliaSelector),
158-
Operation: types.Operation{Data: []byte{0x01}},
158+
Transaction: types.Transaction{Data: []byte{0x01}},
159159
},
160160
{
161161
ChainSelector: types.ChainSelector(SepoliaSelector),
162-
Operation: types.Operation{Data: []byte{0x02}},
162+
Transaction: types.Transaction{Data: []byte{0x02}},
163163
},
164164
},
165165
},
@@ -172,9 +172,9 @@ func TestProposalBuilder(t *testing.T) {
172172
SetDescription("Missing Version").
173173
SetOverridePreviousRoot(false).
174174
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
175-
AddTransaction(types.ChainOperation{
175+
AddOperation(types.Operation{
176176
ChainSelector: types.ChainSelector(SepoliaSelector),
177-
Operation: types.Operation{Data: []byte{0x01}},
177+
Transaction: types.Transaction{Data: []byte{0x01}},
178178
})
179179
},
180180
want: nil,
@@ -190,9 +190,9 @@ func TestProposalBuilder(t *testing.T) {
190190
SetDescription("ValidUntil in Past").
191191
SetOverridePreviousRoot(false).
192192
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
193-
AddTransaction(types.ChainOperation{
193+
AddOperation(types.Operation{
194194
ChainSelector: types.ChainSelector(SepoliaSelector),
195-
Operation: types.Operation{Data: []byte{0x01}},
195+
Transaction: types.Transaction{Data: []byte{0x01}},
196196
})
197197
},
198198
want: nil,
@@ -212,7 +212,7 @@ func TestProposalBuilder(t *testing.T) {
212212
},
213213
want: nil,
214214
wantErrs: []string{
215-
"Key: 'Proposal.Transactions' Error:Field validation for 'Transactions' failed on the 'min' tag",
215+
"Key: 'Proposal.Operations' Error:Field validation for 'Operations' failed on the 'min' tag",
216216
},
217217
},
218218
{
@@ -223,9 +223,9 @@ func TestProposalBuilder(t *testing.T) {
223223
SetDescription("Missing ChainMetadata").
224224
SetOverridePreviousRoot(false).
225225
// ChainMetadata is not added
226-
AddTransaction(types.ChainOperation{
226+
AddOperation(types.Operation{
227227
ChainSelector: types.ChainSelector(SepoliaSelector),
228-
Operation: types.Operation{Data: []byte{0x01}},
228+
Transaction: types.Transaction{Data: []byte{0x01}},
229229
})
230230
},
231231
want: nil,

builder_timelock.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func NewTimelockProposalBuilder() *TimelockProposalBuilder {
1717
ChainMetadata: make(map[types.ChainSelector]types.ChainMetadata),
1818
},
1919
TimelockAddresses: make(map[types.ChainSelector]string),
20-
Transactions: []types.BatchChainOperation{},
20+
Operations: []types.BatchOperation{},
2121
},
2222
}
2323
builder.BaseProposalBuilder = BaseProposalBuilder[*TimelockProposalBuilder]{
@@ -46,16 +46,16 @@ func (b *TimelockProposalBuilder) SetTimelockAddress(selector types.ChainSelecto
4646
return b
4747
}
4848

49-
// AddTransaction adds a transaction to the timelock proposal.
50-
func (b *TimelockProposalBuilder) AddTransaction(transaction types.BatchChainOperation) *TimelockProposalBuilder {
51-
b.proposal.Transactions = append(b.proposal.Transactions, transaction)
49+
// AddOperation adds an operation to the timelock proposal.
50+
func (b *TimelockProposalBuilder) AddOperation(bop types.BatchOperation) *TimelockProposalBuilder {
51+
b.proposal.Operations = append(b.proposal.Operations, bop)
5252

5353
return b
5454
}
5555

5656
// SetTransactions sets all the transactions of the proposal
57-
func (b *TimelockProposalBuilder) SetTransactions(transactions []types.BatchChainOperation) *TimelockProposalBuilder {
58-
b.proposal.Transactions = transactions
57+
func (b *TimelockProposalBuilder) SetTransactions(bops []types.BatchOperation) *TimelockProposalBuilder {
58+
b.proposal.Operations = bops
5959

6060
return b
6161
}

builder_timelock_test.go

+19-19
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ func TestTimelockProposalBuilder(t *testing.T) {
4747
SetDelay("24h").
4848
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
4949
SetTimelockAddress(types.ChainSelector(SepoliaSelector), "0xTimelockAddress").
50-
AddTransaction(types.BatchChainOperation{
50+
AddOperation(types.BatchOperation{
5151
ChainSelector: types.ChainSelector(SepoliaSelector),
52-
Batch: []types.Operation{
52+
Transactions: []types.Transaction{
5353
{
5454
Data: []byte{0x01},
5555
To: "0xContractAddress",
@@ -74,10 +74,10 @@ func TestTimelockProposalBuilder(t *testing.T) {
7474
TimelockAddresses: map[types.ChainSelector]string{
7575
types.ChainSelector(SepoliaSelector): "0xTimelockAddress",
7676
},
77-
Transactions: []types.BatchChainOperation{
77+
Operations: []types.BatchOperation{
7878
{
7979
ChainSelector: types.ChainSelector(SepoliaSelector),
80-
Batch: []types.Operation{
80+
Transactions: []types.Transaction{
8181
{
8282
Data: []byte{0x01},
8383
To: "0xContractAddress",
@@ -100,9 +100,9 @@ func TestTimelockProposalBuilder(t *testing.T) {
100100
SetDelay("24h").
101101
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
102102
SetTimelockAddress(types.ChainSelector(SepoliaSelector), "0xTimelockAddress").
103-
SetTransactions([]types.BatchChainOperation{{
103+
SetTransactions([]types.BatchOperation{{
104104
ChainSelector: types.ChainSelector(SepoliaSelector),
105-
Batch: []types.Operation{
105+
Transactions: []types.Transaction{
106106
{
107107
Data: []byte{0x01},
108108
To: "0xContractAddress",
@@ -128,10 +128,10 @@ func TestTimelockProposalBuilder(t *testing.T) {
128128
TimelockAddresses: map[types.ChainSelector]string{
129129
types.ChainSelector(SepoliaSelector): "0xTimelockAddress",
130130
},
131-
Transactions: []types.BatchChainOperation{
131+
Operations: []types.BatchOperation{
132132
{
133133
ChainSelector: types.ChainSelector(SepoliaSelector),
134-
Batch: []types.Operation{
134+
Transactions: []types.Transaction{
135135
{
136136
Data: []byte{0x01},
137137
To: "0xContractAddress",
@@ -154,9 +154,9 @@ func TestTimelockProposalBuilder(t *testing.T) {
154154
// Missing SetDelay
155155
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
156156
SetTimelockAddress(types.ChainSelector(SepoliaSelector), "0xTimelockAddress").
157-
AddTransaction(types.BatchChainOperation{
157+
AddOperation(types.BatchOperation{
158158
ChainSelector: types.ChainSelector(SepoliaSelector),
159-
Batch: []types.Operation{
159+
Transactions: []types.Transaction{
160160
{
161161
Data: []byte{0x01},
162162
To: "0xContractAddress",
@@ -181,9 +181,9 @@ func TestTimelockProposalBuilder(t *testing.T) {
181181
SetDelay("invalid_duration").
182182
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
183183
SetTimelockAddress(types.ChainSelector(SepoliaSelector), "0xTimelockAddress").
184-
AddTransaction(types.BatchChainOperation{
184+
AddOperation(types.BatchOperation{
185185
ChainSelector: types.ChainSelector(SepoliaSelector),
186-
Batch: []types.Operation{
186+
Transactions: []types.Transaction{
187187
{
188188
Data: []byte{0x01},
189189
To: "0xContractAddress",
@@ -208,9 +208,9 @@ func TestTimelockProposalBuilder(t *testing.T) {
208208
SetDelay("24h").
209209
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
210210
// Missing SetTimelockAddress
211-
AddTransaction(types.BatchChainOperation{
211+
AddOperation(types.BatchOperation{
212212
ChainSelector: types.ChainSelector(SepoliaSelector),
213-
Batch: []types.Operation{
213+
Transactions: []types.Transaction{
214214
{
215215
Data: []byte{0x01},
216216
To: "0xContractAddress",
@@ -239,7 +239,7 @@ func TestTimelockProposalBuilder(t *testing.T) {
239239
},
240240
want: nil,
241241
wantErrs: []string{
242-
"Key: 'TimelockProposal.Transactions' Error:Field validation for 'Transactions' failed on the 'min' tag",
242+
"Key: 'TimelockProposal.Operations' Error:Field validation for 'Operations' failed on the 'min' tag",
243243
},
244244
},
245245
{
@@ -253,9 +253,9 @@ func TestTimelockProposalBuilder(t *testing.T) {
253253
SetDelay("24h").
254254
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
255255
SetTimelockAddress(types.ChainSelector(SepoliaSelector), "0xTimelockAddress").
256-
AddTransaction(types.BatchChainOperation{
256+
AddOperation(types.BatchOperation{
257257
ChainSelector: types.ChainSelector(SepoliaSelector),
258-
Batch: []types.Operation{
258+
Transactions: []types.Transaction{
259259
{
260260
Data: []byte{0x01},
261261
To: "0xContractAddress",
@@ -280,9 +280,9 @@ func TestTimelockProposalBuilder(t *testing.T) {
280280
SetAction("invalid_action").
281281
AddChainMetadata(types.ChainSelector(SepoliaSelector), types.ChainMetadata{StartingOpCount: 0}).
282282
SetTimelockAddress(types.ChainSelector(SepoliaSelector), "0xTimelockAddress").
283-
AddTransaction(types.BatchChainOperation{
283+
AddOperation(types.BatchOperation{
284284
ChainSelector: types.ChainSelector(SepoliaSelector),
285-
Batch: []types.Operation{
285+
Transactions: []types.Transaction{
286286
{
287287
Data: []byte{0x01},
288288
To: "0xContractAddress",

docs/_sidebar.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
- [Key Concepts](/key-concepts.md)
22
- [Configuration](key-concepts/configuration.md)
3-
- [MCMS Proposal](key-concepts/mcms-proposal.md)
3+
- [MCM Proposal](key-concepts/mcm-proposal.md)
44
- [TimeLock Proposal](key-concepts/timelock-proposal.md)
5-
- [Operations & Chain Metadata](key-concepts/operations-and-chain-metadata.md)
5+
- [Chain Metadata](key-concepts/chain-metadata.md)
6+
- [Operations](key-concepts/operations.md)
67
- [Merkle Tree Signing](key-concepts/merkle.md)
78
- [Chain Family SDK](key-concepts/chain-family-sdk.md ':disabled')
89
- [Usage](/usage.md)

docs/key-concepts/chain-metadata.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Chain Metadata
2+
3+
Chain Metadata is shared across all proposal types and contains the information that allow transactions to be hashed and executed for it's respective chain. It is a map of chain-specific configuration for each blockchain involved in the proposal. The key of the object is the chain selector ID, and the value is the metadata object. An entry is required for every chain referenced in the proposal's operations.
4+
5+
<!-- panels:start -->
6+
<!-- div:left-panel -->
7+
### Chain Metadata Structure
8+
9+
```json
10+
{
11+
"16015286601757825753": {
12+
"startingOpCount": 1,
13+
"mcmAddress": "0x0"
14+
}
15+
}
16+
```
17+
18+
<!-- div:right-panel -->
19+
20+
### Chain Selector ID
21+
22+
**Key** uint64<br/>
23+
The chain selector ID matching the chain based on the [Chain Selectors](https://github.com/smartcontractkit/chain-selectors) library.
24+
25+
### Metadata Object
26+
27+
**startingOpCount** uint64<br/>
28+
The starting operation count, typically used for parallel signing processes.
29+
30+
---
31+
32+
**mcmAddress** string<br/>
33+
The MCM contract address that will process this proposal on the respective chain.
34+
35+
<!-- panels:end -->

0 commit comments

Comments
 (0)