Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-OCR3 - interface and sample base implementation #842

Merged
merged 16 commits into from
May 21, 2024

Conversation

elatoskinas
Copy link
Collaborator

@elatoskinas elatoskinas commented May 13, 2024

Motivation

Implements an OCR3 interface that supports the latest OCR needs:

  1. Multi-plugin support: Ability to configure & use multiple OCR plugins under one contract interface
  2. OCR3 plugin compatibility: interface changes (pulled from liquiditymanager OCR3Abstract)
  3. Simplified config digest handling: no longer re-compute config digest / no passing of on-chain config, since the source of truth data will live in the Capability Registry

Solution

Focus: the foucs of the PR is on the interface and structure rather on the exact logic

  • Implements a MultiOCR3Base abstract contract to match multi-plugin, Capability Registry and OCR3 plugin interface expectations
  • Converts _transmit to be internal - implementations are expected to implement separate transmit functions per-DON, since each report logic will be different, e.g. for CCIP:
function transmitExecution(
  // same params as _transmit, except the donId
) {
  // ... handle reporting logic
  _transmit(
    s_transmitDonId,
    // (pass in remaining params from function args)
  );
}

function transmitCommit(
  // same params as _transmit, except the donId
) {
  // ... handle reporting logic
  _transmit(
     s_commitDonId,
     // (pass in remaining params from function args)
  );
}
  • Sample implementation of MultiOCR3Base, with signature skipping support & multi-DON configs

  • Out of scope

    • Config validations & oracle updating logic
    • Transmit msg length handling for different transmit function cases
    • Gas / contract size optimizations

Copy link
Contributor

github-actions bot commented May 13, 2024

LCOV of commit 3f25cfd during Solidity Foundry #4469

Summary coverage rate:
  lines......: 98.8% (1251 of 1266 lines)
  functions..: 96.4% (266 of 276 functions)
  branches...: 92.2% (507 of 550 branches)

Files changed coverage rate: n/a

contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
/// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
/// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
/// @param rawVs ith element is the the V component of the ith signature
function transmit(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: this could rename to _auth later on, and skip the transmission event, if we were to move it to another Auth contract.

TBD based on feasibility of merging contracts

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah transmission event is interesting, its basically used for this https://github.com/smartcontractkit/libocr/blob/73bda92fc450decece23011c007b253bd1be75fd/offchainreporting2plus/types/types.go#L324 offchain. Moving it outside to the caller of _auth is a bit strange because then caller has to parse out the sequenceNumber. Maybe that's worth it though for the separation of concerns this contract is purely a verification contract

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can still transmit with the donId/pluginId and we'd be able to differentiate b/w the two plugins and implement that interface correctly.

The higher level issue here is that this will be emitted on the destination chain and not all DON nodes can read the destination, so I wonder if we need to go back to that config tracking w/ voting idea Lorenz pointed out in our call last week, otherwise I'm not sure how you can get the whole committee to land on the same sequence number/config digest.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used in the pacemaker to restore the epoch: https://github.com/smartcontractkit/libocr/blob/fd3cab206b2ca3b7ff207996b95673b2d6303ec4/offchainreporting2plus/internal/ocr2/protocol/pacemaker.go#L302-L345 presumably after e.g restarting the node. So seems kinda important.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think its an issue because LatestTransmissionDetails is part of the contract transmitter which will only be invoked on node which can read/write to the remote

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can still transmit with the donId/pluginId and we'd be able to differentiate b/w the two plugins and implement that interface correctly.

Yeah this makes sense - I agree with this. However, if we have a decoupled auth contract, it makes more sense emitting on the contract that is actually the OCR contract, rather than the Auth contract to decouple (otherwise the AuthContract emits multiple OCR events for different instances / capabilities)

@elatoskinas elatoskinas requested a review from RayXpub May 13, 2024 11:39
contracts/src/v0.8/ccip/ocr/MultiOCR3Abstract.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Abstract.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Abstract.sol Outdated Show resolved Hide resolved
/// @notice latest OCR config
ConfigInfo configInfo;
/// @notice makes it easier for offchain systems to extract config from logs.
uint32 latestConfigBlockNumber;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this latestConfigBlockNumber optimization not really necessary anymore with our log system (logpoller) offchain, can remove

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate a bit on the log poller - does it mean we will have the block numbers next to the ConfigSet events which will be efficiently queryable, so we no longer need the field on-chain?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this because config won't be fetched from the dest chain anyway, only from home chain.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But in the blue/green model, the config digests on the remote chains might be set at different intervals than on the home chain - isn't it helpful to be able to query the history in case something goes wrong?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, config digests on remote will be set after the green config is set on home chain. What kind of sanity check would you do with latestConfigBlockNumber though (offchain)? It has no relationship to the home chain config block number. I think OCR used it in the past so that we can do a granular log query just for ConfigSet logs in that particular block but since config log fetching logic is completely different now, not sure how you'd use this

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would not be used in sanity checks, but rather to retrieve the blocks when a staging config was set to the active config (by reading the latest block value and applying a query filter). The purpose would just be for debugging / inspection purposes if something goes wrong.

But I'd expect we already have this data available and efficiently queryable on the log poller?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the field

/// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
/// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
/// @param rawVs ith element is the the V component of the ith signature
function transmit(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah transmission event is interesting, its basically used for this https://github.com/smartcontractkit/libocr/blob/73bda92fc450decece23011c007b253bd1be75fd/offchainreporting2plus/types/types.go#L324 offchain. Moving it outside to the caller of _auth is a bit strange because then caller has to parse out the sequenceNumber. Maybe that's worth it though for the separation of concerns this contract is purely a verification contract

contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Abstract.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Abstract.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Abstract.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Abstract.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
/// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
/// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
/// @param rawVs ith element is the the V component of the ith signature
function transmit(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can still transmit with the donId/pluginId and we'd be able to differentiate b/w the two plugins and implement that interface correctly.

The higher level issue here is that this will be emitted on the destination chain and not all DON nodes can read the destination, so I wonder if we need to go back to that config tracking w/ voting idea Lorenz pointed out in our call last week, otherwise I'm not sure how you can get the whole committee to land on the same sequence number/config digest.

/// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
/// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries
/// @param rawVs ith element is the the V component of the ith signature
function transmit(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used in the pacemaker to restore the epoch: https://github.com/smartcontractkit/libocr/blob/fd3cab206b2ca3b7ff207996b95673b2d6303ec4/offchainreporting2plus/internal/ocr2/protocol/pacemaker.go#L302-L345 presumably after e.g restarting the node. So seems kinda important.

contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol Outdated Show resolved Hide resolved
@elatoskinas elatoskinas changed the base branch from temp/multi-ocr-copies to ccip-develop May 17, 2024 16:33
@elatoskinas elatoskinas marked this pull request as ready for review May 17, 2024 16:39
}
}

// TODO: is this function required?
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recon we don't need this anymore? Or is there still a use-case for this? @connorwstein @makramkd

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would only be helpful if offchain we we're trying to make use of a shared transmitter which already implemented https://github.com/smartcontractkit/libocr/blob/73bda92fc450decece23011c007b253bd1be75fd/offchainreporting2plus/types/types.go#L324. I suspect we'll have a custom transmitter anyways to call different functions we can remove it for now.

// The constant-length components of the msg.data sent to transmit.
// See the "If we wanted to call sam" example on for example reasoning
// https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html
// TODO: assumes a constant function sig like in _transmit. Will need adjustment (either removing
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: will revisit this and validations in a follow-up PR focused on validations

}
}

// TODO: is this function required?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would only be helpful if offchain we we're trying to make use of a shared transmitter which already implemented https://github.com/smartcontractkit/libocr/blob/73bda92fc450decece23011c007b253bd1be75fd/offchainreporting2plus/types/types.go#L324. I suspect we'll have a custom transmitter anyways to call different functions we can remove it for now.

@elatoskinas elatoskinas merged commit a0d4251 into ccip-develop May 21, 2024
79 checks passed
@elatoskinas elatoskinas deleted the feat/multi-ocr3-base branch May 21, 2024 09:48
@elatoskinas
Copy link
Collaborator Author

Note: to be iterated in next PRs - the interface is not yet final

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants