背景

当使用Solana部署私链或者侧链时,需要自定义链的手续费价格

配置

先说如何配置
拿multinode-demo/setup.sh举例
在文件尾部添加 --target-lamports-per-signature

...
default_arg --target-lamports-per-signature 10

$solana_genesis "${args[@]}"

链代码分析

sdk/program/src/fee_calculator.rs

pub fn new_derived(
        base_fee_rate_governor: &FeeRateGovernor,
        latest_signatures_per_slot: u64,
    ) -> Self {
        let mut me = base_fee_rate_governor.clone();

        if me.target_signatures_per_slot > 0 { // 当配置target_signatures_per_slot时
            // lamports_per_signature can range from 50% to 1000% of
            // target_lamports_per_signature
            me.min_lamports_per_signature = std::cmp::max(1, me.target_lamports_per_signature / 2);
            me.max_lamports_per_signature = me.target_lamports_per_signature * 10;

            // What the cluster should charge at `latest_signatures_per_slot`
            let desired_lamports_per_signature =
                me.max_lamports_per_signature
                    .min(me.min_lamports_per_signature.max(
                        me.target_lamports_per_signature
                            * std::cmp::min(latest_signatures_per_slot, std::u32::MAX as u64)
                            / me.target_signatures_per_slot,
                    ));

            trace!(
                "desired_lamports_per_signature: {}",
                desired_lamports_per_signature
            );

            let gap = desired_lamports_per_signature as i64
                - base_fee_rate_governor.lamports_per_signature as i64;

            if gap == 0 {
                me.lamports_per_signature = desired_lamports_per_signature;
            } else {
                // Adjust fee by 5% of target_lamports_per_signature to produce a smooth
                // increase/decrease in fees over time.
                let gap_adjust =
                    std::cmp::max(1, me.target_lamports_per_signature / 20) as i64 * gap.signum();

                trace!(
                    "lamports_per_signature gap is {}, adjusting by {}",
                    gap,
                    gap_adjust
                );

                me.lamports_per_signature =
                    me.max_lamports_per_signature
                        .min(me.min_lamports_per_signature.max(
                            (base_fee_rate_governor.lamports_per_signature as i64 + gap_adjust)
                                as u64,
                        ));
            }
        } else { // 当没有设置target_signatures_per_slot时,链采用固定价格
            me.lamports_per_signature = base_fee_rate_governor.target_lamports_per_signature;
            me.min_lamports_per_signature = me.target_lamports_per_signature;
            me.max_lamports_per_signature = me.target_lamports_per_signature;
        }
        debug!(
            "new_derived(): lamports_per_signature: {}",
            me.lamports_per_signature
        );
        me
    }

分析汇总

  1. 当没有设置target_signatures_per_slot时,链采用固定价格
  2. 当设置target_signatures_per_slot时,最小价格为target-lamports-per-signature设置的50%,最高为 target-lamports-per-signature的10倍
    1. 当latest_signatures_per_slot <= target_signatures_per_slot/2时,返回target_lamports_per_signature的50%
    2. 当latest_signatures_per_slot >= target_signatures_per_slot/2 && latest_signatures_per_slot >= target_signatures_per_slot, 返回target_lamports_per_signature的50%->100%
    3. 当latest_signatures_per_slot >= target_signatures_per_slot && latest_signatures_per_slot <= target_signatures_per_slot * 10, 返回target_lamports_per_signature 1-10倍
    4. latest_signatures_per_slot >= target_signatures_per_slot * 10, 返回target_lamports_per_signature 10倍

数据测试demo

fn main() {
    let latest_signatures_per_slot = 1;
    let target_signatures_per_slot = 10;
    let target_lamports_per_signature = 100;
    let min_lamports_per_signature = std::cmp::max(1, target_lamports_per_signature / 2);
    let max_lamports_per_signature = target_lamports_per_signature * 10;
    let desired_lamports_per_signature =
                max_lamports_per_signature
                    .min(min_lamports_per_signature.max(
                        target_lamports_per_signature
                            * std::cmp::min(latest_signatures_per_slot, std::u32::MAX as u64)
                            / target_signatures_per_slot,
                    ));
    println!("{}", desired_lamports_per_signature);
}