penumbra_sdk_transaction/gas.rs
1use penumbra_sdk_auction::auction::dutch::actions::{
2 ActionDutchAuctionEnd, ActionDutchAuctionSchedule, ActionDutchAuctionWithdraw,
3};
4use penumbra_sdk_community_pool::{CommunityPoolDeposit, CommunityPoolOutput, CommunityPoolSpend};
5use penumbra_sdk_dex::{
6 lp::plan::PositionOpenPlan, PositionClose, PositionOpen, PositionWithdraw, Swap, SwapClaim,
7};
8use penumbra_sdk_fee::Gas;
9use penumbra_sdk_funding::liquidity_tournament::{
10 ActionLiquidityTournamentVote, LIQUIDITY_TOURNAMENT_VOTE_DENOM_MAX_BYTES,
11};
12use penumbra_sdk_ibc::IbcRelay;
13use penumbra_sdk_keys::symmetric::ENCRYPTED_POSITION_METADATA_SIZE_BYTES;
14use penumbra_sdk_shielded_pool::{Ics20Withdrawal, Output, Spend};
15use penumbra_sdk_stake::{
16 validator::Definition as ValidatorDefinition, Delegate, Undelegate, UndelegateClaim,
17};
18
19use penumbra_sdk_governance::{
20 DelegatorVote, ProposalDepositClaim, ProposalSubmit, ProposalWithdraw, ValidatorVote,
21};
22
23use crate::{
24 plan::{ActionPlan, TransactionPlan},
25 Action, Transaction,
26};
27
28use penumbra_sdk_proto::DomainType;
29
30const NULLIFIER_SIZE: u64 = 2 + 32;
31const NOTEPAYLOAD_SIZE: u64 = 32 + 32 + 176;
32const SWAPPAYLOAD_SIZE: u64 = 32 + 272;
33const ZKPROOF_SIZE: u64 = 192;
34// This is an approximation, the actual size is variable
35const BSOD_SIZE: u64 = 16 + 16 + 0 + 4 + 64 + 4;
36
37/// Allows [`Action`]s and [`Transaction`]s to statically indicate their relative resource consumption.
38/// Since the gas cost needs to be multiplied by a price, the values returned
39/// only need to be scaled relatively to each other.
40pub trait GasCost {
41 fn gas_cost(&self) -> Gas;
42}
43
44// Where block space costs are hard-coded instead of calculated in the following functions, the values are based on the approximate byte size of the
45// encoded action and ignore the protobuf framing overhead, because it makes only a small difference and simplifies accounting.
46
47pub fn spend_gas_cost() -> Gas {
48 Gas {
49 // penumbra.core.asset.v1.BalanceCommitment `balance_commitment` = 32 bytes
50 // penumbra.core.component.sct.v1.Nullifier `nullifier` = 32 bytes
51 // penumbra.crypto.decaf377_rdsa.v1.SpendVerificationKey `rk` = 32 bytes
52 // penumbra.crypto.decaf377_rdsa.v1.SpendAuthSignature `auth_sig` = 64 bytes
53 // ZKSpendProof `proof` = 192 bytes
54
55 // The block space measured as the byte length of the encoded action.
56 block_space: 160 + ZKPROOF_SIZE, // 352 bytes
57 // The compact block space cost is based on the byte size of the data the [`Action`] adds
58 // to the compact block. For a `Spend`, this is the byte size of a `Nullifier`.
59 compact_block_space: NULLIFIER_SIZE,
60 // Includes a zk-SNARK proof, so we include a constant verification cost.
61 verification: 1000,
62 // Execution cost is currently hardcoded at 10 for all [`Action`] variants.
63 execution: 10,
64 }
65}
66
67pub fn output_gas_cost() -> Gas {
68 Gas {
69 // NotePayload `note_payload` = 32 + 32 + 176 = 240 bytes
70 // penumbra.core.asset.v1.BalanceCommitment `balance_commitment` = 32 bytes
71 // wrapped_memo_key `wrapped_memo_key` = 48 bytes
72 // ovk_wrapped_key `ovk_wrapped_key` = 48 bytes
73 // ZKOutputProof `proof` = 192 bytes
74
75 // The block space measured as the byte length of the encoded action.
76 block_space: 128 + NOTEPAYLOAD_SIZE + ZKPROOF_SIZE, // 560 bytes
77 // The compact block space cost is based on the byte size of the data the [`Action`] adds
78 // to the compact block.
79 compact_block_space: NOTEPAYLOAD_SIZE,
80 // Includes a zk-SNARK proof, so we include a constant verification cost.
81 verification: 1000,
82 // Execution cost is currently hardcoded at 10 for all [`Action`] variants.
83 execution: 10,
84 }
85}
86
87fn delegate_gas_cost(delegate: &Delegate) -> Gas {
88 Gas {
89 // The block space measured as the byte length of the encoded action.
90 block_space: delegate.encode_to_vec().len() as u64,
91 // The compact block space cost is based on the byte size of the data the [`Action`] adds
92 // to the compact block.
93 // For a Delegate, nothing is added to the compact block directly. The associated [`Action::Spend`]
94 // actions will add their costs, but there's nothing to add here.
95 compact_block_space: 0,
96 // Does not include a zk-SNARK proof, so there's no verification cost.
97 verification: 0,
98 // Execution cost is currently hardcoded at 10 for all Action variants.
99 execution: 10,
100 }
101}
102
103fn undelegate_gas_cost(undelegate: &Undelegate) -> Gas {
104 Gas {
105 // The block space measured as the byte length of the encoded action.
106 block_space: undelegate.encode_to_vec().len() as u64,
107 // The compact block space cost is based on the byte size of the data the [`Action`] adds
108 // to the compact block.
109 // For an Undelegate, nothing is added to the compact block directly. The associated [`Action::Spend`]
110 // actions will add their costs, but there's nothing to add here.
111 compact_block_space: 0,
112 // Does not include a zk-SNARK proof, so there's no verification cost.
113 verification: 0,
114 // Execution cost is currently hardcoded at 10 for all Action variants.
115 execution: 10,
116 }
117}
118
119fn undelegate_claim_gas_cost() -> Gas {
120 Gas {
121 // penumbra.core.keys.v1.IdentityKey `validator_identity` = 32 bytes
122 // uint64 `start_epoch_index` = 8 bytes
123 // Penalty `penalty` = 32 bytes
124 // penumbra.core.asset.v1.BalanceCommitment `balance_commitment` = 32 bytes
125 // uint64 `unbonding_start_height` = 8 bytes
126 // ZKSpendProof `proof` = 192 bytes
127
128 // The block space measured as the byte length of the encoded action.
129 block_space: 112 + ZKPROOF_SIZE, // 304 bytes
130 // The compact block space cost is based on the byte size of the data the [`Action`] adds
131 // to the compact block.
132 // For an `UndelegateClaim`, nothing is added to the compact block directly. The associated [`Action::Output`]
133 // actions will add their costs, but there's nothing to add here.
134 compact_block_space: 0,
135 // Includes a zk-SNARK proof, so we include a constant verification cost.
136 verification: 1000,
137 // Execution cost is currently hardcoded at 10 for all Action variants.
138 execution: 10,
139 }
140}
141
142fn validator_definition_gas_cost(validator_definition: &ValidatorDefinition) -> Gas {
143 Gas {
144 // The block space measured as the byte length of the encoded action.
145 block_space: validator_definition.encode_to_vec().len() as u64,
146 // The compact block space cost is based on the byte size of the data the [`Action`] adds
147 // to the compact block.
148 // For a ValidatorDefinition the compact block is not modified.
149 compact_block_space: 0,
150 // Includes a signature verification, so we include a small constant verification cost.
151 verification: 200,
152 // Execution cost is currently hardcoded at 10 for all Action variants.
153 execution: 10,
154 }
155}
156
157fn swap_gas_cost() -> Gas {
158 Gas {
159 // TradingPair `trading_pair` = 64 bytes
160 // penumbra.core.num.v1.Amount `delta_1_i` = 16 bytes
161 // penumbra.core.num.v1.Amount `delta_2_i` = 16 bytes
162 // penumbra.core.asset.v1.BalanceCommitment `fee_commitment` = 32 bytes
163 // SwapPayload `payload` = 304 bytes
164 // ZKSwapProof `proof` = 192 bytes
165 // Batch swap output data = 104 bytes
166
167 // The block space measured as the byte length of the encoded action.
168 block_space: 128 + ZKPROOF_SIZE + SWAPPAYLOAD_SIZE + BSOD_SIZE, // 728 bytes
169 // The compact block space cost is based on the byte size of the data the [`Action`] adds
170 // to the compact block.
171 // For a `Swap` this is the byte size of a [`StatePayload`] and a [`BatchSwapOutputData`].
172 // `Swap`s are batched so technically the cost of the `BatchSwapOutputData` is shared across
173 // multiple swaps, but if only one `swap` for a trading pair is performed in a block, that
174 // `swap` will add a `BatchSwapOutputData` all on its own.
175 // Note: the BSOD has variable size, we pick an approximation.
176 compact_block_space: SWAPPAYLOAD_SIZE + BSOD_SIZE,
177 // Includes a zk-SNARK proof, so we include a constant verification cost.
178 verification: 1000,
179 // Execution cost is currently hardcoded at 10 for all Action variants.
180 execution: 10,
181 }
182}
183
184pub fn swap_claim_gas_cost() -> Gas {
185 Gas {
186 // penumbra.core.component.sct.v1.Nullifier `nullifier` = 32 bytes
187 // penumbra.core.component.fee.v1.Fee `fee`` = 48 bytes
188 // penumbra.crypto.tct.v1.StateCommitment `output_1_commitment`` = 32 bytes
189 // penumbra.crypto.tct.v1.StateCommitment `output_2_commitment` = 32 bytes
190 // BatchSwapOutputData `output_data` = 176 bytes
191 // uint64 `epoch_duration` = 8 bytes
192 // ZKSwapClaimProof `proof` = 192 bytes
193 // Batch swap output data = 104 bytes
194
195 // The block space measured as the byte length of the encoded action.
196 block_space: 328 + ZKPROOF_SIZE + BSOD_SIZE, // 624 bytes
197 // The compact block space cost is based on the byte size of the data the [`Action`] adds
198 // to the compact block.
199 // For a `SwapClaim`, nothing is added to the compact block directly. The associated [`Action::Spend`]
200 // and [`Action::Output`] actions will add their costs, but there's nothing to add here.
201 compact_block_space: 0,
202 // Includes a zk-SNARK proof, so we include a constant verification cost.
203 verification: 1000,
204 // Execution cost is currently hardcoded at 10 for all Action variants.
205 execution: 10,
206 }
207}
208
209fn delegator_vote_gas_cost() -> Gas {
210 Gas {
211 // uint64 `proposal` = 8 bytes
212 // uint64 `start_position` = 8 bytes
213 // Vote `vote` = 1 byte
214 // penumbra.core.asset.v1.Value `value` = 48 bytes
215 // penumbra.core.num.v1.Amount `unbonded_amount` = 16 bytes
216 // penumbra.core.component.sct.v1.Nullifier `nullifier` = 32 bytes
217 // penumbra.crypto.decaf377_rdsa.v1.SpendVerificationKey `rk` = 32 bytes
218 // penumbra.crypto.decaf377_rdsa.v1.SpendAuthSignature `auth_sig` = 64 bytes
219 // ZKDelegatorVoteProof `proof` = 192 bytes
220
221 // The block space measured as the byte length of the encoded action.
222 block_space: 209 + ZKPROOF_SIZE, // 401 bytes
223 // The compact block space cost is based on the byte size of the data the [`Action`] adds
224 // to the compact block.
225 // For a DelegatorVote the compact block is not modified.
226 compact_block_space: 0,
227 // Includes a zk-SNARK proof, so we include a constant verification cost.
228 verification: 1000,
229 // Execution cost is currently hardcoded at 10 for all Action variants.
230 execution: 10,
231 }
232}
233
234fn position_withdraw_gas_cost() -> Gas {
235 Gas {
236 // PositionId `position_id` = 32 bytes
237 // penumbra.core.asset.v1.BalanceCommitment `reserves_commitment` = 32 bytes
238 // uint64 `sequence` = 8 bytes
239
240 // The block space measured as the byte length of the encoded action.
241 block_space: 72, // 72 bytes
242 // The compact block space cost is based on the byte size of the data the [`Action`] adds
243 // to the compact block.
244 // For a PositionWithdraw the compact block is not modified.
245 compact_block_space: 0,
246 // Does not include a zk-SNARK proof, so there's no verification cost.
247 verification: 0,
248 // Execution cost is currently hardcoded at 10 for all `Action`` variants.
249 // Reminder: Any change to this execution gas vector must also be reflected
250 // in updates to the dutch auction gas vectors.
251 execution: 10,
252 }
253}
254
255fn dutch_auction_schedule_gas_cost(dutch_action_schedule: &ActionDutchAuctionSchedule) -> Gas {
256 Gas {
257 // penumbra.core.asset.v1.Value `input` = 48 bytes
258 // penumbra.core.asset.v1.AssetId `output_id` = 32 bytes
259 // penumbra.core.num.v1.Amount `max_output` = 16 bytes
260 // penumbra.core.num.v1.Amount `min_output` = 16 bytes
261 // uint64 `start_height` = 8 bytes
262 // uint64 `end_height` = 8 bytes
263 // uint64 `step_count` = 8 bytes
264 // bytes `nonce` = 32 bytes
265 block_space: 168,
266 compact_block_space: 0,
267 verification: 50,
268 // Currently, we make the execution cost for DA actions proportional to the number of steps
269 // and costs of position open/close in dutch action. The gas cost is calculated by:
270 // 2 * step_count * (`PositionOpen`` + `PositionClose` cost).
271 execution: 2 * dutch_action_schedule.description.step_count * (10 + 10),
272 }
273}
274
275fn dutch_auction_end_gas_cost() -> Gas {
276 Gas {
277 // AuctionId `auction_id` = 32 bytes
278 block_space: 32, // 32 bytes
279 compact_block_space: 0,
280 verification: 0,
281 execution: 10,
282 }
283}
284
285fn dutch_auction_withdraw_gas_cost() -> Gas {
286 Gas {
287 // AuctionId `auction_id` = 32 bytes
288 // uint64 `seq`= 8 bytes
289 // penumbra.core.asset.v1.BalanceCommitment `reserves_commitment` = 32 bytes
290 block_space: 72, // 72 bytes
291 compact_block_space: 0,
292 verification: 0,
293 execution: 10,
294 }
295}
296
297fn liquidity_tournament_vote_gas_cost() -> Gas {
298 Gas {
299 block_space:
300 // LiquidityTournamentVoteBody body = 1;
301 (
302 // asset.v1.Denom incentivized = 1; (restricted to MAX bytes)
303 LIQUIDITY_TOURNAMENT_VOTE_DENOM_MAX_BYTES as u64
304 // keys.v1.Address rewards_recipient = 2; (the larger of the two exclusive fields)
305 + 223
306 // uint64 start_position = 3;
307 + 8
308 // asset.v1.Value value = 4;
309 + 48
310 // sct.v1.Nullifier nullifier = 5;
311 + 32
312 // crypto.decaf377_rdsa.v1.SpendVerificationKey rk = 6;
313 + 32
314 )
315 // crypto.decaf377_rdsa.v1.SpendAuthSignature auth_sig = 2;
316 + 64
317 // ZKLiquidityTournamentVoteProof proof = 3;
318 + ZKPROOF_SIZE,
319 // Each vote will, pessimistically, create one output for the reward.
320 compact_block_space: NOTEPAYLOAD_SIZE,
321 verification: 1000,
322 execution: 10,
323 }
324}
325
326impl GasCost for Transaction {
327 fn gas_cost(&self) -> Gas {
328 self.actions().map(GasCost::gas_cost).sum()
329 }
330}
331
332impl GasCost for TransactionPlan {
333 fn gas_cost(&self) -> Gas {
334 self.actions.iter().map(GasCost::gas_cost).sum()
335 }
336}
337
338// The planner also needs to be able to calculate gas costs,
339// however until the transaction is finalized, the planner only
340// has access to `ActionPlan` variants.
341//
342// IMPORTANT: The results produced by this impl should always
343// match what the impl for the associated `Action` variant would
344// produce, otherwise the planner will not include proper gas in
345// transactions.
346impl GasCost for ActionPlan {
347 fn gas_cost(&self) -> Gas {
348 match self {
349 // Some variants use separate `*Plan` inners and need their
350 // own implementations; others encapsulate an `Action` variant
351 // and can call the `GasCost` impl on that.
352 ActionPlan::Spend(_) => spend_gas_cost(),
353 ActionPlan::Output(_) => output_gas_cost(),
354 ActionPlan::UndelegateClaim(_) => undelegate_claim_gas_cost(),
355 ActionPlan::Swap(_) => swap_gas_cost(),
356 ActionPlan::SwapClaim(_) => swap_claim_gas_cost(),
357 ActionPlan::DelegatorVote(_) => delegator_vote_gas_cost(),
358 ActionPlan::PositionWithdraw(_) => position_withdraw_gas_cost(),
359 ActionPlan::ActionDutchAuctionSchedule(das) => das.gas_cost(),
360 ActionPlan::ActionDutchAuctionEnd(_) => dutch_auction_end_gas_cost(),
361 ActionPlan::ActionDutchAuctionWithdraw(_) => dutch_auction_withdraw_gas_cost(),
362
363 ActionPlan::Delegate(d) => d.gas_cost(),
364 ActionPlan::Undelegate(u) => u.gas_cost(),
365 ActionPlan::ValidatorDefinition(vd) => vd.gas_cost(),
366 ActionPlan::IbcAction(i) => i.gas_cost(),
367 ActionPlan::ProposalSubmit(ps) => ps.gas_cost(),
368 ActionPlan::ProposalWithdraw(pw) => pw.gas_cost(),
369 ActionPlan::ValidatorVote(v) => v.gas_cost(),
370 ActionPlan::ProposalDepositClaim(pdc) => pdc.gas_cost(),
371 ActionPlan::PositionOpen(po) => po.gas_cost(),
372 ActionPlan::PositionClose(pc) => pc.gas_cost(),
373 ActionPlan::CommunityPoolSpend(ds) => ds.gas_cost(),
374 ActionPlan::CommunityPoolOutput(d) => d.gas_cost(),
375 ActionPlan::CommunityPoolDeposit(dd) => dd.gas_cost(),
376 ActionPlan::Ics20Withdrawal(w) => w.gas_cost(),
377 ActionPlan::ActionLiquidityTournamentVote(_) => liquidity_tournament_vote_gas_cost(),
378 }
379 }
380}
381
382impl GasCost for Action {
383 fn gas_cost(&self) -> Gas {
384 match self {
385 Action::Output(output) => output.gas_cost(),
386 Action::Spend(spend) => spend.gas_cost(),
387 Action::Delegate(delegate) => delegate.gas_cost(),
388 Action::Undelegate(undelegate) => undelegate.gas_cost(),
389 Action::UndelegateClaim(undelegate_claim) => undelegate_claim.gas_cost(),
390 Action::Swap(swap) => swap.gas_cost(),
391 Action::SwapClaim(swap_claim) => swap_claim.gas_cost(),
392 Action::ProposalSubmit(submit) => submit.gas_cost(),
393 Action::ProposalWithdraw(withdraw) => withdraw.gas_cost(),
394 Action::DelegatorVote(delegator_vote) => delegator_vote.gas_cost(),
395 Action::ValidatorVote(validator_vote) => validator_vote.gas_cost(),
396 Action::ProposalDepositClaim(p) => p.gas_cost(),
397 Action::PositionOpen(p) => p.gas_cost(),
398 Action::PositionClose(p) => p.gas_cost(),
399 Action::PositionWithdraw(p) => p.gas_cost(),
400 Action::Ics20Withdrawal(withdrawal) => withdrawal.gas_cost(),
401 Action::CommunityPoolDeposit(deposit) => deposit.gas_cost(),
402 Action::CommunityPoolSpend(spend) => spend.gas_cost(),
403 Action::CommunityPoolOutput(output) => output.gas_cost(),
404 Action::IbcRelay(x) => x.gas_cost(),
405 Action::ValidatorDefinition(x) => x.gas_cost(),
406 Action::ActionDutchAuctionSchedule(action_dutch_auction_schedule) => {
407 action_dutch_auction_schedule.gas_cost()
408 }
409 Action::ActionDutchAuctionEnd(action_dutch_auction_end) => {
410 action_dutch_auction_end.gas_cost()
411 }
412 Action::ActionDutchAuctionWithdraw(action_dutch_auction_withdraw) => {
413 action_dutch_auction_withdraw.gas_cost()
414 }
415 Action::ActionLiquidityTournamentVote(action_liquidity_tournament_vote) => {
416 action_liquidity_tournament_vote.gas_cost()
417 }
418 }
419 }
420}
421
422impl GasCost for Output {
423 fn gas_cost(&self) -> Gas {
424 output_gas_cost()
425 }
426}
427
428impl GasCost for Spend {
429 fn gas_cost(&self) -> Gas {
430 spend_gas_cost()
431 }
432}
433
434impl GasCost for Delegate {
435 fn gas_cost(&self) -> Gas {
436 delegate_gas_cost(&self)
437 }
438}
439
440impl GasCost for Undelegate {
441 fn gas_cost(&self) -> Gas {
442 undelegate_gas_cost(&self)
443 }
444}
445
446impl GasCost for UndelegateClaim {
447 fn gas_cost(&self) -> Gas {
448 undelegate_claim_gas_cost()
449 }
450}
451
452impl GasCost for Swap {
453 fn gas_cost(&self) -> Gas {
454 swap_gas_cost()
455 }
456}
457
458impl GasCost for SwapClaim {
459 fn gas_cost(&self) -> Gas {
460 swap_claim_gas_cost()
461 }
462}
463
464impl GasCost for ProposalSubmit {
465 fn gas_cost(&self) -> Gas {
466 Gas {
467 // The block space measured as the byte length of the encoded action.
468 block_space: self.encode_to_vec().len() as u64,
469 // In the case of a proposal submission, the compact block cost is zero.
470 // The compact block is only modified it the proposal is ratified.
471 // And when that's the case, the cost is mutualized.
472 compact_block_space: 0,
473 // There are some checks performed to validate the proposed state changes, so we include a constant verification cost,
474 // smaller than a zk-SNARK verification cost.
475 verification: 100,
476 // Execution cost is currently hardcoded at 10 for all Action variants.
477 execution: 10,
478 }
479 }
480}
481
482impl GasCost for ProposalWithdraw {
483 fn gas_cost(&self) -> Gas {
484 Gas {
485 // The block space measured as the byte length of the encoded action.
486 block_space: self.encode_to_vec().len() as u64,
487 // The compact block space cost is based on the byte size of the data the [`Action`] adds
488 // to the compact block.
489 // For a ProposalWithdraw the compact block is not modified.
490 compact_block_space: 0,
491 // Does not include a zk-SNARK proof, so there's no verification cost.
492 verification: 0,
493 // Execution cost is currently hardcoded at 10 for all Action variants.
494 execution: 10,
495 }
496 }
497}
498
499impl GasCost for DelegatorVote {
500 fn gas_cost(&self) -> Gas {
501 delegator_vote_gas_cost()
502 }
503}
504
505impl GasCost for ValidatorVote {
506 fn gas_cost(&self) -> Gas {
507 Gas {
508 // The block space measured as the byte length of the encoded action.
509 block_space: self.encode_to_vec().len() as u64,
510 // The compact block space cost is based on the byte size of the data the [`Action`] adds
511 // to the compact block.
512 // For a ValidatorVote the compact block is not modified.
513 compact_block_space: 0,
514 // Includes a signature verification, so we include a small constant verification cost.
515 verification: 200,
516 // Execution cost is currently hardcoded at 10 for all Action variants.
517 execution: 10,
518 }
519 }
520}
521
522impl GasCost for ProposalDepositClaim {
523 fn gas_cost(&self) -> Gas {
524 Gas {
525 // The block space measured as the byte length of the encoded action.
526 block_space: self.encode_to_vec().len() as u64,
527 // The compact block space cost is based on the byte size of the data the [`Action`] adds
528 // to the compact block.
529 // For a ProposalDepositClaim the compact block is not modified.
530 compact_block_space: 0,
531 // Does not include a zk-SNARK proof, so there's no verification cost.
532 verification: 0,
533 // Execution cost is currently hardcoded at 10 for all Action variants.
534 execution: 10,
535 }
536 }
537}
538
539impl GasCost for PositionOpenPlan {
540 fn gas_cost(&self) -> Gas {
541 let padding = if self.metadata.is_none() {
542 ENCRYPTED_POSITION_METADATA_SIZE_BYTES as u64
543 } else {
544 0
545 };
546 Gas {
547 // The block space measured as the byte length of the encoded action.
548 // But, we also add padding to not penalize including a ciphertext.
549 block_space: self.position.encode_to_vec().len() as u64 + padding,
550 // The compact block space cost is based on the byte size of the data the [`Action`] adds
551 // to the compact block.
552 // For a PositionOpen the compact block is not modified.
553 compact_block_space: 0,
554 // There are some small validations performed so a token amount of gas is charged.
555 verification: 50,
556 // Execution cost is currently hardcoded at 10 for all Action variants.
557 // Reminder: Any change to this execution gas vector must also be reflected
558 // in updates to the dutch auction gas vectors.
559 execution: 10,
560 }
561 }
562}
563
564impl GasCost for PositionOpen {
565 fn gas_cost(&self) -> Gas {
566 Gas {
567 // The block space measured as the byte length of the encoded action.
568 block_space: self.encode_to_vec().len() as u64,
569 // The compact block space cost is based on the byte size of the data the [`Action`] adds
570 // to the compact block.
571 // For a PositionOpen the compact block is not modified.
572 compact_block_space: 0,
573 // There are some small validations performed so a token amount of gas is charged.
574 verification: 50,
575 // Execution cost is currently hardcoded at 10 for all Action variants.
576 // Reminder: Any change to this execution gas vector must also be reflected
577 // in updates to the dutch auction gas vectors.
578 execution: 10,
579 }
580 }
581}
582
583impl GasCost for PositionClose {
584 fn gas_cost(&self) -> Gas {
585 Gas {
586 // The block space measured as the byte length of the encoded action.
587 block_space: self.encode_to_vec().len() as u64,
588 // The compact block space cost is based on the byte size of the data the [`Action`] adds
589 // to the compact block.
590 // For a PositionClose the compact block is not modified.
591 compact_block_space: 0,
592 // Does not include a zk-SNARK proof, so there's no verification cost.
593 verification: 0,
594 // Execution cost is currently hardcoded at 10 for all Action variants.
595 // Reminder: Any change to this execution gas vector must also be reflected
596 // in updates to the dutch auction gas vectors.
597 execution: 10,
598 }
599 }
600}
601
602impl GasCost for PositionWithdraw {
603 fn gas_cost(&self) -> Gas {
604 position_withdraw_gas_cost()
605 }
606}
607
608impl GasCost for Ics20Withdrawal {
609 fn gas_cost(&self) -> Gas {
610 Gas {
611 // The block space measured as the byte length of the encoded action.
612 block_space: self.encode_to_vec().len() as u64,
613 // The compact block space cost is based on the byte size of the data the [`Action`] adds
614 // to the compact block.
615 // For a Ics20Withdrawal the compact block is not modified.
616 compact_block_space: 0,
617 // Does not include a zk-SNARK proof, so there's no verification cost.
618 verification: 0,
619 // Execution cost is currently hardcoded at 10 for all Action variants.
620 execution: 10,
621 }
622 }
623}
624
625impl GasCost for CommunityPoolDeposit {
626 fn gas_cost(&self) -> Gas {
627 Gas {
628 // The block space measured as the byte length of the encoded action.
629 block_space: self.encode_to_vec().len() as u64,
630 // The compact block space cost is based on the byte size of the data the [`Action`] adds
631 // to the compact block.
632 // For a CommunityPoolDeposit the compact block is not modified.
633 compact_block_space: 0,
634 // Does not include a zk-SNARK proof, so there's no verification cost.
635 verification: 0,
636 // Execution cost is currently hardcoded at 10 for all Action variants.
637 execution: 10,
638 }
639 }
640}
641
642impl GasCost for CommunityPoolSpend {
643 fn gas_cost(&self) -> Gas {
644 Gas {
645 // The block space measured as the byte length of the encoded action.
646 block_space: self.encode_to_vec().len() as u64,
647 // The compact block space cost is based on the byte size of the data the [`Action`] adds
648 // to the compact block.
649 // For a CommunityPoolSpend the compact block is not modified.
650 compact_block_space: 0,
651 // Does not include a zk-SNARK proof, so there's no verification cost.
652 verification: 0,
653 // Execution cost is currently hardcoded at 10 for all Action variants.
654 execution: 10,
655 }
656 }
657}
658
659impl GasCost for CommunityPoolOutput {
660 fn gas_cost(&self) -> Gas {
661 // We hardcode the gas costs of a `CommunityPoolOutput` to 0, since it's a protocol action.
662 Gas {
663 block_space: 0,
664 compact_block_space: 0,
665 verification: 0,
666 execution: 0,
667 }
668 }
669}
670
671impl GasCost for IbcRelay {
672 fn gas_cost(&self) -> Gas {
673 Gas {
674 // The block space measured as the byte length of the encoded action.
675 block_space: self.encode_to_vec().len() as u64,
676 // The compact block space cost is based on the byte size of the data the [`Action`] adds
677 // to the compact block.
678 // For a IbcAction this is the byte size of a [`StatePayload`].
679 compact_block_space: match self {
680 // RecvPacket will mint a note if successful.
681 IbcRelay::RecvPacket(_) => NOTEPAYLOAD_SIZE,
682 _ => 0,
683 },
684 // Includes a proof in the execution for RecvPacket (TODO: check the other variants).
685 verification: match self {
686 IbcRelay::RecvPacket(_) => 1000,
687 _ => 0,
688 },
689 // Execution cost is currently hardcoded at 10 for all Action variants.
690 execution: 10,
691 }
692 }
693}
694
695impl GasCost for ValidatorDefinition {
696 fn gas_cost(&self) -> Gas {
697 validator_definition_gas_cost(&self)
698 }
699}
700
701impl GasCost for ActionDutchAuctionSchedule {
702 fn gas_cost(&self) -> Gas {
703 dutch_auction_schedule_gas_cost(&self)
704 }
705}
706
707impl GasCost for ActionDutchAuctionEnd {
708 fn gas_cost(&self) -> Gas {
709 dutch_auction_end_gas_cost()
710 }
711}
712
713impl GasCost for ActionDutchAuctionWithdraw {
714 fn gas_cost(&self) -> Gas {
715 dutch_auction_withdraw_gas_cost()
716 }
717}
718
719impl GasCost for ActionLiquidityTournamentVote {
720 fn gas_cost(&self) -> Gas {
721 liquidity_tournament_vote_gas_cost()
722 }
723}