Skip to content

Commit aad9c00

Browse files
drozdziak1m30m
andauthored
Oracle: Make permissions account mandatory for all privileged instructions (#388)
* Return error on permission-less branch * Fix permissions error value, adjust PythSimulator and AccountSetup * Cargo.toml: bump to v2.25.0 for release * tests: Add a unit test for the permissions validation routine --------- Co-authored-by: Amin Moghaddam <[email protected]>
1 parent a43baa9 commit aad9c00

14 files changed

+375
-124
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

program/rust/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyth-oracle"
3-
version = "2.24.0"
3+
version = "2.25.0"
44
edition = "2021"
55
license = "Apache 2.0"
66
publish = false

program/rust/src/tests/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod test_add_product;
44
mod test_add_publisher;
55
mod test_aggregation;
66
mod test_c_code;
7+
mod test_check_valid_signable_account_or_permissioned_funding_account;
78
mod test_del_price;
89
mod test_del_product;
910
mod test_del_publisher;

program/rust/src/tests/pyth_simulator.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ impl PythSimulator {
179179
rent_epoch: Epoch::default(),
180180
};
181181

182-
// Add to both accounts to program test, now the program is deploy as upgradable
182+
// Add accounts to program test, now the program is deploy as upgradable
183183
program_test.add_account(program_key, program_account);
184184
program_test.add_account(programdata_key, programdata_account);
185185

@@ -193,7 +193,7 @@ impl PythSimulator {
193193
last_blockhash,
194194
programdata_id: programdata_key,
195195
upgrade_authority: upgrade_authority_keypair,
196-
genesis_keypair,
196+
genesis_keypair: copy_keypair(&genesis_keypair),
197197
};
198198

199199
// Transfer money to upgrade_authority so it can call the instructions
@@ -202,6 +202,20 @@ impl PythSimulator {
202202
.await
203203
.unwrap();
204204

205+
result
206+
.upd_permissions(
207+
UpdPermissionsArgs {
208+
header: OracleCommand::UpdPermissions.into(),
209+
master_authority: genesis_keypair.pubkey(),
210+
data_curation_authority: genesis_keypair.pubkey(),
211+
security_authority: genesis_keypair.pubkey(),
212+
},
213+
&copy_keypair(&result.upgrade_authority),
214+
)
215+
.await
216+
.unwrap();
217+
218+
205219
result
206220
}
207221

@@ -268,6 +282,7 @@ impl PythSimulator {
268282
vec![
269283
AccountMeta::new(self.genesis_keypair.pubkey(), true),
270284
AccountMeta::new(mapping_keypair.pubkey(), true),
285+
AccountMeta::new(self.get_permissions_pubkey(), false),
271286
],
272287
);
273288

@@ -296,6 +311,7 @@ impl PythSimulator {
296311
AccountMeta::new(self.genesis_keypair.pubkey(), true),
297312
AccountMeta::new(mapping_keypair.pubkey(), true),
298313
AccountMeta::new(product_keypair.pubkey(), true),
314+
AccountMeta::new(self.get_permissions_pubkey(), false),
299315
],
300316
);
301317

@@ -322,6 +338,7 @@ impl PythSimulator {
322338
AccountMeta::new(self.genesis_keypair.pubkey(), true),
323339
AccountMeta::new(mapping_keypair.pubkey(), true),
324340
AccountMeta::new(product_keypair.pubkey(), true),
341+
AccountMeta::new(self.get_permissions_pubkey(), false),
325342
],
326343
);
327344

@@ -356,6 +373,7 @@ impl PythSimulator {
356373
AccountMeta::new(self.genesis_keypair.pubkey(), true),
357374
AccountMeta::new(product_keypair.pubkey(), true),
358375
AccountMeta::new(price_keypair.pubkey(), true),
376+
AccountMeta::new(self.get_permissions_pubkey(), false),
359377
],
360378
);
361379

@@ -384,6 +402,7 @@ impl PythSimulator {
384402
vec![
385403
AccountMeta::new(self.genesis_keypair.pubkey(), true),
386404
AccountMeta::new(price_keypair.pubkey(), true),
405+
AccountMeta::new(self.get_permissions_pubkey(), false),
387406
],
388407
);
389408

