Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/gentle-waves-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink-deployments-framework": minor
---

feat(mcms): check MCM state before calling SetRoot or Execute
65 changes: 65 additions & 0 deletions engine/cld/legacy/cli/mcmsv2/mcms_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ func buildExecuteOperationv2Cmd(lggr logger.Logger, domain cldf_domain.Domain, p
if err != nil {
return fmt.Errorf("error converting proposal to executable: %w", err)
}
inspector, err := getInspectorFromChainSelector(*cfg)
if err != nil {
return fmt.Errorf("failed to get inspector: %w", err)
}

if cfg.fork {
lggr.Info("Fork mode is on, all transactions will be executed on a forked chain")
}
Expand All @@ -213,6 +218,23 @@ func buildExecuteOperationv2Cmd(lggr logger.Logger, domain cldf_domain.Domain, p
return fmt.Errorf("operation %d is not for chain %d", index, cfg.chainSelector)
}

opCount, err := inspector.GetOpCount(cmd.Context(), cfg.proposal.ChainMetadata[types.ChainSelector(cfg.chainSelector)].MCMAddress)
if err != nil {
return fmt.Errorf("failed to get opcount for chain %d: %w", cfg.chainSelector, err)
}
txNonce, err := executable.TxNonce(index)
if err != nil {
return fmt.Errorf("failed to get TxNonce for chain %d: %w", cfg.chainSelector, err)
}
if txNonce < opCount {
lggr.Infow("operation already executed", "index", index, "txNonce", txNonce, "opCount", opCount)
return nil
}
if txNonce > opCount {
lggr.Warnw("txNonce too large", "index", index, "txNonce", txNonce, "opCount", opCount)
return fmt.Errorf("txNonce too large (%d; expected %d)", txNonce, opCount)
}

tx, err := executable.Execute(cmd.Context(), index)
if err != nil {
err = cldf.DecodeErr(bindings.ManyChainMultiSigABI, err)
Expand Down Expand Up @@ -1177,6 +1199,11 @@ func executeChainCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2, sk
if err != nil {
return fmt.Errorf("error converting proposal to executable: %w", err)
}
inspector, err := getInspectorFromChainSelector(*cfg)
if err != nil {
return fmt.Errorf("failed to get inspector: %w", err)
}

if cfg.fork {
lggr.Info("Fork mode is on, all transactions will be executed on a forked chain")
}
Expand All @@ -1187,6 +1214,23 @@ func executeChainCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2, sk
continue
}

opCount, err := inspector.GetOpCount(ctx, cfg.proposal.ChainMetadata[types.ChainSelector(cfg.chainSelector)].MCMAddress)
if err != nil {
return fmt.Errorf("failed to get opcount for chain %d: %w", cfg.chainSelector, err)
}
txNonce, err := executable.TxNonce(i)
if err != nil {
return fmt.Errorf("failed to get TxNonce for chain %d: %w", cfg.chainSelector, err)
}
if txNonce < opCount {
lggr.Infow("operation already executed", "index", i, "txNonce", txNonce, "opCount", opCount)
continue
}
if txNonce > opCount {
lggr.Warnw("txNonce too large", "index", i, "txNonce", txNonce, "opCount", opCount)
break
}

tx, err := executable.Execute(ctx, i)
if err != nil {
lggr.Errorf("error executing operation %d: %s", i, err)
Expand Down Expand Up @@ -1229,6 +1273,27 @@ func setRootCommand(ctx context.Context, lggr logger.Logger, cfg *cfgv2) error {
lggr.Info("Fork mode is on, all transactions will be executed on a forked chain")
}

inspector, err := getInspectorFromChainSelector(*cfg)
if err != nil {
return fmt.Errorf("failed to get inspector: %w", err)
}

proposalMerkleTree, err := cfg.proposal.MerkleTree()
if err != nil {
return fmt.Errorf("failed to compute the proposal's merkle tree: %w", err)
}

mcmAddress := cfg.proposal.ChainMetadata[types.ChainSelector(cfg.chainSelector)].MCMAddress
mcmRoot, _, err := inspector.GetRoot(ctx, mcmAddress)
if err != nil {
return fmt.Errorf("failed to get the merkle tree root from the MCM contract (%v): %w", mcmAddress, err)
}

if mcmRoot == proposalMerkleTree.Root {
lggr.Infof("Root %v already set in MCM contract %v", mcmRoot, mcmAddress)
return nil
}

executable, err := createExecutable(cfg)
if err != nil {
return fmt.Errorf("error converting proposal to executable: %w", err)
Expand Down
Loading
Loading