From 14a0774f09cd4d0b8de821b31ef840573d8c94c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 9 Apr 2024 16:19:46 +0900 Subject: [PATCH 1/2] Remove gauntlet exmaple commands (we no longer use it for examples/) --- .../src/commands/example/declare.ts | 11 --- .../src/commands/example/deploy.ts | 52 ------------- .../src/commands/example/index.ts | 6 -- .../src/commands/example/inspect.ts | 75 ------------------- .../src/commands/index.ts | 11 +-- 5 files changed, 1 insertion(+), 154 deletions(-) delete mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/example/declare.ts delete mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/example/deploy.ts delete mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/example/index.ts delete mode 100644 packages-ts/starknet-gauntlet-ocr2/src/commands/example/inspect.ts diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/declare.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/declare.ts deleted file mode 100644 index df507cd57..000000000 --- a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/declare.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { makeExecuteCommand, declareCommandConfig } from '@chainlink/starknet-gauntlet' -import { CATEGORIES } from '../../lib/categories' -import { CONTRACT_LIST, aggregatorConsumerLoader } from '../../lib/contracts' - -export default makeExecuteCommand( - declareCommandConfig( - CONTRACT_LIST.AGGREGATOR_CONSUMER, - CATEGORIES.OCR2, - aggregatorConsumerLoader, - ), -) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/deploy.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/deploy.ts deleted file mode 100644 index 3a8f84315..000000000 --- a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/deploy.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { ExecuteCommandConfig, makeExecuteCommand } from '@chainlink/starknet-gauntlet' -import { isValidAddress } from '@chainlink/starknet-gauntlet' -import { CATEGORIES } from '../../lib/categories' -import { CONTRACT_LIST, aggregatorConsumerLoader } from '../../lib/contracts' -import { validateClassHash } from '../../lib/utils' - -export interface UserInput { - address: string - classHash?: string -} - -type ContractInput = [address: string] - -const makeUserInput = async (flags, args): Promise => { - if (flags.input) return flags.input as UserInput - - return { - address: flags.address, - classHash: flags.classHash, - } -} - -const makeContractInput = async (input: UserInput): Promise => { - return [input.address] -} - -const validateInput = async (input: UserInput): Promise => { - if (!isValidAddress(input.address)) { - throw new Error(`Invalid OCR2 address: ${input.address}`) - } - - return true -} - -const commandConfig: ExecuteCommandConfig = { - contractId: CONTRACT_LIST.AGGREGATOR_CONSUMER, - category: CATEGORIES.OCR2, - action: 'deploy', - suffixes: ['consumer'], - ux: { - description: 'Deploys an example Aggregator consumer', - examples: [ - `${CATEGORIES.OCR2}:consumer:deploy --network= --address= --classHash=`, - ], - }, - makeUserInput, - makeContractInput, - validations: [validateInput, validateClassHash], - loadContract: aggregatorConsumerLoader, -} - -export default makeExecuteCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/index.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/index.ts deleted file mode 100644 index 8362de175..000000000 --- a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import Deploy from './deploy' -import Declare from './declare' -import Inspect from './inspect' - -export const executeCommands = [Deploy, Declare] -export const inspectionCommands = [Inspect] diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/inspect.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/example/inspect.ts deleted file mode 100644 index cb29b4437..000000000 --- a/packages-ts/starknet-gauntlet-ocr2/src/commands/example/inspect.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { - InspectCommandConfig, - IStarknetProvider, - makeInspectionCommand, - InspectUserInput, -} from '@chainlink/starknet-gauntlet' -import { CATEGORIES } from '../../lib/categories' -import { aggregatorConsumerLoader } from '../../lib/contracts' -import { uint256 } from 'starknet' - -type UserInput = {} - -type ContractInput = null - -type QueryResult = { - roundId: string - answer: string - decimals: string -} - -const makeUserInput = async (flags, args): Promise> => { - if (flags.input) return flags.input as InspectUserInput - - return { - input: {}, - } -} - -const makeContractInput = async (input: UserInput): Promise => { - return [] -} - -const makeComparisionData = (provider: IStarknetProvider) => async ( - results: any[], - input: null, - contractAddress: string, -): Promise<{ - toCompare: null - result: QueryResult -}> => { - const [round, decimals] = results - const { round_id, answer } = round[0] - - // workaround proxy returning incorrect round id (0x1 in high register uint256) - // todo: remove/adjust when figured out - const roundIdUint256 = uint256.bnToUint256(round_id) - roundIdUint256.high = 0 - const roundId = uint256.uint256ToBN(roundIdUint256) - - return { - toCompare: null, - result: { - roundId: roundId.toString(), - answer: answer.toString(), - decimals: decimals[0].toString(), - }, - } -} - -const commandConfig: InspectCommandConfig = { - ux: { - category: CATEGORIES.OCR2, - function: 'inspect:consumer', - examples: [ - `${CATEGORIES.OCR2}:inspect:consumer --network= `, - ], - }, - queries: ['readLatestRound', 'readDecimals'], - makeUserInput, - makeContractInput, - makeComparisionData, - loadContract: aggregatorConsumerLoader, -} - -export default makeInspectionCommand(commandConfig) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/index.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/index.ts index 19c958b40..5f7344a13 100644 --- a/packages-ts/starknet-gauntlet-ocr2/src/commands/index.ts +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/index.ts @@ -9,19 +9,10 @@ import { executeCommands as proxyExecuteCommands, inspectionCommands as proxyInspectionCommands, } from './proxy' -import { - executeCommands as exampleExecuteCommands, - inspectionCommands as exampleInspectionCommands, -} from './example' export const executeCommands = [ ...acExecuteCommands, ...ocr2ExecuteCommands, ...proxyExecuteCommands, - ...exampleExecuteCommands, -] -export const inspectionCommands = [ - ...ocr2InspectionCommands, - ...proxyInspectionCommands, - ...exampleInspectionCommands, ] +export const inspectionCommands = [...ocr2InspectionCommands, ...proxyInspectionCommands] From 432411eed4c4b21b31eae6e114719bef02a0a8e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 9 Apr 2024 17:22:28 +0900 Subject: [PATCH 2/2] gauntlet: Fix ConfigSet event decoding --- .../commands/ocr2/inspection/configEvent.ts | 10 +------ .../src/commands/ocr2/setConfig.ts | 22 +++++++++++--- .../src/lib/encoding.ts | 29 ++++--------------- .../starknet-gauntlet/src/encoding/index.ts | 4 +-- 4 files changed, 26 insertions(+), 39 deletions(-) diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/inspection/configEvent.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/inspection/configEvent.ts index 52b1632e7..4b43d0b75 100644 --- a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/inspection/configEvent.ts +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/inspection/configEvent.ts @@ -27,13 +27,5 @@ export const getLatestOCRConfigEvent = async ( keys: [keyFilter], chunk_size: 10, }) - const events = chunk.events - // if no config set events found in the given block, throw error - // this should not happen if block number in latestConfigDetails is set correctly - if (events.length === 0) - throw new Error(`No ConfigSet events found in block number ${latestConfigDetails.blockNumber}`) - - // assume last event found is the latest config, in the event that multiple - // set_config transactions ended up in the same block - return events[events.length - 1].data + return chunk.events } diff --git a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setConfig.ts b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setConfig.ts index 8ee7ad79a..56a70369e 100644 --- a/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setConfig.ts +++ b/packages-ts/starknet-gauntlet-ocr2/src/commands/ocr2/setConfig.ts @@ -14,6 +14,7 @@ import { SetConfig, encoding, SetConfigInput } from '@chainlink/gauntlet-contrac import { decodeOffchainConfigFromEventData } from '../../lib/encoding' import assert from 'assert' import { getLatestOCRConfigEvent } from './inspection/configEvent' +import { BigNumberish, GetTransactionReceiptResponse } from 'starknet' type Oracle = { signer: string @@ -136,15 +137,26 @@ const beforeExecute: BeforeExecute = ( input.user.offchainConfig, input.user.secret, ) + const newOffchainConfig = encoding.deserializeConfig(offchainConfig) - const eventData = await getLatestOCRConfigEvent(context.provider, context.contractAddress) - if (eventData.length === 0) { + const rawEvents = await getLatestOCRConfigEvent(context.provider, context.contractAddress) + if (rawEvents.length === 0) { + // if no config set events found in the given block, throw error + // this should not happen if block number in latestConfigDetails is set correctly deps.logger.info('No previous config found, review the offchain config below:') deps.logger.log(newOffchainConfig) return } - const currOffchainConfig = decodeOffchainConfigFromEventData(eventData) + // assume last event found is the latest config, in the event that multiple + // set_config transactions ended up in the same block + const events = context.contract.parseEvents({ + events: rawEvents, + } as GetTransactionReceiptResponse) + const event = events[events.length - 1]['ConfigSet'] + const currOffchainConfig = decodeOffchainConfigFromEventData( + event.offchain_config as BigNumberish[], + ) deps.logger.info( 'Review the proposed offchain config changes below: green - added, red - deleted.', @@ -162,7 +174,9 @@ const afterExecute: AfterExecute = (context, inpu } const eventData = txInfo.events[0].data - const offchainConfig = decodeOffchainConfigFromEventData(eventData) + const events = context.contract.parseEvents(txInfo) + const event = events[events.length - 1]['ConfigSet'] + const offchainConfig = decodeOffchainConfigFromEventData(event.offchain_config as BigNumberish[]) try { // remove cfg keys from user input delete input.user.offchainConfig.configPublicKeys diff --git a/packages-ts/starknet-gauntlet-ocr2/src/lib/encoding.ts b/packages-ts/starknet-gauntlet-ocr2/src/lib/encoding.ts index e061cffd3..e33ac54db 100644 --- a/packages-ts/starknet-gauntlet-ocr2/src/lib/encoding.ts +++ b/packages-ts/starknet-gauntlet-ocr2/src/lib/encoding.ts @@ -1,28 +1,9 @@ import { encoding } from '@chainlink/gauntlet-contracts-ocr2' import { feltsToBytes } from '@chainlink/starknet-gauntlet' +import { BigNumberish } from 'starknet' -export const decodeOffchainConfigFromEventData = (data: string[]): encoding.OffchainConfig => { - // The ConfigSet event is defined as: - // fn ConfigSet( - // previous_config_block_number: u64, (key) - // latest_config_digest: felt252, (key) - // config_count: u64, - // oracles: Array, - // f: u8, - // onchain_config: Array, - // offchain_config_version: u64, - // offchain_config: Array, - //) - const oraclesLenIndex = 1 - const oraclesLen = Number(BigInt(data[oraclesLenIndex])) - const oracleStructSize = 2 - const fIndex = oraclesLenIndex + oraclesLen * oracleStructSize + 1 - const onchainConfigLenIndex = fIndex + 1 - const onchainConfigLen = Number(BigInt(data[onchainConfigLenIndex])) - const offchainConfigVersionIndex = onchainConfigLenIndex + onchainConfigLen + 1 - const offchainConfigArrayLenIndex = offchainConfigVersionIndex + 1 - const offchainConfigStartIndex = offchainConfigArrayLenIndex + 1 - - const offchainConfigFelts = data.slice(offchainConfigStartIndex) - return encoding.deserializeConfig(feltsToBytes(offchainConfigFelts)) +export const decodeOffchainConfigFromEventData = ( + data: BigNumberish[], +): encoding.OffchainConfig => { + return encoding.deserializeConfig(feltsToBytes(data)) } diff --git a/packages-ts/starknet-gauntlet/src/encoding/index.ts b/packages-ts/starknet-gauntlet/src/encoding/index.ts index e102a489d..b05ae7795 100644 --- a/packages-ts/starknet-gauntlet/src/encoding/index.ts +++ b/packages-ts/starknet-gauntlet/src/encoding/index.ts @@ -1,4 +1,4 @@ -import { cairo } from 'starknet' +import { BigNumberish, cairo } from 'starknet' const CHUNK_SIZE = 31 @@ -28,7 +28,7 @@ export function bytesToFelts(data: Uint8Array | Buffer): string[] { const MAX_LEN: bigint = (BigInt(1) << BigInt(54)) - BigInt(1) -export function feltsToBytes(felts: string[]): Buffer { +export function feltsToBytes(felts: BigNumberish[]): Buffer { const data: number[] = [] if (!felts.length) {