Skip to content

Commit d58eb95

Browse files
authored
refactor: use requires macros instead of if-else for validations (#129)
1 parent a2c0490 commit d58eb95

File tree

4 files changed

+202
-14
lines changed

4 files changed

+202
-14
lines changed

src/diff/algorithm.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use super::{
1010
SIZE_OF_SINGLE_OFFSET_PAIR,
1111
};
1212

13+
use crate::{require_eq, require_le};
14+
1315
///
1416
/// Compute diff between original and changed.
1517
///
@@ -258,18 +260,18 @@ pub fn merge_diff_copy<'a>(
258260
original: &[u8],
259261
diffset: &DiffSet<'_>,
260262
) -> Result<&'a mut [u8], ProgramError> {
261-
if destination.len() != diffset.changed_len() {
262-
return Err(DlpError::MergeDiffError.into());
263-
}
263+
require_eq!(
264+
destination.len(),
265+
diffset.changed_len(),
266+
DlpError::MergeDiffError
267+
);
264268

265269
let mut write_index = 0;
266270
for item in diffset.iter() {
267271
let (diff_segment, OffsetInData { start, end }) = item?;
268272

269273
if write_index < start {
270-
if start > original.len() {
271-
return Err(DlpError::InvalidDiff.into());
272-
}
274+
require_le!(start, original.len(), DlpError::InvalidDiff);
273275
// copy the unchanged bytes
274276
destination[write_index..start].copy_from_slice(&original[write_index..start]);
275277
}

src/error.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,86 +7,130 @@ use thiserror::Error;
77
pub enum DlpError {
88
#[error("Invalid Authority")]
99
InvalidAuthority = 0,
10+
1011
#[error("Account cannot be undelegated, is_undelegatable is false")]
1112
NotUndelegatable = 1,
13+
1214
#[error("Unauthorized Operation")]
1315
Unauthorized = 2,
16+
1417
#[error("Invalid Authority for the current target program")]
1518
InvalidAuthorityForProgram = 3,
19+
1620
#[error("Delegated account does not match the expected account")]
1721
InvalidDelegatedAccount = 4,
22+
1823
#[error("Delegated account is not in a valid state")]
1924
InvalidDelegatedState = 5,
25+
2026
#[error("Reimbursement account does not match the expected account")]
2127
InvalidReimbursementAccount = 6,
28+
2229
#[error("Invalid account data after CPI")]
2330
InvalidAccountDataAfterCPI = 7,
31+
2432
#[error("Invalid validator balance after CPI")]
2533
InvalidValidatorBalanceAfterCPI = 8,
34+
2635
#[error("Invalid reimbursement address for delegation rent")]
2736
InvalidReimbursementAddressForDelegationRent = 9,
37+
2838
#[error("Authority is invalid for the delegated account program owner")]
2939
InvalidWhitelistProgramConfig = 10,
40+
3041
#[error("Account already undelegated")]
3142
AlreadyUndelegated = 11,
43+
3244
#[error("Commit is out of order")]
3345
NonceOutOfOrder = 12,
46+
3447
#[error("Computation overflow detected")]
3548
Overflow = 13,
49+
3650
#[error("Too many seeds")]
3751
TooManySeeds = 14,
52+
3853
#[error("Invalid length of diff passed to DiffSet::try_new")]
3954
InvalidDiff = 15,
55+
4056
#[error("Diff is not properly aligned")]
4157
InvalidDiffAlignment = 16,
58+
4259
#[error("MergeDiff precondition did not meet")]
4360
MergeDiffError = 17,
61+
4462
#[error("Commit state PDA invalid seeds")]
4563
CommitStateInvalidSeeds = 18,
64+
4665
#[error("Commit state PDA invalid account owner")]
4766
CommitStateInvalidAccountOwner = 19,
67+
4868
#[error("Commit state PDA is already initialized")]
4969
CommitStateAlreadyInitialized = 20,
70+
5071
#[error("Commit state PDA immutable")]
5172
CommitStateImmutable = 21,
73+
5274
#[error("Commit record PDA invalid seeds")]
5375
CommitRecordInvalidSeeds = 22,
76+
5477
#[error("Commit record PDA invalid account owner")]
5578
CommitRecordInvalidAccountOwner = 23,
79+
5680
#[error("Commit record PDA is already initialized")]
5781
CommitRecordAlreadyInitialized = 24,
82+
5883
#[error("Commit record PDA immutable")]
5984
CommitRecordImmutable = 25,
85+
6086
#[error("Delegation record PDA invalid seeds")]
6187
DelegationRecordInvalidSeeds = 26,
88+
6289
#[error("Delegation record PDA invalid account owner")]
6390
DelegationRecordInvalidAccountOwner = 27,
91+
6492
#[error("Delegation record PDA is already initialized")]
6593
DelegationRecordAlreadyInitialized = 28,
94+
6695
#[error("Delegation record PDA immutable")]
6796
DelegationRecordImmutable = 29,
97+
6898
#[error("Delegation metadata PDA invalid seeds")]
6999
DelegationMetadataInvalidSeeds = 30,
100+
70101
#[error("Delegation metadata PDA invalid account owner")]
71102
DelegationMetadataInvalidAccountOwner = 31,
103+
72104
#[error("Delegation metadata PDA is already initialized")]
73105
DelegationMetadataAlreadyInitialized = 32,
106+
74107
#[error("Delegation metadata PDA immutable")]
75108
DelegationMetadataImmutable = 33,
109+
76110
#[error("Undelegate buffer PDA invalid seeds")]
77111
UndelegateBufferInvalidSeeds = 34,
112+
78113
#[error("Undelegate buffer PDA invalid account owner")]
79114
UndelegateBufferInvalidAccountOwner = 35,
115+
80116
#[error("Undelegate buffer PDA is already initialized")]
81117
UndelegateBufferAlreadyInitialized = 36,
118+
82119
#[error("Undelegate buffer PDA immutable")]
83120
UndelegateBufferImmutable = 37,
121+
84122
#[error("Invalid data length for deserialization")]
85123
InvalidDataLength = 38,
124+
86125
#[error("Invalid discriminator for delegation record")]
87126
InvalidDiscriminator = 39,
127+
88128
#[error("Invalid delegation record deserialization")]
89129
InvalidDelegationRecordData = 40,
130+
131+
#[error("Too many account keys passed to the instruction")]
132+
TooManyAccountKeys = 41,
133+
90134
#[error("An infallible error is encountered possibly due to logic error")]
91135
InfallibleError = 100,
92136
}

src/processor/fast/commit_diff.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use crate::DiffSet;
1010

1111
use super::NewState;
1212

13+
use crate::{require, require_n_accounts};
14+
1315
/// Commit diff to a delegated PDA
1416
///
1517
/// Accounts:
@@ -47,15 +49,22 @@ pub fn process_commit_diff(
4749
accounts: &[AccountInfo],
4850
data: &[u8],
4951
) -> ProgramResult {
50-
let [validator, delegated_account, commit_state_account, commit_record_account, delegation_record_account, delegation_metadata_account, validator_fees_vault, program_config_account, _system_program] =
51-
accounts
52-
else {
53-
return Err(ProgramError::NotEnoughAccountKeys);
54-
};
52+
let [
53+
validator, // force multi-line
54+
delegated_account,
55+
commit_state_account,
56+
commit_record_account,
57+
delegation_record_account,
58+
delegation_metadata_account,
59+
validator_fees_vault,
60+
program_config_account,
61+
_system_program,
62+
] = require_n_accounts!(accounts, 9);
5563

56-
if data.len() < SIZE_COMMIT_DIFF_ARGS_WITHOUT_DIFF {
57-
return Err(ProgramError::InvalidInstructionData);
58-
}
64+
require!(
65+
data.len() >= SIZE_COMMIT_DIFF_ARGS_WITHOUT_DIFF,
66+
ProgramError::InvalidInstructionData
67+
);
5968

6069
let (diff, data) = data.split_at(data.len() - SIZE_COMMIT_DIFF_ARGS_WITHOUT_DIFF);
6170

src/processor/fast/utils/requires.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,139 @@ mod pubkey {
2727
}
2828
}
2929

30+
// require true
31+
#[macro_export]
32+
macro_rules! require {
33+
($cond:expr, $error:expr) => {{
34+
if !$cond {
35+
let expr = stringify!($cond);
36+
pinocchio_log::log!("require!({}) failed.", expr);
37+
return Err($error.into());
38+
}
39+
}};
40+
}
41+
42+
// require key1 == key2
43+
#[macro_export]
44+
macro_rules! require_eq_keys {
45+
( $key1:expr, $key2:expr, $error:expr) => {{
46+
if !pinocchio::pubkey::pubkey_eq($key1, $key2) {
47+
pinocchio_log::log!(
48+
"require_eq_keys!({}, {}) failed: ",
49+
stringify!($key1),
50+
stringify!($key2)
51+
);
52+
pinocchio::pubkey::log($key1);
53+
pinocchio::pubkey::log($key2);
54+
return Err($error.into());
55+
}
56+
}};
57+
}
58+
59+
// require a == b
60+
#[macro_export]
61+
macro_rules! require_eq {
62+
( $val1:expr, $val2:expr, $error:expr) => {{
63+
if !($val1 == $val2) {
64+
pinocchio_log::log!(
65+
"require_eq!({}, {}) failed: {} == {}",
66+
stringify!($val1),
67+
stringify!($val2),
68+
$val1,
69+
$val2
70+
);
71+
return Err($error.into());
72+
}
73+
}};
74+
}
75+
76+
// require a <= b
77+
#[macro_export]
78+
macro_rules! require_le {
79+
( $val1:expr, $val2:expr, $error:expr) => {{
80+
if !($val1 <= $val2) {
81+
pinocchio_log::log!(
82+
"require_le!({}, {}) failed: {} <= {}",
83+
stringify!($val1),
84+
stringify!($val2),
85+
$val1,
86+
$val2
87+
);
88+
return Err($error.into());
89+
}
90+
}};
91+
}
92+
93+
// require a < b
94+
#[macro_export]
95+
macro_rules! require_lt {
96+
( $val1:expr, $val2:expr, $error:expr) => {{
97+
if !($val1 < $val2) {
98+
pinocchio_log::log!(
99+
"require_lt!({}, {}) failed: {} < {}",
100+
stringify!($val1),
101+
stringify!($val2),
102+
$val1,
103+
$val2
104+
);
105+
return Err($error.into());
106+
}
107+
}};
108+
}
109+
110+
// require a >= b
111+
#[macro_export]
112+
macro_rules! require_ge {
113+
( $val1:expr, $val2:expr, $error:expr) => {{
114+
if !($val1 >= $val2) {
115+
pinocchio_log::log!(
116+
"require_ge!({}, {}) failed: {} >= {}",
117+
stringify!($val1),
118+
stringify!($val2),
119+
$val1,
120+
$val2
121+
);
122+
return Err($error.into());
123+
}
124+
}};
125+
}
126+
127+
#[macro_export]
128+
macro_rules! require_n_accounts {
129+
( $accounts:expr, $n:literal) => {{
130+
match $accounts.len().cmp(&$n) {
131+
core::cmp::Ordering::Less => {
132+
pinocchio_log::log!(
133+
"Need {} accounts, but got less ({}) accounts",
134+
$n,
135+
$accounts.len()
136+
);
137+
return Err(pinocchio::program_error::ProgramError::NotEnoughAccountKeys);
138+
}
139+
core::cmp::Ordering::Equal => TryInto::<&[_; $n]>::try_into($accounts)
140+
.map_err(|_| $crate::error::DlpError::InfallibleError)?,
141+
core::cmp::Ordering::Greater => {
142+
pinocchio_log::log!(
143+
"Need {} accounts, but got more ({}) accounts",
144+
$n,
145+
$accounts.len()
146+
);
147+
return Err($crate::error::DlpError::TooManyAccountKeys.into());
148+
}
149+
}
150+
}};
151+
}
152+
153+
#[macro_export]
154+
macro_rules! require_some {
155+
($option:expr, $error:expr) => {{
156+
match $option {
157+
Some(val) => val,
158+
None => return Err($error.into()),
159+
}
160+
}};
161+
}
162+
30163
/// Errors if:
31164
/// - Account is not owned by expected program.
32165
#[inline(always)]

0 commit comments

Comments
 (0)