|
|
4 tuần trước cách đây | |
|---|---|---|
| .. | ||
| src | 4 tuần trước cách đây | |
| .gitignore | 4 tuần trước cách đây | |
| Cargo.toml | 4 tuần trước cách đây | |
| Containerfile.capacity | 4 tuần trước cách đây | |
| Makefile | 4 tuần trước cách đây | |
| README.md | 4 tuần trước cách đây | |
Utilities for calibrating fee constants from resource usage measurements.
src/validator/fees.rs.FEE_CALL_GAS to report
gas_per_tx_with_fee.Low-level microbenchmark of WASM opcodes, hashes, signatures, and ZK circuits.
make bench
Writes bench_results.json (JSON on stdout, progress on stderr).
ZK proof files must be generated first:
cd ../zkvm-metering/generator
make
./generator
What it measures:
| Operation | Iterations |
|---|---|
| WASM opcode (add) | 1000000 |
| Poseidon, Sinsemilla hashes | 1000000 |
| Pallas Schnorr signature verify | 1000000 |
| ZK circuit verify (k=11, k=14) | 1000 |
| ZK circuit compile (verifying key build, k=11, k=14) | 1000 |
Timed closures exclude RNG, allocation, and formatting so the numbers reflect the primitive. ZK stats are reported per-row in nanoseconds.
In addition to the aggregate stats, bench emits a circuits map keyed
by contract circuit name (money/dao *.zk.bin). Each entry records k,
compile_p50_ns_per_row, vk_size_bytes, opcodes_count,
witnesses_count, and literals_count.
Standalone database microbenchmark. Measures sled I/O across four scenarios (set new key, overwrite, get, contains_key) and eight payload sizes (32b to 8KiB), fits a linear regression of ns/byte, and expresses the slopes as ratios against the WASM-add baseline.
make db_bench
Writes db_bench_results.json.
Measures per-tx gas and per-tx wall-clock time (verify + apply) across the scenarios below. Each scenario builds a batch of prebuilt transactions and runs it through the validator. Output is raw measurements (gas_per_tx, secs_per_tx).
Scenarios:
| Scenario | Shape |
|---|---|
| transfer_simple | transfer 1-in/2-out |
| transfer_20in_2out | transfer 20-in/2-out |
| transfer_1in_20out | transfer 1-in/20-out |
| dao_propose_20recip | DAO propose, 20 recipients |
| dao_exec_20recip | DAO exec, 20 recipients |
| dao_vote | DAO vote |
| otc_swap | OTC swap |
| token_mint | token mint |
| dao_mint | DAO mint |
| deploy_512kb | deploy 512 KiB WASM |
| deploy_1024kb | deploy 1024 KiB WASM |
| mixed | ~78% transfers, 10% votes, 6% execs, 4% mints, 2% deploys |
Run with:
make capacity
make capacity runs all scenarios. Set MONEY_WASM_PATH only when the
money contract WASM is not at the default source-tree path:
MONEY_WASM_PATH=/path/to/darkfi_money_contract.wasm make capacity
Timing: verification_secs is the median of 3 verify-only (write=false) runs. apply_secs comes from one verify+apply (write=true) pass, as max(0, apply_total - verification_secs). Verify-only trials reuse the same base state because a write=true run spends the prebuilt coins and would break the next trial. No explicit warmup is needed: building the transactions already executes each one once.
machine_info (CPU model, cores, RAM, disk type) is auto-detected and included in the output so runs from different machines can be grouped.
Example output:
{
"machine_info": { "cpu_model": "...", "physical_cores": 12, ... },
"results": [
{
"scenario": "transfer_20in_2out",
"gas_per_tx": 96336180.0,
"secs_per_tx": 0.326,
"tps": 3.07
}
]
}
Each result object also includes gas_per_tx_with_fee, fee_overhead_gas,
verify_fees, block_gas_limit, op_shape, tx_count, gas_used,
verification_secs, apply_secs, and total_secs (omitted above for
brevity).
The gas-model constants live in src/validator/fees.rs, plus
FEE_CALL_GAS in src/contract/money/src/client/fee_v1.rs. They are
expressed relative to a single WASM opcode (the wasm_add baseline). The
ratios are approximate. A given constant set should be calibrated
against the target validator hardware profile.
wasm_add below means the p50 of one WASM opcode (wasm_add.p50_ns from
bench, or wasm_add_p50_ns from db_bench). db_bench pre-divides its slopes
by wasm_add, so its ratios.* fields are already in gas units.
| Constant | Benchmark | Read from | Convert |
|---|---|---|---|
| POSEIDON_HASH_GAS | bench | poseidon_hash.p50_ns | / wasm_add.p50_ns |
| SINSEMILLA_HASH_GAS | bench | sinsemilla_hash.p50_ns | / wasm_add.p50_ns |
| PALLAS_SCHNORR_VERIFY_GAS | bench | pallas_signature_verify.p50_ns | / wasm_add.p50_ns |
| VERIFY_GAS_PER_ROW | bench | zk_verify.*.p50_ns | / wasm_add.p50_ns (already per-row) |
| COMPILE_GAS_PER_ROW | bench | zk_compile.*.p50_ns | / wasm_add.p50_ns (already per-row) |
| READ_GAS_PER_BYTE | db_bench | ratios.read_per_byte | already in gas units |
| WRITE_GAS_PER_BYTE | db_bench | ratios.write_new_per_byte | already in gas units |
| STATE_GROWTH_GAS | db_bench | db_set_new.intercept_ns | / wasm_add_p50_ns |
FEE_CALL_GAS is set conservatively (see fee_v1.rs and
doc/src/arch/fees.md); it does not require recalibration when gas
constants change because it carries deliberate headroom.
make bench and make db_bench (CPU-pinned): measure primitive
timings, then re-derive each constant from the ratios above.make capacity: record the new gas_per_tx per scenario.secs_per_tx (timing) only changes if the hardware or implementation
changed, not from constant edits.
A constant edit does not require re-running bench / db_bench — those
measure time, not gas. Gas is computed from the constants at runtime, so
only the gas-valued outputs drift. After editing the constant in
src/validator/fees.rs:
make capacity: every scenario that inserts keys gets a new
gas_per_tx; secs_per_tx is unchanged.gas_per_tx (below).Redo capacity after any fees.rs edit.
Pick the block gas limit L by combining gas_per_tx (hardware-independent)
with secs_per_tx per hardware tier:
time_bound_tps(h, s) = 1 / secs_per_tx(h, s)
gas_bound_tps(L, s) = L / gas_per_tx(s)
effective_tps(h, s, L) = min(time_bound_tps, gas_bound_tps)
Run capacity on each target hardware tier, sweep candidate L values, and pick the largest L where the slowest tier's worst-case block still fits within the block time. Any larger and validators get blocks they cannot process in time.