@@ -458,6 +477,7 @@ impl PythSimulator {
458477
AccountMeta::new(self.genesis_keypair.pubkey(), true),
459478
AccountMeta::new(product_keypair.pubkey(), true),
460479
AccountMeta::new(price_keypair.pubkey(), true),
480+
AccountMeta::new(self.get_permissions_pubkey(), false),
461481
],
462482
);
463483

@@ -552,18 +572,6 @@ impl PythSimulator {
552572
.await
553573
.unwrap();
554574

555-
self.upd_permissions(
556-
UpdPermissionsArgs {
557-
header: OracleCommand::UpdPermissions.into(),
558-
master_authority: self.upgrade_authority.pubkey(),
559-
data_curation_authority: self.upgrade_authority.pubkey(),
560-
security_authority,
561-
},
562-
&copy_keypair(&self.upgrade_authority),
563-
)
564-
.await
565-
.unwrap();
566-
567575
let product_metadatas: HashMap<String, ProductMetadata> =
568576
serde_json::from_reader(&result_file).unwrap();
569577

program/rust/src/tests/test_add_price.rs

+35-27
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use {
33
accounts::{
44
clear_account,
55
MappingAccount,
6+
PermissionAccount,
67
PriceAccount,
78
ProductAccount,
89
PythAccount,
@@ -53,17 +54,29 @@ fn test_add_price() {
5354
let product_account = product_setup.as_account_info();
5455

5556
let mut price_setup = AccountSetup::new::<PriceAccount>(&program_id);
56-
let mut price_account = price_setup.as_account_info();
57+
let price_account = price_setup.as_account_info();
5758

5859
let mut price_setup_2 = AccountSetup::new::<PriceAccount>(&program_id);
5960
let price_account_2 = price_setup_2.as_account_info();
6061

62+
let mut permissions_setup = AccountSetup::new_permission(&program_id);
63+
let permissions_account = permissions_setup.as_account_info();
64+
65+
{
66+
let mut permissions_account_data =
67+
PermissionAccount::initialize(&permissions_account, PC_VERSION).unwrap();
68+
permissions_account_data.master_authority = *funding_account.key;
69+
permissions_account_data.data_curation_authority = *funding_account.key;
70+
permissions_account_data.security_authority = *funding_account.key;
71+
}
72+
6173
assert!(process_instruction(
6274
&program_id,
6375
&[
6476
funding_account.clone(),
6577
mapping_account.clone(),
66-
product_account.clone()
78+
product_account.clone(),
79+
permissions_account.clone(),
6780
],
6881
instruction_data_add_product
6982
)
@@ -74,7 +87,8 @@ fn test_add_price() {
7487
&[
7588
funding_account.clone(),
7689
product_account.clone(),
77-
price_account.clone()
90+
price_account.clone(),
91+
permissions_account.clone(),
7892
],
7993
instruction_data_add_price
8094
)
@@ -96,7 +110,8 @@ fn test_add_price() {
96110
&[
97111
funding_account.clone(),
98112
product_account.clone(),
99-
price_account_2.clone()
113+
price_account_2.clone(),
114+
permissions_account.clone(),
100115
],
101116
instruction_data_add_price
102117
)
@@ -117,7 +132,13 @@ fn test_add_price() {
117132
assert_eq!(
118133
process_instruction(
119134
&program_id,
120-
&[funding_account.clone(), product_account.clone()],
135+
&[
136+
funding_account.clone(),
137+
product_account.clone(),
138+
price_account.clone(),
139+
permissions_account.clone(),
140+
permissions_account.clone(),
141+
],
121142
instruction_data_add_price
122143
),
123144
Err(OracleError::InvalidNumberOfAccounts.into())
@@ -130,7 +151,8 @@ fn test_add_price() {
130151
&[
131152
funding_account.clone(),
132153
product_account.clone(),
133-
price_account.clone()
154+
price_account.clone(),
155+
permissions_account.clone(),
134156
],
135157
instruction_data_add_price
136158
),
@@ -153,47 +175,33 @@ fn test_add_price() {
153175
&[
154176
funding_account.clone(),
155177
product_account.clone(),
156-
price_account.clone()
178+
price_account.clone(),
179+
permissions_account.clone(),
157180
],
158181
instruction_data_add_price
159182
),
160183
Err(ProgramError::InvalidArgument)
161184
);
162185

163-
// Price not signing
186+
// Fresh product account
187+
clear_account(&product_account).unwrap();
188+
164189
hdr_add_price = AddPriceArgs {
165190
header: OracleCommand::AddPrice.into(),
166191
exponent: 6,
167192
price_type: 1,
168193
};
169194

170195
instruction_data_add_price = bytes_of::<AddPriceArgs>(&hdr_add_price);
171-
price_account.is_signer = false;
172-
173-
assert_eq!(
174-
process_instruction(
175-
&program_id,
176-
&[
177-
funding_account.clone(),
178-
product_account.clone(),
179-
price_account.clone()
180-
],
181-
instruction_data_add_price
182-
),
183-
Err(OracleError::InvalidSignableAccount.into())
184-
);
185-
186-
// Fresh product account
187-
price_account.is_signer = true;
188-
clear_account(&product_account).unwrap();
189196

190197
assert_eq!(
191198
process_instruction(
192199
&program_id,
193200
&[
194201
funding_account.clone(),
195202
product_account.clone(),
196-
price_account.clone()
203+
price_account.clone(),
204+
permissions_account.clone(),
197205
],
198206
instruction_data_add_price
199207
),

program/rust/src/tests/test_add_product.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use {
55
clear_account,
66
create_pc_str_t,
77
MappingAccount,
8+
PermissionAccount,
89
ProductAccount,
910
PythAccount,
1011
},
@@ -57,13 +58,25 @@ fn test_add_product() {
5758
let mut product_setup_2 = AccountSetup::new::<ProductAccount>(&program_id);
5859
let product_account_2 = product_setup_2.as_account_info();
5960

61+
let mut permissions_setup = AccountSetup::new_permission(&program_id);
62+
let permissions_account = permissions_setup.as_account_info();
63+
64+
{
65+
let mut permissions_account_data =
66+
PermissionAccount::initialize(&permissions_account, PC_VERSION).unwrap();
67+
permissions_account_data.master_authority = *funding_account.key;
68+
permissions_account_data.data_curation_authority = *funding_account.key;
69+
permissions_account_data.security_authority = *funding_account.key;
70+
}
71+
6072
let mut size = populate_instruction(&mut instruction_data, &[]);
6173
assert!(process_instruction(
6274
&program_id,
6375
&[
6476
funding_account.clone(),
6577
mapping_account.clone(),
66-
product_account.clone()
78+
product_account.clone(),
79+
permissions_account.clone()
6780
],
6881
&instruction_data[..size]
6982
)
@@ -93,7 +106,8 @@ fn test_add_product() {
93106
&[
94107
funding_account.clone(),
95108
mapping_account.clone(),
96-
product_account_2.clone()
109+
product_account_2.clone(),
110+
permissions_account.clone()
97111
],
98112
&instruction_data[..size]
99113
)
@@ -131,7 +145,8 @@ fn test_add_product() {
131145
&[
132146
funding_account.clone(),
133147
mapping_account.clone(),
134-
product_account_3.clone()
148+
product_account_3.clone(),
149+
permissions_account.clone()
135150
],
136151
&instruction_data[..size]
137152
),
@@ -151,7 +166,8 @@ fn test_add_product() {
151166
&[
152167
funding_account.clone(),
153168
mapping_account.clone(),
154-
product_account.clone()
169+
product_account.clone(),
170+
permissions_account.clone()
155171
],
156172
&instruction_data[..size]
157173
)
@@ -173,7 +189,8 @@ fn test_add_product() {
173189
&[
174190
funding_account.clone(),
175191
mapping_account.clone(),
176-
product_account.clone()
192+
product_account.clone(),
193+
permissions_account.clone()
177194
],
178195
&instruction_data[..size]
179196
),

0 commit comments

Comments
 (0)