fees.rs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use darkfi_sdk::crypto::constants::{MERKLE_DEPTH_ORCHARD, SPARSE_MERKLE_DEPTH};
  19. use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
  20. use crate::zkas::{Opcode, VarType, ZkBinary};
  21. /// Fixed fee for verifying Schnorr signatures using the Pallas
  22. /// elliptic curve.
  23. pub const PALLAS_SCHNORR_SIGNATURE_FEE: u64 = 1000;
  24. /// Calculate the gas use for verifying a given zkas circuit.
  25. /// This function assumes that the zkbin was properly decoded.
  26. pub fn circuit_gas_use(zkbin: &ZkBinary) -> u64 {
  27. let mut accumulator: u64 = 0;
  28. // Constants each with a cost of 10
  29. accumulator = accumulator.saturating_add(10u64.saturating_mul(zkbin.constants.len() as u64));
  30. // Literals each with a cost of 10 (for now there's only 1 type of
  31. // literal).
  32. accumulator = accumulator.saturating_add(10u64.saturating_mul(zkbin.literals.len() as u64));
  33. // Witnesses have cost by type
  34. for witness in &zkbin.witnesses {
  35. let cost = match witness {
  36. VarType::Dummy => unreachable!(),
  37. VarType::EcPoint => 20,
  38. VarType::EcFixedPoint => unreachable!(),
  39. VarType::EcFixedPointShort => unreachable!(),
  40. VarType::EcFixedPointBase => unreachable!(),
  41. VarType::EcNiPoint => 20,
  42. VarType::Base => 10,
  43. VarType::BaseArray => unreachable!(),
  44. VarType::Scalar => 20,
  45. VarType::ScalarArray => unreachable!(),
  46. VarType::MerklePath => 10 * MERKLE_DEPTH_ORCHARD as u64,
  47. VarType::SparseMerklePath => 10 * SPARSE_MERKLE_DEPTH as u64,
  48. VarType::Uint32 => 10,
  49. VarType::Uint64 => 10,
  50. VarType::Any => 10,
  51. };
  52. accumulator = accumulator.saturating_add(cost);
  53. }
  54. // Opcodes depending on how heavy they are
  55. for opcode in &zkbin.opcodes {
  56. let cost = match opcode.0 {
  57. Opcode::Noop => unreachable!(),
  58. Opcode::EcAdd => 30,
  59. Opcode::EcMul => 30,
  60. Opcode::EcMulBase => 30,
  61. Opcode::EcMulShort => 30,
  62. Opcode::EcMulVarBase => 30,
  63. Opcode::EcGetX => 5,
  64. Opcode::EcGetY => 5,
  65. Opcode::PoseidonHash => {
  66. 20u64.saturating_add(10u64.saturating_mul(opcode.1.len() as u64))
  67. }
  68. Opcode::MerkleRoot => 10 * MERKLE_DEPTH_ORCHARD as u64,
  69. Opcode::SparseMerkleRoot => 10 * SPARSE_MERKLE_DEPTH as u64,
  70. Opcode::BaseAdd => 15,
  71. Opcode::BaseMul => 15,
  72. Opcode::BaseSub => 15,
  73. Opcode::WitnessBase => 10,
  74. Opcode::RangeCheck => 60,
  75. Opcode::LessThanStrict => 100,
  76. Opcode::LessThanLoose => 100,
  77. Opcode::BoolCheck => 20,
  78. Opcode::CondSelect => 10,
  79. Opcode::ZeroCondSelect => 10,
  80. Opcode::ConstrainEqualBase => 10,
  81. Opcode::ConstrainEqualPoint => 20,
  82. Opcode::ConstrainInstance => 10,
  83. Opcode::DebugPrint => 100,
  84. };
  85. accumulator = accumulator.saturating_add(cost);
  86. }
  87. accumulator
  88. }
  89. /// Auxiliary struct representing the full gas usage breakdown of a
  90. /// transaction.
  91. ///
  92. /// This data is used for accounting of fees, providing details
  93. /// relating to resource consumption across different transactions.
  94. #[derive(Default, Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
  95. pub struct GasData {
  96. /// Wasm calls gas consumption
  97. pub wasm: u64,
  98. /// ZK circuits gas consumption
  99. pub zk_circuits: u64,
  100. /// Signature fee
  101. pub signatures: u64,
  102. /// Contract deployment gas
  103. pub deployments: u64,
  104. /// Transaction paid fee
  105. pub paid: u64,
  106. }
  107. impl GasData {
  108. /// Calculates the total gas used by summing all individual gas
  109. /// usage fields.
  110. pub fn total_gas_used(&self) -> u64 {
  111. self.wasm
  112. .saturating_add(self.zk_circuits)
  113. .saturating_add(self.signatures)
  114. .saturating_add(self.deployments)
  115. }
  116. }
  117. /// Implements custom debug trait to include
  118. /// [`GasData::total_gas_used`].
  119. impl std::fmt::Debug for GasData {
  120. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  121. f.debug_struct("GasData")
  122. .field("total", &self.total_gas_used())
  123. .field("wasm", &self.wasm)
  124. .field("zk_circuits", &self.zk_circuits)
  125. .field("signatures", &self.signatures)
  126. .field("deployments", &self.deployments)
  127. .field("paid", &self.paid)
  128. .finish()
  129. }
  130. }