darkfi/validator/
fees.rs

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
19use darkfi_sdk::crypto::constants::{MERKLE_DEPTH_ORCHARD, SPARSE_MERKLE_DEPTH};
20use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
21
22use crate::zkas::{Opcode, VarType, ZkBinary};
23
24/// Fixed fee for verifying Schnorr signatures using the Pallas elliptic curve
25pub const PALLAS_SCHNORR_SIGNATURE_FEE: u64 = 1000;
26
27/// Calculate the gas use for verifying a given zkas circuit.
28/// This function assumes that the zkbin was properly decoded.
29pub fn circuit_gas_use(zkbin: &ZkBinary) -> u64 {
30    let mut accumulator: u64 = 0;
31
32    // Constants each with a cost of 10
33    accumulator += 10 * zkbin.constants.len() as u64;
34
35    // Literals each with a cost of 10 (for now there's only 1 type of literal)
36    accumulator += 10 * zkbin.literals.len() as u64;
37
38    // Witnesses have cost by type
39    for witness in &zkbin.witnesses {
40        let cost = match witness {
41            VarType::Dummy => unreachable!(),
42            VarType::EcPoint => 20,
43            VarType::EcFixedPoint => unreachable!(),
44            VarType::EcFixedPointShort => unreachable!(),
45            VarType::EcFixedPointBase => unreachable!(),
46            VarType::EcNiPoint => 20,
47            VarType::Base => 10,
48            VarType::BaseArray => unreachable!(),
49            VarType::Scalar => 20,
50            VarType::ScalarArray => unreachable!(),
51            VarType::MerklePath => 10 * MERKLE_DEPTH_ORCHARD as u64,
52            VarType::SparseMerklePath => 10 * SPARSE_MERKLE_DEPTH as u64,
53            VarType::Uint32 => 10,
54            VarType::Uint64 => 10,
55            VarType::Any => 10,
56        };
57
58        accumulator += cost;
59    }
60
61    // Opcodes depending on how heavy they are
62    for opcode in &zkbin.opcodes {
63        let cost = match opcode.0 {
64            Opcode::Noop => unreachable!(),
65            Opcode::EcAdd => 30,
66            Opcode::EcMul => 30,
67            Opcode::EcMulBase => 30,
68            Opcode::EcMulShort => 30,
69            Opcode::EcMulVarBase => 30,
70            Opcode::EcGetX => 5,
71            Opcode::EcGetY => 5,
72            Opcode::PoseidonHash => 20 + 10 * opcode.1.len() as u64,
73            Opcode::MerkleRoot => 10 * MERKLE_DEPTH_ORCHARD as u64,
74            Opcode::SparseMerkleRoot => 10 * SPARSE_MERKLE_DEPTH as u64,
75            Opcode::BaseAdd => 15,
76            Opcode::BaseMul => 15,
77            Opcode::BaseSub => 15,
78            Opcode::WitnessBase => 10,
79            Opcode::RangeCheck => 60,
80            Opcode::LessThanStrict => 100,
81            Opcode::LessThanLoose => 100,
82            Opcode::BoolCheck => 20,
83            Opcode::CondSelect => 10,
84            Opcode::ZeroCondSelect => 10,
85            Opcode::ConstrainEqualBase => 10,
86            Opcode::ConstrainEqualPoint => 20,
87            Opcode::ConstrainInstance => 10,
88            Opcode::DebugPrint => 100,
89        };
90
91        accumulator += cost;
92    }
93
94    accumulator
95}
96
97/// Auxiliary struct representing the full gas usage breakdown of a transaction.
98///
99/// This data is used for accounting of fees, providing details relating to
100/// resource consumption across different transactions.
101#[derive(Default, Clone, Eq, PartialEq, SerialEncodable, SerialDecodable)]
102pub struct GasData {
103    /// Wasm calls gas consumption
104    pub wasm: u64,
105    /// ZK circuits gas consumption
106    pub zk_circuits: u64,
107    /// Signature fee
108    pub signatures: u64,
109    /// Contract deployment gas
110    pub deployments: u64,
111    /// Transaction paid fee
112    pub paid: u64,
113}
114
115impl GasData {
116    /// Calculates the total gas used by summing all individual gas usage fields.
117    pub fn total_gas_used(&self) -> u64 {
118        self.wasm + self.zk_circuits + self.signatures + self.deployments
119    }
120}
121
122/// Implements custom debug trait to include [`GasData::total_gas_used`].
123impl std::fmt::Debug for GasData {
124    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125        f.debug_struct("GasData")
126            .field("total", &self.total_gas_used())
127            .field("wasm", &self.wasm)
128            .field("zk_circuits", &self.zk_circuits)
129            .field("signatures", &self.signatures)
130            .field("deployments", &self.deployments)
131            .field("paid", &self.paid)
132            .finish()
133    }
134}
135
136/// Auxiliary function to compute the corresponding fee value
137/// for the provided gas.
138///
139/// Currently we simply divide the gas value by 100.
140pub fn compute_fee(gas: &u64) -> u64 {
141    gas / 100
142}