Skip to content

Commit ea68f1f

Browse files
feat: check MCM state before calling SetRoot or Execute
1 parent 1b9e949 commit ea68f1f

7 files changed

Lines changed: 408 additions & 11 deletions

File tree

.changeset/gentle-waves-appear.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"chainlink-deployments-framework": minor
3+
---
4+
5+
feat(mcms): check MCM state before calling SetRoot or Execute

engine/cld/legacy/cli/mcmsv2/mcms_v2.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ func buildExecuteOperationv2Cmd(lggr logger.Logger, domain cldf_domain.Domain, p
200200
if err != nil {
201201
return fmt.Errorf("error converting proposal to executable: %w", err)
202202
}
203+
inspector, err := getInspectorFromChainSelector(*cfg)
204+
if err != nil {
205+
return fmt.Errorf("failed to get inspector: %w", err)
206+
}
207+
203208
if cfg.fork {
204209
lggr.Info("Fork mode is on, all transactions will be executed on a forked chain")
205210
}
@@ -213,6 +218,20 @@ func buildExecuteOperationv2Cmd(lggr logger.Logger, domain cldf_domain.Domain, p
213218
return fmt.Errorf("operation %d is not for chain %d", index, cfg.chainSelector)
214219
}
215220

221+
opCount, err := inspector.GetOpCount(cmd.Context(), cfg.proposal.ChainMetadata[types.ChainSelector(cfg.chainSelector)].MCMAddress)
222+
if err != nil {
223+
return fmt.Errorf("failed to get opcount for chain %d: %w", cfg.chainSelector, err)
224+
}
225+
txNonce := executable.TxNonce(index)
226+
if txNonce < opCount {
227+
lggr.Infow("operation already executed", "index", index, "txNonce", txNonce, "opCount", opCount)
228+
return nil
229+
}
230+
if txNonce > opCount {
231+
lggr.Warnw("txNonce too large", "index", index, "txNonce", txNonce, "opCount", opCount)
232+
return fmt.Errorf("txNonce too large (%d; expected %d)", txNonce, opCount)
233+
}
234+
216235
tx, err := executable.Execute(cmd.Context(), index)
217236
if err != nil {
218237
err = cldf.DecodeErr(bindings.ManyChainMultiSigABI, err)
@@ -1173,6 +1192,11 @@ func executeChainCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2, sk
11731192
if err != nil {
11741193
return fmt.Errorf("error converting proposal to executable: %w", err)
11751194
}
1195+
inspector, err := getInspectorFromChainSelector(*cfg)
1196+
if err != nil {
1197+
return fmt.Errorf("failed to get inspector: %w", err)
1198+
}
1199+
11761200
if cfg.fork {
11771201
lggr.Info("Fork mode is on, all transactions will be executed on a forked chain")
11781202
}
@@ -1183,6 +1207,20 @@ func executeChainCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2, sk
11831207
continue
11841208
}
11851209

1210+
opCount, err := inspector.GetOpCount(ctx, cfg.proposal.ChainMetadata[types.ChainSelector(cfg.chainSelector)].MCMAddress)
1211+
if err != nil {
1212+
return fmt.Errorf("failed to get opcount for chain %d: %w", cfg.chainSelector, err)
1213+
}
1214+
txNonce := executable.TxNonce(i)
1215+
if txNonce < opCount {
1216+
lggr.Infow("operation already executed", "index", i, "txNonce", txNonce, "opCount", opCount)
1217+
continue
1218+
}
1219+
if txNonce > opCount {
1220+
lggr.Warnw("txNonce too large", "index", i, "txNonce", txNonce, "opCount", opCount)
1221+
break
1222+
}
1223+
11861224
tx, err := executable.Execute(ctx, i)
11871225
if err != nil {
11881226
lggr.Errorf("error executing operation %d: %s", i, err)
@@ -1225,6 +1263,27 @@ func setRootCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2) error {
12251263
lggr.Info("Fork mode is on, all transactions will be executed on a forked chain")
12261264
}
12271265

1266+
inspector, err := getInspectorFromChainSelector(*cfg)
1267+
if err != nil {
1268+
return fmt.Errorf("failed to get inspector: %w", err)
1269+
}
1270+
1271+
proposalMerkleTree, err := cfg.proposal.MerkleTree()
1272+
if err != nil {
1273+
return fmt.Errorf("failed to compute the proposal's merkle tree: %w", err)
1274+
}
1275+
1276+
mcmAddress := cfg.proposal.ChainMetadata[types.ChainSelector(cfg.chainSelector)].MCMAddress
1277+
mcmRoot, _, err := inspector.GetRoot(ctx, mcmAddress)
1278+
if err != nil {
1279+
return fmt.Errorf("failed to get the merkle tree root from the MCM contract (%v): %w", mcmAddress, err)
1280+
}
1281+
1282+
if mcmRoot == proposalMerkleTree.Root {
1283+
lggr.Infof("Root %v already set in MCM contract %v", mcmRoot, mcmAddress)
1284+
return nil
1285+
}
1286+
12281287
executable, err := createExecutable(cfg)
12291288
if err != nil {
12301289
return fmt.Errorf("error converting proposal to executable: %w", err)

0 commit comments

Comments
 (0)