-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[KS-54] OCR3 contract + config tooling (#12078)
* [KS-54] OCR3 contract + config tooling * Update CODEOWNERS Co-authored-by: Blaž Hrastnik <[email protected]> --------- Co-authored-by: Blaž Hrastnik <[email protected]>
- Loading branch information
Showing
5 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.6; | ||
|
||
import {OCR2Base} from "../shared/ocr2/OCR2Base.sol"; | ||
|
||
// OCR2Base provides config management compatible with OCR3 | ||
contract OCR3Capability is OCR2Base { | ||
error ReportingUnsupported(); | ||
|
||
constructor() OCR2Base(true) {} | ||
|
||
function typeAndVersion() external pure override returns (string memory) { | ||
return "Keystone 0.0.0"; | ||
} | ||
|
||
function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal override {} | ||
|
||
function _afterSetConfig(uint8 _f, bytes memory _onchainConfig) internal override {} | ||
|
||
function _validateReport( | ||
bytes32 /* configDigest */, | ||
uint40 /* epochAndRound */, | ||
bytes memory /* report */ | ||
) internal pure override returns (bool) { | ||
return true; | ||
} | ||
|
||
function _report( | ||
uint256 /* initialGas */, | ||
address /* transmitter */, | ||
uint8 /* signerCount */, | ||
address[MAX_NUM_ORACLES] memory /* signers */, | ||
bytes calldata /* report */ | ||
) internal virtual override { | ||
revert ReportingUnsupported(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"OracleConfig": { | ||
"MaxQueryLengthBytes": 1000000, | ||
"MaxObservationLengthBytes": 1000000, | ||
"MaxReportLengthBytes": 1000000, | ||
"MaxRequestBatchSize": 1000, | ||
"UniqueReports": true, | ||
|
||
"DeltaProgressMillis": 5000, | ||
"DeltaResendMillis": 5000, | ||
"DeltaInitialMillis": 5000, | ||
"DeltaRoundMillis": 2000, | ||
"DeltaGraceMillis": 500, | ||
"DeltaCertifiedCommitRequestMillis": 1000, | ||
"DeltaStageMillis": 30000, | ||
"MaxRoundsPerEpoch": 10, | ||
"TransmissionSchedule": [1, 1, 1, 1], | ||
|
||
"MaxDurationQueryMillis": 1000, | ||
"MaxDurationObservationMillis": 1000, | ||
"MaxDurationReportMillis": 1000, | ||
"MaxDurationAcceptMillis": 1000, | ||
"MaxDurationTransmitMillis": 1000, | ||
|
||
"MaxFaultyOracles": 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
package main | ||
|
||
import ( | ||
"crypto/ed25519" | ||
"encoding/hex" | ||
"encoding/json" | ||
"flag" | ||
"fmt" | ||
"io" | ||
"os" | ||
"time" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
|
||
"github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" | ||
"github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" | ||
"github.com/smartcontractkit/libocr/offchainreporting2plus/types" | ||
|
||
helpers "github.com/smartcontractkit/chainlink/core/scripts/common" | ||
) | ||
|
||
type TopLevelConfigSource struct { | ||
OracleConfig OracleConfigSource | ||
} | ||
|
||
type OracleConfigSource struct { | ||
MaxQueryLengthBytes uint32 | ||
MaxObservationLengthBytes uint32 | ||
MaxReportLengthBytes uint32 | ||
MaxRequestBatchSize uint32 | ||
UniqueReports bool | ||
|
||
DeltaProgressMillis uint32 | ||
DeltaResendMillis uint32 | ||
DeltaInitialMillis uint32 | ||
DeltaRoundMillis uint32 | ||
DeltaGraceMillis uint32 | ||
DeltaCertifiedCommitRequestMillis uint32 | ||
DeltaStageMillis uint32 | ||
MaxRoundsPerEpoch uint64 | ||
TransmissionSchedule []int | ||
|
||
MaxDurationQueryMillis uint32 | ||
MaxDurationObservationMillis uint32 | ||
MaxDurationAcceptMillis uint32 | ||
MaxDurationTransmitMillis uint32 | ||
|
||
MaxFaultyOracles int | ||
} | ||
|
||
type NodeKeys struct { | ||
EthAddress string | ||
P2PPeerID string // p2p_<key> | ||
OCR2BundleID string // used only in job spec | ||
OCR2OnchainPublicKey string // ocr2on_evm_<key> | ||
OCR2OffchainPublicKey string // ocr2off_evm_<key> | ||
OCR2ConfigPublicKey string // ocr2cfg_evm_<key> | ||
CSAPublicKey string | ||
} | ||
|
||
type orc2drOracleConfig struct { | ||
Signers []string `json:"signers"` | ||
Transmitters []string `json:"transmitters"` | ||
F uint8 `json:"f"` | ||
OnchainConfig string `json:"onchainConfig"` | ||
OffchainConfigVersion uint64 `json:"offchainConfigVersion"` | ||
OffchainConfig string `json:"offchainConfig"` | ||
} | ||
|
||
type generateOCR2Config struct { | ||
} | ||
|
||
func NewGenerateOCR2ConfigCommand() *generateOCR2Config { | ||
return &generateOCR2Config{} | ||
} | ||
|
||
func (g *generateOCR2Config) Name() string { | ||
return "generate-ocr2config" | ||
} | ||
|
||
func mustParseJSONConfigFile(fileName string) (output TopLevelConfigSource) { | ||
return mustParseJSON[TopLevelConfigSource](fileName) | ||
} | ||
|
||
func mustParseKeysFile(fileName string) (output []NodeKeys) { | ||
return mustParseJSON[[]NodeKeys](fileName) | ||
} | ||
|
||
func mustParseJSON[T any](fileName string) (output T) { | ||
jsonFile, err := os.Open(fileName) | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer jsonFile.Close() | ||
bytes, err := io.ReadAll(jsonFile) | ||
if err != nil { | ||
panic(err) | ||
} | ||
err = json.Unmarshal(bytes, &output) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return | ||
} | ||
|
||
func main() { | ||
fs := flag.NewFlagSet("config_gen", flag.ExitOnError) | ||
configFile := fs.String("config", "config_example.json", "a file containing JSON config") | ||
keysFile := fs.String("keys", "public_keys_example.json", "a file containing node public keys") | ||
if err := fs.Parse(os.Args[1:]); err != nil || *keysFile == "" || *configFile == "" { | ||
fs.Usage() | ||
os.Exit(1) | ||
} | ||
|
||
topLevelCfg := mustParseJSONConfigFile(*configFile) | ||
cfg := topLevelCfg.OracleConfig | ||
nca := mustParseKeysFile(*keysFile) | ||
|
||
onchainPubKeys := []common.Address{} | ||
for _, n := range nca { | ||
onchainPubKeys = append(onchainPubKeys, common.HexToAddress(n.OCR2OnchainPublicKey)) | ||
} | ||
|
||
offchainPubKeysBytes := []types.OffchainPublicKey{} | ||
for _, n := range nca { | ||
pkBytes, err := hex.DecodeString(n.OCR2OffchainPublicKey) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
pkBytesFixed := [ed25519.PublicKeySize]byte{} | ||
nCopied := copy(pkBytesFixed[:], pkBytes) | ||
if nCopied != ed25519.PublicKeySize { | ||
panic("wrong num elements copied from ocr2 offchain public key") | ||
} | ||
|
||
offchainPubKeysBytes = append(offchainPubKeysBytes, types.OffchainPublicKey(pkBytesFixed)) | ||
} | ||
|
||
configPubKeysBytes := []types.ConfigEncryptionPublicKey{} | ||
for _, n := range nca { | ||
pkBytes, err := hex.DecodeString(n.OCR2ConfigPublicKey) | ||
helpers.PanicErr(err) | ||
|
||
pkBytesFixed := [ed25519.PublicKeySize]byte{} | ||
n := copy(pkBytesFixed[:], pkBytes) | ||
if n != ed25519.PublicKeySize { | ||
panic("wrong num elements copied") | ||
} | ||
|
||
configPubKeysBytes = append(configPubKeysBytes, types.ConfigEncryptionPublicKey(pkBytesFixed)) | ||
} | ||
|
||
identities := []confighelper.OracleIdentityExtra{} | ||
for index := range nca { | ||
identities = append(identities, confighelper.OracleIdentityExtra{ | ||
OracleIdentity: confighelper.OracleIdentity{ | ||
OnchainPublicKey: onchainPubKeys[index][:], | ||
OffchainPublicKey: offchainPubKeysBytes[index], | ||
PeerID: nca[index].P2PPeerID, | ||
TransmitAccount: types.Account(nca[index].EthAddress), | ||
}, | ||
ConfigEncryptionPublicKey: configPubKeysBytes[index], | ||
}) | ||
} | ||
|
||
signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( | ||
time.Duration(cfg.DeltaProgressMillis)*time.Millisecond, | ||
time.Duration(cfg.DeltaResendMillis)*time.Millisecond, | ||
time.Duration(cfg.DeltaInitialMillis)*time.Millisecond, | ||
time.Duration(cfg.DeltaRoundMillis)*time.Millisecond, | ||
time.Duration(cfg.DeltaGraceMillis)*time.Millisecond, | ||
time.Duration(cfg.DeltaCertifiedCommitRequestMillis)*time.Millisecond, | ||
time.Duration(cfg.DeltaStageMillis)*time.Millisecond, | ||
cfg.MaxRoundsPerEpoch, | ||
cfg.TransmissionSchedule, | ||
identities, | ||
nil, // empty plugin config | ||
time.Duration(cfg.MaxDurationQueryMillis)*time.Millisecond, | ||
time.Duration(cfg.MaxDurationObservationMillis)*time.Millisecond, | ||
time.Duration(cfg.MaxDurationAcceptMillis)*time.Millisecond, | ||
time.Duration(cfg.MaxDurationTransmitMillis)*time.Millisecond, | ||
cfg.MaxFaultyOracles, | ||
nil, // empty onChain config | ||
) | ||
helpers.PanicErr(err) | ||
|
||
var signersStr []string | ||
var transmittersStr []string | ||
for i := range transmitters { | ||
signersStr = append(signersStr, "0x"+hex.EncodeToString(signers[i])) | ||
transmittersStr = append(transmittersStr, string(transmitters[i])) | ||
} | ||
|
||
config := orc2drOracleConfig{ | ||
Signers: signersStr, | ||
Transmitters: transmittersStr, | ||
F: f, | ||
OnchainConfig: "0x" + hex.EncodeToString(onchainConfig), | ||
OffchainConfigVersion: offchainConfigVersion, | ||
OffchainConfig: "0x" + hex.EncodeToString(offchainConfig), | ||
} | ||
|
||
js, err := json.MarshalIndent(config, "", " ") | ||
helpers.PanicErr(err) | ||
fmt.Println("Config:", string(js)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
[ | ||
{ | ||
"EthAddress": "0x9639dCc7D0ca4468B5f684ef89F12F0B365c9F6d", | ||
"P2PPeerID": "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", | ||
"OCR2BundleID": "29e8dd8c916eac1fc6df8ac6f449481f5db1cf3714e7cb629e16d7b499af5603", | ||
"OCR2OnchainPublicKey": "049b55674e2485b9a6788c0796b74f2c33667670", | ||
"OCR2OffchainPublicKey": "f4f13ca3053e0f44f869648857f0c0ebc20045f9b51d6a5712c867f5920def01", | ||
"OCR2ConfigPublicKey": "17a60b694f7cfb0a02da3da5e79f87b071e518d1f4a27aeb181776969b766e1e", | ||
"CSAPublicKey": "csa_2245bbbee39f75f22e12c345a0ac76bad1f3214b7020a47324a1634dee285761" | ||
}, | ||
{ | ||
"EthAddress": "0x8f0fAE64f5f75067833ed5deDC2804B62b21383d", | ||
"P2PPeerID": "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", | ||
"OCR2BundleID": "9b19ff8196aec2cdf70f6ac2c3617ea9b03dfb426e0938aee0af2b37459f86eb", | ||
"OCR2OnchainPublicKey": "8405c2b28fcab284f08ed0028f1f511cd57a16b7", | ||
"OCR2OffchainPublicKey": "29e41861f005a0b1bc3156ecd40992a5b552b3182f73f4adec43b4e3052ac2c7", | ||
"OCR2ConfigPublicKey": "0a0c21b14924ee28afad15c96b3a5be372870cdf9b13f002b63fb4ba8942c461", | ||
"CSAPublicKey": "csa_d329bfff7b7835aec205a6ac09bb217e46c754c3ab6730d09b709c7bc395dc3f" | ||
}, | ||
{ | ||
"EthAddress": "0xf09A863D920840c13277e76F43CFBdfB22b8FB7C", | ||
"P2PPeerID": "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", | ||
"OCR2BundleID": "200e5d187b4fc8e2d263c13cd28d37c914f275aba1aee91199d5c7766ada9d63", | ||
"OCR2OnchainPublicKey": "4a5199a4e65acfd07b690493ec02bdba3c44c1ec", | ||
"OCR2OffchainPublicKey": "f535037b9ca113d61eb0548e62c28d5abc201bfe36a803ea5f1e94f66da64c9e", | ||
"OCR2ConfigPublicKey": "d62623257ebf3e805ee77162a1b1df0d1b3f57c7dc1dc28b88acb6c9b4f5455f", | ||
"CSAPublicKey": "csa_35ff548c85ada4dbd09b5f02ea3421217d15ebec00a63cab7e529f8bb90542a1" | ||
}, | ||
{ | ||
"EthAddress": "0x7eD90b519bC3054a575C464dBf39946b53Ff90EF", | ||
"P2PPeerID": "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", | ||
"OCR2BundleID": "25b40149256109e6036f27b11969c61ba9e765fc60a13324410588c4801f0466", | ||
"OCR2OnchainPublicKey": "07183b1fe36c8f3885a3ce4131b9151a2c7e86b4", | ||
"OCR2OffchainPublicKey": "c64252067d48efe341745cff9aad2f20990158dfe31548322a0bf2921e9428b8", | ||
"OCR2ConfigPublicKey": "893f61aa755f356a248d66b58974742b22518db962ab036b440a33c3eb86ea5b", | ||
"CSAPublicKey": "csa_541f97026a2be5e460276ba4eddebce6e74ccb1d1cfb1550fe54ef615c0534c9" | ||
} | ||
] |