Skip to content

Commit c8c9618

Browse files
authored
Add inspection docs and allow ocr2:inspect to run without RDD flag (#296)
* Add solana program inspection docs * Add gauntlet inspect docs, add ability to run ocr2:inspect without rdd * Check if --input or --rdd exists in ocr2:inspect * Expect proper response from makeInputFromRDD * Add ocr2/types.ts, Add additional block explorers to docs * Allow makeInput to return undefined
1 parent 1e0bdfe commit c8c9618

File tree

3 files changed

+195
-14
lines changed

3 files changed

+195
-14
lines changed

docs/InspectingContracts.md

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Inspecting Solana Programs
2+
3+
Programs for Solana can be found in the [programs](/contracts/programs/) directory. Here, you can find source code for each of the Chainlink programs deployed on Solana.
4+
5+
- [Access Controller](/contracts/programs/access-controller/)
6+
- [OCR2](/contracts/programs/ocr2/)
7+
- [Store](/contracts/programs/store/)
8+
9+
## Via Gauntlet Inspect
10+
11+
Using Gaunlet, you can inspect the state of Chainlink programs on Solana.
12+
13+
### Inspect Ownership
14+
15+
Gauntlet offers an *inspect_ownership* command for each program. The following is a template for these commands, where PROGRAM_NAME is either ocr2 or access_controller and NETWORK_NAME corresponds to one of the networks defined in the [networks](/gauntlet/packages/gauntlet-solana-contracts/networks/) folder.
16+
17+
```bash
18+
yarn gauntlet [PROGRAM_NAME]:inspect_ownership --network=[NETWORK_NAME] [PROGRAM_ACCOUNT_ADDRESS]
19+
20+
e.g.
21+
yarn gauntlet ocr2:inspect_ownership --network=mainnet 2oyA8ZLwuWeAR5ANyDsiEGueUyDC8jFGFLSixSzT9KtV
22+
```
23+
24+
This command logs the owner and proposed owner (if defined) of the program account.
25+
26+
```bash
27+
🧤 gauntlet 0.1.2
28+
ℹ️ Loading Local wallet
29+
Operator address is H2ScWiFt1ZMRR1beYWB6Yr9cuADJ8sQhkGvYJxjJNAh8
30+
ℹ️ Checking owner of 2TQmhSnGK5NwdXBKEmJ8wfwH17rNSQgH11SVdHkYC1ZD
31+
ℹ️ Owner: 2CbCTf2V95kMfNA31yYaqJ9oVX7MN71RU6zvvg27PgSz
32+
ℹ️ Proposed Owner: 11111111111111111111111111111111
33+
✨ Done in 12.38s.
34+
```
35+
36+
### OCR2 Inspect
37+
38+
Using Gauntlet, you can query an OCR2 program to obtain information about its oracles and configuration. The following template is used for this command.
39+
40+
```bash
41+
yarn gauntlet ocr2:inspect --network=[NETWORK_NAME] [PROGRAM_ACCOUNT_ADDRESS]
42+
43+
e.g.
44+
yarn gauntlet ocr2:inspect --network=devnet 2TQmhSnGK5NwdXBKEmJ8wfwH17rNSQgH11SVdHkYC1ZD
45+
```
46+
47+
You can find an example response below.
48+
49+
```bash
50+
🧤 gauntlet 0.1.2
51+
ℹ️ Loading Local wallet
52+
Operator address is H2ScWiFt1ZMRR1beYWB6Yr9cuADJ8sQhkGvYJxjJNAh8
53+
ℹ️ Oracle Info:
54+
- Transmitter: 6s1wr4fv2GdTkcKxnXRdR429FYadX4mUVn9TMMhh3eMz
55+
- Proposed Payee: 11111111111111111111111111111111
56+
- From Round ID: 0
57+
- Payment Gjuels: 223296045
58+
59+
.
60+
.
61+
.
62+
63+
ℹ️ Oracle Info:
64+
- Transmitter: 7o1AzTiXbvhZH1UV6ZHA664h4hBFbPbFYdLfSnVprRKa
65+
- Proposed Payee: 11111111111111111111111111111111
66+
- From Round ID: 0
67+
- Payment Gjuels: 222637143
68+
69+
ℹ️ Min Answer: 1
70+
ℹ️ Max Answer: 100000000000000
71+
ℹ️ Transmission Payment: 1
72+
ℹ️ Observation Payment: 1
73+
ℹ️ Requester Access Controller: 5vkHdxPiTyfY5VdRpPu8tNTpeik6Cy93M6GzztMPWfAk
74+
ℹ️ Billing Access Controller: CBWXiwPGX6ykWtPGXp4cuFJP53SW81pe9q1YfUASWC46
75+
✨ Done in 12.61s.
76+
```
77+
78+
## Via Block Explorers
79+
80+
[Solana Explorer](https://explorer.solana.com/) allows users to search for deployed programs and read their state. On the home page, search the address of the program account that you want to inspect. For example, if you want to inspect the OCR2 program for the BTC/USD feed on mainnet, search *2oyA8ZLwuWeAR5ANyDsiEGueUyDC8jFGFLSixSzT9KtV*.
81+
82+
On the program account page, select the *Anchor Account* tab. In this tab, you will be able to inspect all of the data stored on the program in JSON format. In the case of an OCR2 program, this includes on-chain configuration and oracle information.
83+
84+
Other block explorers include:
85+
86+
- [Solscan](https://solscan.io/)
87+
- [Solana Beach](https://solanabeach.io/)
88+
89+
## Via cURL
90+
91+
You can also interact with deployed programs via cURL. Querying account info using cURL requires the following format.
92+
93+
```bash
94+
curl [RPC_URL] -X POST -H "Content-Type: application/json" -d '
95+
{
96+
"jsonrpc": "2.0",
97+
"id": 1,
98+
"method": "getAccountInfo",
99+
"params": [
100+
"ACCOUNT_ADDRESS",
101+
{
102+
"encoding": "base58"
103+
}
104+
]
105+
}
106+
'
107+
```
108+
109+
You may need to change the encoding if the data stored by your program is larger than 128 bytes. Here is the result of the above query.
110+
111+
```bash
112+
{
113+
"jsonrpc":"2.0",
114+
"result": {
115+
"context": {
116+
"slot":128841900
117+
},
118+
"value": {
119+
"data": ["BASE_58_STRING...","base58"],
120+
"executable":false,
121+
"lamports":49054080,
122+
"owner":"cjg3oHmg9uuPsP8D6g29NWvhySJkdYdAo9D25PRbKXJ",
123+
"rentEpoch":298
124+
}
125+
},
126+
"id":1
127+
}
128+
```
129+
130+
## Via Solana-CLI
131+
132+
Using [solana-cli](https://docs.solana.com/cli/install-solana-cli-tools) produces similar results to cURL. Run the following command to get information about a program account.
133+
134+
```bash
135+
solana account [ACCOUNT_ADDRESS]
136+
```
137+
138+
This command will dump information about the given account.
139+
140+
```bash
141+
Public Key: 2oyA8ZLwuWeAR5ANyDsiEGueUyDC8jFGFLSixSzT9KtV
142+
Balance: 0.04905408 SOL
143+
Owner: cjg3oHmg9uuPsP8D6g29NWvhySJkdYdAo9D25PRbKXJ
144+
Executable: false
145+
Rent Epoch: 298
146+
Length: 6920 (0x1b08) bytes
147+
0000: d8 92 6b 5e 68 4b b6 b1 01 f9 00 00 00 00 00 00 ..k^hK..........
148+
0010: a7 7a 9a 54 2d bb 05 64 37 03 f0 e4 90 be e4 d1 .z.T-..d7.......
149+
0020: bf 25 69 0f f1 2a 5d 82 52 57 16 71 f7 8a e3 40 .%i..*].RW.q...@
150+
.
151+
.
152+
.
153+
```

docs/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- **[Multisig](./multisig/)**: How to setup and use the multisig program.
88
-- **[Relay](./relay/)**: Details on the configuration options within a job spec.
99
- **[Running E2E Tests](./RunningE2eTests.md)**: How to run the E2E Tests
10+
- **[Inspecting Programs](./InspectingContracts.md)**: How to inspect programs on Solana
1011

1112
## Local initial setup
1213

gauntlet/packages/gauntlet-solana-contracts/src/commands/contracts/ocr2/inspection/inspect.ts

+41-14
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,18 @@ export default class OCR2Inspect extends SolanaCommand {
3434
'yarn gauntlet ocr2:inspect [AGGREGATOR_ADDRESS]',
3535
]
3636

37-
makeInput = (userInput): Input => {
37+
makeInput = (userInput): Input | undefined => {
3838
if (userInput) return userInput as Input
3939
const network = this.flags.network || ''
4040
const rddPath = this.flags.rdd || ''
4141
const billingAccessController = this.flags.billingAccessController || process.env.BILLING_ACCESS_CONTROLLER
4242
const requesterAccessController = this.flags.requesterAccessController || process.env.REQUESTER_ACCESS_CONTROLLER
4343

44+
// Return empty input if no rdd or user input provided
45+
if (!rddPath) {
46+
return undefined
47+
}
48+
4449
const rdd = RDD.load(network, rddPath)
4550
const aggregator = RDD.loadAggregator(this.args[0], network, rddPath)
4651
const aggregatorOperators: string[] = aggregator.oracles.map((o) => o.operator)
@@ -125,8 +130,6 @@ export default class OCR2Inspect extends SolanaCommand {
125130
const ocr2 = getContract(CONTRACT_LIST.OCR_2, '')
126131
const ocr2program = this.loadProgram(ocr2.idl, ocr2.programId.toString())
127132

128-
const input = this.makeInput(this.flags.input)
129-
130133
const state = new PublicKey(this.args[0])
131134
const onChainState = await ocr2program.account.state.fetch(state)
132135

@@ -136,6 +139,41 @@ export default class OCR2Inspect extends SolanaCommand {
136139
)
137140

138141
const onChainOCRConfig = deserializeConfig(bufferedConfig)
142+
143+
// Print on-chain oracle information
144+
onChainState.oracles.xs.forEach((oracle) => {
145+
logger.info(
146+
`Oracle Info:
147+
- Transmitter: ${oracle.transmitter}
148+
- Proposed Payee: ${oracle.proposedPayee}
149+
- From Round ID: ${oracle.fromRoundId}
150+
- Payment Gjuels: ${oracle.paymentGjuels}
151+
`,
152+
)
153+
})
154+
155+
const input = this.makeInput(this.flags.input)
156+
// If input does not exist, just print config
157+
if (!input) {
158+
logger.info(
159+
`On Chain Config
160+
- Min Answer: ${onChainState.config.minAnswer}
161+
- Max Answer: ${onChainState.config.maxAnswer}
162+
- Transmission Payment: ${onChainState.config.billing.transmissionPaymentGjuels}
163+
- Observation Payment: ${onChainState.config.billing.observationPaymentGjuels}
164+
- Requester Access Controller: ${onChainState.config.requesterAccessController}
165+
- Billing Access Controller: ${onChainState.config.billingAccessController}
166+
`,
167+
)
168+
return {
169+
responses: [
170+
{
171+
contract: state.toString(),
172+
},
173+
],
174+
} as Result<TransactionResponse>
175+
}
176+
139177
const wrappedComparableLongNumber = (v: any) => {
140178
// Proto encoding will ignore falsy values.
141179
if (!v) return '0'
@@ -243,17 +281,6 @@ export default class OCR2Inspect extends SolanaCommand {
243281
`Offchain Config "reportingPluginConfig.deltaCNanoseconds"`,
244282
),
245283
]
246-
// Print on-chain oracle information
247-
onChainState.oracles.xs.forEach((oracle) => {
248-
logger.info(
249-
`Oracle Info:
250-
- Transmitter: ${oracle.transmitter}
251-
- Proposed Payee: ${oracle.proposedPayee}
252-
- From Round ID: ${oracle.fromRoundId}
253-
- Payment Gjuels: ${oracle.paymentGjuels}
254-
`,
255-
)
256-
})
257284

258285
// Fetching tranmissions involves a tx. Give the option to the user to choose whether to fetch it or not.
259286
// Deactivated until we find a more efficient way to fetch this info

0 commit comments

Comments
 (0)