From c58e0fbb12372296543e96387291660a763b1de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Thu, 17 Nov 2022 17:01:27 +0900 Subject: [PATCH] Merge in createProposal --- .../src/commands/contracts/ocr2/index.ts | 2 - .../contracts/ocr2/initialize.flow.ts | 8 -- .../contracts/ocr2/proposal/createProposal.ts | 75 ------------------- .../commands/contracts/ocr2/proposeConfig.ts | 57 +++++++++----- .../commands/contracts/ocr2/setup.dev.flow.ts | 9 +-- 5 files changed, 40 insertions(+), 111 deletions(-) delete mode 100644 gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/proposal/createProposal.ts diff --git a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/index.ts b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/index.ts index 24e47825f..e52ede004 100644 --- a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/index.ts +++ b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/index.ts @@ -14,7 +14,6 @@ import { CONTRACT_LIST } from '../../../lib/contracts' import { makeTransferOwnershipCommand } from '../ownership/transferOwnership' import { makeUpgradeProgramCommand } from '../../abstract/upgrade' import Fund from './fund' -import CreateProposal from './proposal/createProposal' import ProposeConfig from './proposeConfig' import Close from './close' import WithdrawFunds from './withdrawFunds' @@ -33,7 +32,6 @@ export default [ OCR2InitializeFlow, SetBilling, AcceptProposal, - CreateProposal, ProposeConfig, ReadState, SetBillingAccessController, diff --git a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/initialize.flow.ts b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/initialize.flow.ts index 384792bd5..4bd210901 100644 --- a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/initialize.flow.ts +++ b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/initialize.flow.ts @@ -8,7 +8,6 @@ import { logger, prompt } from '@chainlink/gauntlet-core/dist/utils' import OCR2Inspect from './inspection/inspect' import CreateFeed from '../store/createFeed' import SetWriter from '../store/setWriter' -import CreateProposal from './proposal/createProposal' import ProposeConfig from './proposeConfig' import AcceptProposal from './proposal/acceptProposal' @@ -67,15 +66,8 @@ export default class OCR2InitializeFlow extends FlowCommand }, { id: this.stepIds.PROPOSAL, - name: 'Create Proposal', - command: CreateProposal, - }, - { name: 'Propose Config', command: ProposeConfig, - flags: { - proposalId: FlowCommand.ID.data(this.stepIds.PROPOSAL, 'proposal'), - }, args: [FlowCommand.ID.contract(this.stepIds.OCR_2)], }, { diff --git a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/proposal/createProposal.ts b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/proposal/createProposal.ts deleted file mode 100644 index c217c50a6..000000000 --- a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/proposal/createProposal.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Result } from '@chainlink/gauntlet-core' -import { logger, BN, prompt } from '@chainlink/gauntlet-core/dist/utils' -import { SolanaCommand, TransactionResponse } from '@chainlink/gauntlet-solana' -import { PublicKey, Keypair, SystemProgram } from '@solana/web3.js' -import { CONTRACT_LIST, getContract } from '../../../../lib/contracts' - -export default class CreateProposal extends SolanaCommand { - static id = 'ocr2:create_proposal' - static category = CONTRACT_LIST.OCR_2 - - static examples = ['yarn gauntlet ocr2:create_proposal --network=devnet'] - - constructor(flags, args) { - super(flags, args) - } - - makeRawTransaction = async (signer: PublicKey, proposal?: PublicKey) => { - if (!proposal) throw new Error('Proposal address is required') - - const ocr2 = getContract(CONTRACT_LIST.OCR_2, '') - const address = ocr2.programId.toString() - const program = this.loadProgram(ocr2.idl, address) - - const version = new BN(2) - - logger.log('Generating data for creating config proposal') - logger.log('Config Proposal state will be at:', proposal.toString()) - - const createIx = await program.methods - .createProposal(version) - .accounts({ - proposal: proposal, - authority: signer, - }) - .instruction() - const defaultAccountSize = new BN(program.account.proposal.size) - const createAccountIx = SystemProgram.createAccount({ - fromPubkey: signer, - newAccountPubkey: proposal, - space: defaultAccountSize.toNumber(), - lamports: await this.provider.connection.getMinimumBalanceForRentExemption(defaultAccountSize.toNumber()), - programId: program.programId, - }) - - return [createAccountIx, createIx] - } - - execute = async () => { - const signer = this.wallet.publicKey - - const proposal = Keypair.generate() - const rawTx = await this.makeRawTransaction(signer, proposal.publicKey) - await this.simulateTx(signer, rawTx) - await prompt(`Continue creating config proposal?`) - - const txhash = await this.signAndSendRawTx(rawTx, [proposal]) - logger.success(`Config Proposal created on tx ${txhash}`) - logger.line() - logger.info('Use the Config Proposal ID in future proposal commands:') - logger.info(proposal.publicKey.toString()) - logger.line() - - return { - responses: [ - { - tx: this.wrapResponse(txhash, ''), - contract: '', - }, - ], - data: { - proposal: proposal.publicKey.toString(), - }, - } as Result - } -} diff --git a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/proposeConfig.ts b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/proposeConfig.ts index 32ca2e2d8..f973d4a14 100644 --- a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/proposeConfig.ts +++ b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/proposeConfig.ts @@ -1,7 +1,7 @@ import { Result } from '@chainlink/gauntlet-core' import { logger, BN, time, prompt, longs } from '@chainlink/gauntlet-core/dist/utils' import { SolanaCommand, TransactionResponse } from '@chainlink/gauntlet-solana' -import { PublicKey } from '@solana/web3.js' +import { Keypair, PublicKey, SystemProgram } from '@solana/web3.js' import { MAX_TRANSACTION_BYTES, ORACLES_MAX_LENGTH } from '../../../lib/constants' import { CONTRACT_LIST, getContract } from '../../../lib/contracts' import { divideIntoChunks } from '../../../lib/utils' @@ -96,7 +96,6 @@ type Input = { f: number | string offchainConfig: OffchainConfig userSecret?: string - proposalId: string } export const prepareOffchainConfigForDiff = (config: OffchainConfig, extra?: Object): Object => { @@ -112,12 +111,11 @@ const _toHex = (a: string) => Buffer.from(a, 'hex') export default class ProposeConfig extends SolanaCommand { static id = 'ocr2:propose_config' static category = CONTRACT_LIST.OCR_2 - static examples = [ - 'yarn gauntlet ocr2:propose_config --network=devnet --rdd=[PATH_TO_RDD] --proposalId=EPRYwrb1Dwi8VT5SutS4vYNdF8HqvE7QwvqeCCwHdVLC [AGGREGATOR_ADDRESS]', - ] + static examples = ['yarn gauntlet ocr2:propose_config --network=devnet --rdd=[PATH_TO_RDD] [AGGREGATOR_ADDRESS]'] input: Input randomSecret: string + proposal: Keypair static makeInputFromRDD = (rdd: any, stateAddress: string): OffchainConfig => { const aggregator = rdd.contracts[stateAddress] @@ -193,16 +191,11 @@ export default class ProposeConfig extends SolanaCommand { oracles, f, offchainConfig, - proposalId: this.flags.proposalId || this.flags.configProposal, } } constructor(flags, args) { super(flags, args) - this.require( - !!this.flags.proposalId || !!this.flags.configProposal, - 'Please provide Config Proposal ID with flag "proposalId" or "configProposal"', - ) this.requireArgs('Please provide an aggregator address') this.require( // TODO: should be able to just rely on random secret? @@ -220,15 +213,38 @@ export default class ProposeConfig extends SolanaCommand { } makeRawTransaction = async (signer: PublicKey) => { - const proposal = new PublicKey(this.input.proposalId) + const proposal = Keypair.generate() + this.proposal = proposal + + // createProposal + const version = new BN(2) + + logger.log('Generating data for creating config proposal') + logger.log('Config Proposal state will be at:', proposal.toString()) + + const createIx = await this.program.methods + .createProposal(version) + .accounts({ + proposal: proposal.publicKey, + authority: signer, + }) + .instruction() + const defaultAccountSize = new BN(this.program.account.proposal.size) + const createAccountIx = SystemProgram.createAccount({ + fromPubkey: signer, + newAccountPubkey: proposal.publicKey, + space: defaultAccountSize.toNumber(), + lamports: await this.provider.connection.getMinimumBalanceForRentExemption(defaultAccountSize.toNumber()), + programId: this.program.programId, + }) + + // proposeConfig const oracles = this.input.oracles.map(({ signer, transmitter }) => ({ signer: Buffer.from(signer, 'hex'), transmitter: new PublicKey(transmitter), })) - // proposeConfig - const f = new BN(this.input.f) const minOracleLength = f.mul(new BN(3)).toNumber() @@ -241,7 +257,7 @@ export default class ProposeConfig extends SolanaCommand { const configIx = await this.program.methods .proposeConfig(oracles, f) .accounts({ - proposal, + proposal: proposal.publicKey, authority: signer, }) .instruction() @@ -259,7 +275,7 @@ export default class ProposeConfig extends SolanaCommand { const payeesIx = await this.program.methods .proposePayees(link) .accounts({ - proposal, + proposal: proposal.publicKey, authority: signer, }) .remainingAccounts(payees) @@ -295,7 +311,7 @@ export default class ProposeConfig extends SolanaCommand { this.program.methods .writeOffchainConfig(buffer) .accounts({ - proposal: proposal, + proposal: proposal.publicKey, authority: signer, }) .instruction(), @@ -305,12 +321,12 @@ export default class ProposeConfig extends SolanaCommand { const finalizeIx = await this.program.methods .finalizeProposal() .accounts({ - proposal: proposal, + proposal: proposal.publicKey, authority: signer, }) .instruction() - return [configIx, payeesIx, ...offchainConfigIxs, finalizeIx] + return [createAccountIx, createIx, configIx, payeesIx, ...offchainConfigIxs, finalizeIx] } beforeExecute = async () => { @@ -382,10 +398,15 @@ export default class ProposeConfig extends SolanaCommand { } const txhash = txs[txs.length - 1] logger.success(`Config proposal finalized on tx ${txhash}`) + logger.line() + logger.info('Use the Config Proposal ID in future proposal commands:') + logger.info(this.proposal.publicKey.toString()) + logger.line() return { data: { secret: this.randomSecret, + proposal: this.proposal.publicKey.toString(), }, responses: [ // TODO: map over responses diff --git a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/setup.dev.flow.ts b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/setup.dev.flow.ts index fdda5afa9..22d0eb1e7 100644 --- a/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/setup.dev.flow.ts +++ b/gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/setup.dev.flow.ts @@ -10,7 +10,6 @@ import DeployToken from '../token/deploy' import SetBilling from './setBilling' import CreateFeed from '../store/createFeed' import SetWriter from '../store/setWriter' -import CreateProposal from './proposal/createProposal' import ProposeConfig from './proposeConfig' import AcceptProposal from './proposal/acceptProposal' @@ -192,22 +191,16 @@ export default class SetupFlow extends FlowCommand { }, args: [FlowCommand.ID.contract(this.stepIds.OCR_2)], }, - { - id: this.stepIds.PROPOSAL, - name: 'Create Proposal', - command: CreateProposal, - }, { name: 'Propose Config', command: ProposeConfig, + id: this.stepIds.PROPOSAL, flags: { input: { oracles: configInput.oracles, f: configInput.f, offchainConfig: offchainConfigInput, - proposalId: this.getReportStepDataById(FlowCommand.ID.data(this.stepIds.PROPOSAL, 'proposal')), }, - proposalId: FlowCommand.ID.data(this.stepIds.PROPOSAL, 'proposal'), secret: randomSecret, }, args: [FlowCommand.ID.contract(this.stepIds.OCR_2)],