Skip to content

Commit de2986e

Browse files
revision
1 parent 5bdc49e commit de2986e

6 files changed

Lines changed: 70 additions & 69 deletions

File tree

smartcontract/cli/src/permission/flags.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl PermissionName {
4242
}
4343
}
4444

45-
pub fn as_str(self) -> &'static str {
45+
fn as_static_str(self) -> &'static str {
4646
match self {
4747
Self::Foundation => "foundation",
4848
Self::PermissionAdmin => "permission-admin",
@@ -63,6 +63,12 @@ impl PermissionName {
6363
}
6464
}
6565

66+
impl std::fmt::Display for PermissionName {
67+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68+
f.write_str(self.as_static_str())
69+
}
70+
}
71+
6672
impl ValueEnum for PermissionName {
6773
fn value_variants<'a>() -> &'a [Self] {
6874
&[
@@ -85,7 +91,7 @@ impl ValueEnum for PermissionName {
8591
}
8692

8793
fn to_possible_value(&self) -> Option<PossibleValue> {
88-
Some(PossibleValue::new(self.as_str()))
94+
Some(PossibleValue::new(self.as_static_str()))
8995
}
9096
}
9197

smartcontract/cli/src/permission/set.rs

Lines changed: 41 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,19 @@ impl SetPermissionCliCommand {
6161
})?;
6262
(sig, permissions)
6363
}
64-
Some((_, current)) => {
65-
// Account exists — apply incremental delta.
66-
let add_mask = names_to_bitmask(&self.add);
67-
let remove_mask = names_to_bitmask(&self.remove);
68-
let new_permissions = (current.permissions | add_mask) & !remove_mask;
69-
70-
if new_permissions == 0 {
71-
return Err(eyre::eyre!(
72-
"resulting permissions bitmask is zero — at least one permission is required"
73-
));
74-
}
75-
64+
Some(_) => {
65+
// Account exists — apply incremental delta atomically via the program.
66+
let add = names_to_bitmask(&self.add);
67+
let remove = names_to_bitmask(&self.remove);
7668
let sig = client.update_permission(UpdatePermissionCommand {
7769
permission_pda,
78-
permissions: new_permissions,
70+
add,
71+
remove,
72+
})?;
73+
let (_, updated) = client.get_permission(GetPermissionCommand {
74+
pubkey: permission_pda.to_string(),
7975
})?;
80-
(sig, new_permissions)
76+
(sig, updated.permissions)
8177
}
8278
};
8379

@@ -205,7 +201,7 @@ mod tests {
205201
let (permission_pda, _) = get_permission_pda(&TEST_PROGRAM_ID, &user_payer);
206202

207203
let initial = permission_flags::NETWORK_ADMIN;
208-
let expected = initial | permission_flags::SENTINEL;
204+
let updated = initial | permission_flags::SENTINEL;
209205

210206
client
211207
.expect_check_requirements()
@@ -216,14 +212,23 @@ mod tests {
216212
.with(predicate::eq(GetPermissionCommand {
217213
pubkey: permission_pda.to_string(),
218214
}))
215+
.once()
219216
.returning(move |_| Ok((permission_pda, make_permission(initial))));
220217
client
221218
.expect_update_permission()
222219
.with(predicate::eq(UpdatePermissionCommand {
223220
permission_pda,
224-
permissions: expected,
221+
add: permission_flags::SENTINEL,
222+
remove: 0,
225223
}))
226224
.returning(|_| Ok(Signature::new_unique()));
225+
client
226+
.expect_get_permission()
227+
.with(predicate::eq(GetPermissionCommand {
228+
pubkey: permission_pda.to_string(),
229+
}))
230+
.once()
231+
.returning(move |_| Ok((permission_pda, make_permission(updated))));
227232

228233
let mut output = Vec::new();
229234
let res = SetPermissionCliCommand {
@@ -246,7 +251,7 @@ mod tests {
246251
let (permission_pda, _) = get_permission_pda(&TEST_PROGRAM_ID, &user_payer);
247252

248253
let initial = permission_flags::NETWORK_ADMIN | permission_flags::USER_ADMIN;
249-
let expected = permission_flags::NETWORK_ADMIN;
254+
let updated = permission_flags::NETWORK_ADMIN;
250255

251256
client
252257
.expect_check_requirements()
@@ -257,14 +262,23 @@ mod tests {
257262
.with(predicate::eq(GetPermissionCommand {
258263
pubkey: permission_pda.to_string(),
259264
}))
265+
.once()
260266
.returning(move |_| Ok((permission_pda, make_permission(initial))));
261267
client
262268
.expect_update_permission()
263269
.with(predicate::eq(UpdatePermissionCommand {
264270
permission_pda,
265-
permissions: expected,
271+
add: 0,
272+
remove: permission_flags::USER_ADMIN,
266273
}))
267274
.returning(|_| Ok(Signature::new_unique()));
275+
client
276+
.expect_get_permission()
277+
.with(predicate::eq(GetPermissionCommand {
278+
pubkey: permission_pda.to_string(),
279+
}))
280+
.once()
281+
.returning(move |_| Ok((permission_pda, make_permission(updated))));
268282

269283
let mut output = Vec::new();
270284
let res = SetPermissionCliCommand {
@@ -287,7 +301,7 @@ mod tests {
287301
let (permission_pda, _) = get_permission_pda(&TEST_PROGRAM_ID, &user_payer);
288302

289303
let initial = permission_flags::NETWORK_ADMIN | permission_flags::USER_ADMIN;
290-
let expected = permission_flags::NETWORK_ADMIN | permission_flags::SENTINEL;
304+
let updated = permission_flags::NETWORK_ADMIN | permission_flags::SENTINEL;
291305

292306
client
293307
.expect_check_requirements()
@@ -298,61 +312,33 @@ mod tests {
298312
.with(predicate::eq(GetPermissionCommand {
299313
pubkey: permission_pda.to_string(),
300314
}))
315+
.once()
301316
.returning(move |_| Ok((permission_pda, make_permission(initial))));
302317
client
303318
.expect_update_permission()
304319
.with(predicate::eq(UpdatePermissionCommand {
305320
permission_pda,
306-
permissions: expected,
321+
add: permission_flags::SENTINEL,
322+
remove: permission_flags::USER_ADMIN,
307323
}))
308324
.returning(|_| Ok(Signature::new_unique()));
309-
310-
let mut output = Vec::new();
311-
let res = SetPermissionCliCommand {
312-
user_payer: user_payer.to_string(),
313-
add: vec![PermissionName::Sentinel],
314-
remove: vec![PermissionName::UserAdmin],
315-
}
316-
.execute(&client, &mut output);
317-
318-
assert!(res.is_ok());
319-
}
320-
321-
#[test]
322-
fn test_set_remove_all_rejected() {
323-
let mut client = create_test_client();
324-
let user_payer = Pubkey::new_unique();
325-
let (permission_pda, _) = get_permission_pda(&TEST_PROGRAM_ID, &user_payer);
326-
327-
client
328-
.expect_check_requirements()
329-
.with(predicate::eq(CHECK_ID_JSON | CHECK_BALANCE))
330-
.returning(|_| Ok(()));
331325
client
332326
.expect_get_permission()
333327
.with(predicate::eq(GetPermissionCommand {
334328
pubkey: permission_pda.to_string(),
335329
}))
336-
.returning(move |_| {
337-
Ok((
338-
permission_pda,
339-
make_permission(permission_flags::NETWORK_ADMIN),
340-
))
341-
});
330+
.once()
331+
.returning(move |_| Ok((permission_pda, make_permission(updated))));
342332

343333
let mut output = Vec::new();
344334
let res = SetPermissionCliCommand {
345335
user_payer: user_payer.to_string(),
346-
add: vec![],
347-
remove: vec![PermissionName::NetworkAdmin],
336+
add: vec![PermissionName::Sentinel],
337+
remove: vec![PermissionName::UserAdmin],
348338
}
349339
.execute(&client, &mut output);
350340

351-
assert!(res.is_err());
352-
assert!(res
353-
.unwrap_err()
354-
.to_string()
355-
.contains("resulting permissions bitmask is zero"));
341+
assert!(res.is_ok());
356342
}
357343

358344
#[test]

smartcontract/programs/doublezero-serviceability/src/instructions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1272,7 +1272,8 @@ mod tests {
12721272
);
12731273
test_instruction(
12741274
DoubleZeroInstruction::UpdatePermission(PermissionUpdateArgs {
1275-
permissions: permission_flags::FOUNDATION,
1275+
add: permission_flags::FOUNDATION,
1276+
remove: 0,
12761277
}),
12771278
"UpdatePermission",
12781279
);

smartcontract/programs/doublezero-serviceability/src/processors/permission/update.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ use solana_program::{
2020

2121
#[derive(BorshSerialize, BorshDeserializeIncremental, PartialEq, Clone, Default)]
2222
pub struct PermissionUpdateArgs {
23-
/// New permissions bitmask to replace the existing one.
24-
pub permissions: u128,
23+
/// Bits to add to the existing permissions bitmask.
24+
pub add: u128,
25+
/// Bits to remove from the existing permissions bitmask.
26+
pub remove: u128,
2527
}
2628

2729
impl fmt::Debug for PermissionUpdateArgs {
2830
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29-
write!(f, "permissions: {}", self.permissions)
31+
write!(f, "add: {}, remove: {}", self.add, self.remove)
3032
}
3133
}
3234

@@ -63,7 +65,8 @@ pub fn process_update_permission(
6365
return Err(ProgramError::InvalidArgument);
6466
}
6567

66-
if value.permissions == 0 {
68+
let new_permissions = (permission.permissions | value.add) & !value.remove;
69+
if new_permissions == 0 {
6770
return Err(DoubleZeroError::InvalidArgument.into());
6871
}
6972

@@ -76,7 +79,7 @@ pub fn process_update_permission(
7679
permission_flags::PERMISSION_ADMIN,
7780
)?;
7881

79-
permission.permissions = value.permissions;
82+
permission.permissions = new_permissions;
8083
try_acc_write(&permission, permission_account, payer_account, accounts)?;
8184

8285
Ok(())

smartcontract/programs/doublezero-serviceability/tests/permission_test.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ async fn test_permission_crud() {
7272
recent_blockhash,
7373
program_id,
7474
DoubleZeroInstruction::UpdatePermission(PermissionUpdateArgs {
75-
permissions: permission_flags::USER_ADMIN | permission_flags::NETWORK_ADMIN,
75+
add: permission_flags::NETWORK_ADMIN,
76+
remove: 0,
7677
}),
7778
vec![
7879
AccountMeta::new(permission_pda, false),

smartcontract/sdk/rs/src/commands/permission/update.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use solana_sdk::{instruction::AccountMeta, pubkey::Pubkey, signature::Signature}
88
#[derive(Debug, PartialEq, Clone)]
99
pub struct UpdatePermissionCommand {
1010
pub permission_pda: Pubkey,
11-
pub permissions: u128,
11+
pub add: u128,
12+
pub remove: u128,
1213
}
1314

1415
impl UpdatePermissionCommand {
@@ -17,7 +18,8 @@ impl UpdatePermissionCommand {
1718

1819
client.execute_transaction(
1920
DoubleZeroInstruction::UpdatePermission(PermissionUpdateArgs {
20-
permissions: self.permissions,
21+
add: self.add,
22+
remove: self.remove,
2123
}),
2224
vec![
2325
AccountMeta::new(self.permission_pda, false),
@@ -46,15 +48,16 @@ mod tests {
4648
let mut client = create_test_client();
4749

4850
let user_payer = Pubkey::new_unique();
49-
let permissions: u128 = 0b111;
51+
let add: u128 = 0b110;
52+
let remove: u128 = 0b001;
5053
let (globalstate_pubkey, _) = get_globalstate_pda(&client.get_program_id());
5154
let (permission_pda, _) = get_permission_pda(&client.get_program_id(), &user_payer);
5255

5356
client
5457
.expect_execute_transaction()
5558
.with(
5659
predicate::eq(DoubleZeroInstruction::UpdatePermission(
57-
PermissionUpdateArgs { permissions },
60+
PermissionUpdateArgs { add, remove },
5861
)),
5962
predicate::eq(vec![
6063
AccountMeta::new(permission_pda, false),
@@ -65,7 +68,8 @@ mod tests {
6568

6669
let res = UpdatePermissionCommand {
6770
permission_pda,
68-
permissions,
71+
add,
72+
remove,
6973
}
7074
.execute(&client);
7175

0 commit comments

Comments
 (0)