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