Skip to content

Commit

Permalink
Keystone: add router and other refactors (#13426)
Browse files Browse the repository at this point in the history
* keystone: Split forwarder into two contracts

* keystone: Add a ConfigSet event

* add events to router, further changes

* forwarder: Use OwnerIsCreator, ITypeAndVersion

* Remove TODO

* Replace _splitSignature with code

* minor gas savings by caching config var

* Cache array length

* Remove TODO

* Port over reentrancy guard optimization

* Don't assign signers twice

* Update gethwrappers

* Address some feedback on KeystoneFeedsConsumer

* Inline signer in setConfig/clearConfig

* Update gethwrappers

* Remove unused import

* prettier format

* Generate bindings for router too

* Update gethwrappers

* Fix keystone scripts

* Add KeystoneRouter tests

* Update snapshot

* Remove redundant operations

* Remove more variables

* Remove another unnecessary conversion

* Remove unnecessary version check

* ConfigId bytes32 => uint64

* Slight improvement to error path with duplicate signer

* Optimize clearConfig function

* More micro optimizations

* Inline functions

* Remove dangling error

* Move things around

* Add reportId to ReportProcessed

* Handle empty receiver address case

* Side: update "f" value in CapabilityRegistry

* Nit: import order

* Style Guide: uint256 i = 0

* Add forwarder and router getters

* Add changesets

* Remove unused error

* Update gethwrappers

* receiverAddress -> receiver

* Update gethwrappers

---------

Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com>
Co-authored-by: DeividasK <deividas.karzinauskas@gmail.com>
  • Loading branch information
3 people committed Jun 10, 2024
1 parent 4fdfffd commit 592b2bb
Show file tree
Hide file tree
Showing 20 changed files with 1,681 additions and 297 deletions.
5 changes: 5 additions & 0 deletions .changeset/shy-deers-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

#internal
5 changes: 5 additions & 0 deletions contracts/.changeset/new-bugs-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/contracts': patch
---

#internal
178 changes: 92 additions & 86 deletions contracts/gas-snapshots/keystone.gas-snapshot

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions contracts/scripts/native_solc_compile_all_keystone
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ compileContract () {

compileContract keystone/CapabilityRegistry.sol
compileContract keystone/KeystoneForwarder.sol
compileContract keystone/KeystoneRouter.sol
compileContract keystone/OCR3Capability.sol
12 changes: 6 additions & 6 deletions contracts/src/v0.8/keystone/CapabilityRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
/// @notice The f value for the DON. This is the number of faulty nodes
/// that the DON can tolerate. This can be different from the f value of
/// the OCR instances that capabilities spawn.
uint32 f;
uint8 f;
/// @notice True if the DON is public. A public DON means that it accepts
/// external capability requests
bool isPublic;
Expand All @@ -177,7 +177,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
/// @notice The f value for the DON. This is the number of faulty nodes
/// that the DON can tolerate. This can be different from the f value of
/// the OCR instances that capabilities spawn.
uint32 f;
uint8 f;
/// @notice True if the DON is public. A public DON means that it accepts
/// external capability requests
bool isPublic;
Expand All @@ -196,7 +196,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
uint32 configCount;
bool isPublic;
bool acceptsWorkflows;
uint32 f;
uint8 f;
}

/// @notice This error is thrown when a caller is not allowed
Expand Down Expand Up @@ -265,7 +265,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
/// fault tolerance value.
/// @param f The proposed fault tolerance value
/// @param nodeCount The proposed number of nodes in the DON
error InvalidFaultTolerance(uint32 f, uint256 nodeCount);
error InvalidFaultTolerance(uint8 f, uint256 nodeCount);

/// @notice This error is thrown when a capability with the provided hashed ID is
/// not found.
Expand Down Expand Up @@ -689,7 +689,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
CapabilityConfiguration[] calldata capabilityConfigurations,
bool isPublic,
bool acceptsWorkflows,
uint32 f
uint8 f
) external onlyOwner {
uint32 id = s_nextDONId++;
s_dons[id].id = id;
Expand All @@ -715,7 +715,7 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
CapabilityConfiguration[] calldata capabilityConfigurations,
bool isPublic,
bool acceptsWorkflows,
uint32 f
uint8 f
) external onlyOwner {
uint32 configCount = s_dons[donId].configCount;
if (configCount == 0) revert DONDoesNotExist(donId);
Expand Down
32 changes: 15 additions & 17 deletions contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
pragma solidity ^0.8.19;

import {IReceiver} from "./interfaces/IReceiver.sol";
import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol";
import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol";

contract KeystoneFeedsConsumer is IReceiver, ConfirmedOwner {
contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator {
event FeedReceived(bytes32 indexed feedId, int192 price, uint32 timestamp);

error UnauthorizedSender(address sender);
error UnauthorizedWorkflowOwner(address workflowOwner);
error UnauthorizedWorkflowName(bytes10 workflowName);

constructor() ConfirmedOwner(msg.sender) {}

struct ReceivedFeedReport {
bytes32 FeedId;
int192 Price;
Expand All @@ -26,55 +24,55 @@ contract KeystoneFeedsConsumer is IReceiver, ConfirmedOwner {

mapping(bytes32 feedId => StoredFeedReport feedReport) internal s_feedReports;
address[] internal s_allowedSendersList;
mapping(address => bool) internal s_allowedSenders;
mapping(address sender => bool) internal s_allowedSenders;
address[] internal s_allowedWorkflowOwnersList;
mapping(address => bool) internal s_allowedWorkflowOwners;
mapping(address owner => bool) internal s_allowedWorkflowOwners;
bytes10[] internal s_allowedWorkflowNamesList;
mapping(bytes10 => bool) internal s_allowedWorkflowNames;
mapping(bytes10 workflowName => bool) internal s_allowedWorkflowNames;

function setConfig(
address[] calldata _allowedSendersList,
address[] calldata _allowedWorkflowOwnersList,
bytes10[] calldata _allowedWorkflowNamesList
) external onlyOwner {
for (uint32 i = 0; i < s_allowedSendersList.length; i++) {
for (uint32 i = 0; i < s_allowedSendersList.length; ++i) {
s_allowedSenders[s_allowedSendersList[i]] = false;
}
for (uint32 i = 0; i < _allowedSendersList.length; i++) {
for (uint32 i = 0; i < _allowedSendersList.length; ++i) {
s_allowedSenders[_allowedSendersList[i]] = true;
}
s_allowedSendersList = _allowedSendersList;
for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; i++) {
for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; ++i) {
s_allowedWorkflowOwners[s_allowedWorkflowOwnersList[i]] = false;
}
for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; i++) {
for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; ++i) {
s_allowedWorkflowOwners[_allowedWorkflowOwnersList[i]] = true;
}
s_allowedWorkflowOwnersList = _allowedWorkflowOwnersList;
for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; i++) {
for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; ++i) {
s_allowedWorkflowNames[s_allowedWorkflowNamesList[i]] = false;
}
for (uint32 i = 0; i < _allowedWorkflowNamesList.length; i++) {
for (uint32 i = 0; i < _allowedWorkflowNamesList.length; ++i) {
s_allowedWorkflowNames[_allowedWorkflowNamesList[i]] = true;
}
s_allowedWorkflowNamesList = _allowedWorkflowNamesList;
}

function onReport(bytes calldata metadata, bytes calldata rawReport) external {
if (s_allowedSenders[msg.sender] == false) {
if (!s_allowedSenders[msg.sender]) {
revert UnauthorizedSender(msg.sender);
}

(bytes10 workflowName, address workflowOwner) = _getInfo(metadata);
if (s_allowedWorkflowNames[workflowName] == false) {
if (!s_allowedWorkflowNames[workflowName]) {
revert UnauthorizedWorkflowName(workflowName);
}
if (s_allowedWorkflowOwners[workflowOwner] == false) {
if (!s_allowedWorkflowOwners[workflowOwner]) {
revert UnauthorizedWorkflowOwner(workflowOwner);
}

ReceivedFeedReport[] memory feeds = abi.decode(rawReport, (ReceivedFeedReport[]));
for (uint32 i = 0; i < feeds.length; i++) {
for (uint256 i = 0; i < feeds.length; ++i) {
s_feedReports[feeds[i].FeedId] = StoredFeedReport(feeds[i].Price, feeds[i].Timestamp);
emit FeedReceived(feeds[i].FeedId, feeds[i].Price, feeds[i].Timestamp);
}
Expand Down
Loading

0 comments on commit 592b2bb

Please sign in to comment.