Skip to content

Commit 3f0e64e

Browse files
committed
solana: reduce timestamp calls
1 parent ead61ab commit 3f0e64e

File tree

3 files changed

+18
-18
lines changed

3 files changed

+18
-18
lines changed

solana/programs/example-native-token-transfers/src/instructions/redeem.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use anchor_spl::token_interface;
33

44
use crate::{
55
bitmap::Bitmap,
6-
clock::current_timestamp,
76
config::*,
87
error::NTTError,
98
messages::{ManagerMessage, NativeTokenTransfer, ValidatedEndpointMessage},
@@ -123,11 +122,11 @@ pub fn redeem(ctx: Context<Redeem>, _args: RedeemArgs) -> Result<()> {
123122
}
124123

125124
let release_timestamp = match accs.inbox_rate_limit.rate_limit.consume_or_delay(amount) {
126-
RateLimitResult::Consumed => {
125+
RateLimitResult::Consumed(now) => {
127126
// When receiving a transfer, we refill the outbound rate limit with
128127
// the same amount (we call this "backflow")
129-
accs.outbox_rate_limit.rate_limit.refill(amount);
130-
current_timestamp()
128+
accs.outbox_rate_limit.rate_limit.refill(now, amount);
129+
now
131130
}
132131
RateLimitResult::Delayed(release_timestamp) => release_timestamp,
133132
};

solana/programs/example-native-token-transfers/src/instructions/transfer.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use anchor_spl::token_interface;
44
use crate::{
55
bitmap::Bitmap,
66
chain_id::ChainId,
7-
clock::current_timestamp,
87
config::*,
98
error::NTTError,
109
normalized_amount::NormalizedAmount,
@@ -216,11 +215,11 @@ fn insert_into_outbox(
216215
) -> Result<()> {
217216
// consume the rate limit, or delay the transfer if it's outside the limit
218217
let release_timestamp = match common.outbox_rate_limit.rate_limit.consume_or_delay(amount) {
219-
RateLimitResult::Consumed => {
218+
RateLimitResult::Consumed(now) => {
220219
// When sending a transfer, we refill the inbound rate limit for
221220
// that chain the same amount (we call this "backflow")
222-
inbox_rate_limit.rate_limit.refill(amount);
223-
current_timestamp()
221+
inbox_rate_limit.rate_limit.refill(now, amount);
222+
now
224223
}
225224
RateLimitResult::Delayed(release_timestamp) => {
226225
if !should_queue {

solana/programs/example-native-token-transfers/src/queue/rate_limit.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct RateLimitState {
2222
pub enum RateLimitResult {
2323
/// If the rate limit is not exceeded, the transfer is immediate,
2424
/// and the capacity is reduced.
25-
Consumed,
25+
Consumed(UnixTimestamp),
2626
/// If the rate limit is exceeded, the transfer is delayed until the
2727
/// given timestamp.
2828
Delayed(UnixTimestamp),
@@ -81,21 +81,21 @@ impl RateLimitState {
8181
/// returned.
8282
pub fn consume_or_delay(&mut self, amount: u64) -> RateLimitResult {
8383
let now = current_timestamp();
84-
let capacity = self.capacity();
84+
let capacity = self.capacity_at(now);
8585
if capacity >= amount {
8686
self.capacity_at_last_tx = capacity - amount;
8787
self.last_tx_timestamp = now;
88-
RateLimitResult::Consumed
88+
RateLimitResult::Consumed(now)
8989
} else {
9090
RateLimitResult::Delayed(now + Self::RATE_LIMIT_DURATION)
9191
}
9292
}
9393

9494
/// Refills the capacity by the given amount.
9595
/// This is used to replenish the capacity via backflows.
96-
pub fn refill(&mut self, amount: u64) {
96+
pub fn refill(&mut self, now: UnixTimestamp, amount: u64) {
9797
self.capacity_at_last_tx = self.capacity().saturating_add(amount).min(self.limit);
98-
self.last_tx_timestamp = current_timestamp();
98+
self.last_tx_timestamp = now;
9999
}
100100

101101
pub fn set_limit(&mut self, limit: u64) {
@@ -127,30 +127,32 @@ mod tests {
127127

128128
#[test]
129129
fn test_rate_limit() {
130+
let now = current_timestamp();
130131
let mut rate_limit_state = RateLimitState {
131132
limit: 100_000,
132133
capacity_at_last_tx: 100_000,
133-
last_tx_timestamp: current_timestamp(),
134+
last_tx_timestamp: now,
134135
};
135136

136137
// consume 30k. should be immediate
137138
let immediately = rate_limit_state.consume_or_delay(30_000);
138139

139-
assert_eq!(immediately, RateLimitResult::Consumed);
140+
assert_eq!(immediately, RateLimitResult::Consumed(now));
140141
assert_eq!(rate_limit_state.capacity(), 70_000);
141142
assert_eq!(rate_limit_state.limit, 100_000); // unchanged
142143
assert_eq!(rate_limit_state.last_tx_timestamp, current_timestamp());
143144

144145
// replenish 1/4 of the limit, i.e. 25k
145146
set_test_timestamp(current_timestamp() + RateLimitState::RATE_LIMIT_DURATION / 4);
147+
let now = current_timestamp();
146148

147149
assert_eq!(rate_limit_state.capacity(), 70_000 + 25_000);
148150

149151
// now consume 150k. should be delayed
150152
let tomorrow = rate_limit_state.consume_or_delay(150_000);
151153
assert_eq!(
152154
tomorrow,
153-
RateLimitResult::Delayed(current_timestamp() + RateLimitState::RATE_LIMIT_DURATION)
155+
RateLimitResult::Delayed(now + RateLimitState::RATE_LIMIT_DURATION)
154156
);
155157

156158
// the limit is not changed, since the tx was delayed
@@ -168,11 +170,11 @@ mod tests {
168170
assert_eq!(rate_limit_state.capacity(), 95_000);
169171

170172
// now refill 2k
171-
rate_limit_state.refill(2_000);
173+
rate_limit_state.refill(now, 2_000);
172174
assert_eq!(rate_limit_state.capacity(), 97_000);
173175

174176
// now refill 50k
175-
rate_limit_state.refill(50_000);
177+
rate_limit_state.refill(now, 50_000);
176178
assert_eq!(rate_limit_state.capacity(), 100_000);
177179
}
178180
}

0 commit comments

Comments
 (0)