Blockchain Arithmetic: Examples
Each example is a verified run of a guided tour script from the shipped python/examples/
bundle (see PROGRESSION.md for the full 01→06 sequence). Run the guided tour
first: it narrates the scenario, explains each metric, and shows when to trust the result. Use
the production one-liner when wiring the same API call into your pipeline.
Beta release. Products in this catalog other than the SolvSRK family and SolvScout / SolvTune are beta — suitable for trials and evaluation; APIs and packaging may change before GA. Do not deploy beta builds in production programs without a signed agreement with Resonix. Activate a trial license before running examples — see Install and Licensing.
Journeys
Example 1: Journey 01 — First contact
Version, license, simplest successful call. Every support ticket starts with the package version. The C engine is machine-locked (Ed25519, SolvSRK model). license_valid() tells you whether this machine can run the gated functions.
Walkthrough:
-
What you are doing — blockchain_arithmetic is a C engine for consensus-critical integer and elliptic-curve math: 512-bit mul_div, AMM/vault accounting, secp256k1 scalars, Pedersen commitments, and Schnorr signatures. This journey confirms the wheel loads, shows your license state, and runs the single smallest exact call: mul_div.
-
Version — Every support ticket starts with the package version.
version: 0.3.0
-
License — The C engine is machine-locked (Ed25519, SolvSRK model). license_valid() tells you whether this machine can run the gated functions.
license_valid: True
-
Simplest call: mul_div — mul_div(a, b, denominator) returns floor(ab/denominator) using a full 512-bit intermediate, so it is exact even when ab overflows 64 bits. Here: 1e18 * 3e6 / 1e6 = 3e18, computed without loss.
a: 1e18b: 3e6denominator: 1e6result: 3000000000000000000— Exact integer result, no floating point, no overflow.
Guided tour output (from a verified run):
Version, license, simplest successful call
-- Act 1 - What you are doing --
-> blockchain_arithmetic is a C engine for consensus-critical integer and elliptic-curve math: 512-bit mul_div, AMM/vault accounting, secp256k1 scalars, Pedersen commitments, and Schnorr signatures. This journey confirms the wheel loads, shows your license state, and runs the single smallest exact call: mul_div.
-- Act 2 - Version --
-> Every support ticket starts with the package version.
version: 0.3.0
-- Act 3 - License --
-> The C engine is machine-locked (Ed25519, SolvSRK model). license_valid() tells you whether this machine can run the gated functions.
license_valid: True
-- Act 4 - Simplest call: mul_div --
-> mul_div(a, b, denominator) returns floor(a*b/denominator) using a full 512-bit intermediate, so it is exact even when a*b overflows 64 bits. Here: 1e18 * 3e6 / 1e6 = 3e18, computed without loss.
a: 1e18
b: 3e6
denominator: 1e6
result: 3000000000000000000
-> Exact integer result, no floating point, no overflow.
-- Run complete --
version: 0.3.0
mul_div: 3000000000000000000
next_journey: 02_fullmath_mul_div.pycd python
# Guided tour — narrated scenario walkthrough (recommended first run):
python examples/journeys/01_first_contact.py
# Production one-liner — same API call you ship:
python -c "import blockchain_arithmetic as ba; print(ba.__version__, ba.license_valid())"Example 2: Journey 02 — FullMath mul_div
Exact 512-bit intermediate vs naive uint64 overflow. a = b = 2^40, denominator = 2^30 (product is 2^80). compare_mul_div runs both the FullMath path and a naive uint64 path, and reports whether the naive path overflowed and how far it diverged.
Walkthrough:
-
Why FullMath exists — Uniswap-v3-style pricing multiplies two ~2^96 numbers before dividing. A naive uint64 a*b overflows and silently wraps, corrupting the price. FullMath keeps the product in 512 bits, divides, and returns the exact floor. Consensus code cannot tolerate the wrap.
-
A hard case — a = b = 2^40, denominator = 2^30 (product is 2^80).
a: 1099511627776b: 1099511627776denominator: 1073741824mul_div: 1125899906842624
-
Compare against the naive path — compare_mul_div runs both the FullMath path and a naive uint64 path, and reports whether the naive path overflowed and how far it diverged.
fullmath: 1125899906842624naive: 0divergence: 0fullmath_ok: Truenaive_overflow: True— The naive path overflows; FullMath does not. The divergence is the error you would ship if you used 64-bit multiply.
-
Rounding control — mul_div floors; mul_div_rounding_up ceils. Choose per direction so fees always round in the protocol's favor.
floor: 7ceil: 8
Guided tour output (from a verified run):
Exact 512-bit intermediate vs naive uint64 overflow
-- Act 1 - Why FullMath exists --
-> Uniswap-v3-style pricing multiplies two ~2^96 numbers before dividing. A naive uint64 a*b overflows and silently wraps, corrupting the price. FullMath keeps the product in 512 bits, divides, and returns the exact floor. Consensus code cannot tolerate the wrap.
-- Act 2 - A hard case --
-> a = b = 2^40, denominator = 2^30 (product is 2^80).
a: 1099511627776
b: 1099511627776
denominator: 1073741824
mul_div: 1125899906842624
-- Act 3 - Compare against the naive path --
-> compare_mul_div runs both the FullMath path and a naive uint64 path, and reports whether the naive path overflowed and how far it diverged.
fullmath: 1125899906842624
naive: 0
divergence: 0
fullmath_ok: True
naive_overflow: True
-> The naive path overflows; FullMath does not. The divergence is the error you would ship if you used 64-bit multiply.
-- Act 4 - Rounding control --
-> mul_div floors; mul_div_rounding_up ceils. Choose per direction so fees always round in the protocol's favor.
floor: 7
ceil: 8
-- Run complete --
fullmath: 1125899906842624
naive_overflow: True
next_journey: 03_amm_shares.pycd python
# Guided tour — narrated scenario walkthrough (recommended first run):
python examples/journeys/02_fullmath_mul_div.py
# Production one-liner — same API call you ship:
python -c "import blockchain_arithmetic as ba; print(ba.mul_div(2**64-1, 2**64-1, 2**63))"Example 3: Journey 03 — AMM swap + vault shares
Constant-product pricing, share accounting, MEV exposure. share_mint converts a deposit into shares against the current vault totals with floor rounding; share_redeem converts shares back to assets. An empty vault bootstraps 1:1. simulate_sandwich front-runs and back-runs a victim trade. It reports the attacker's profit and the victim's loss versus the fair execution.
Walkthrough:
-
Price a swap — amm_swap_x_for_y prices a constant-product (x*y=k) swap with a fee in basis points. A 100-unit swap into a balanced 1000/1000 pool at 30 bps returns 90 units out.
reserve_x: 1000reserve_y: 1000amount_in: 100fee_bps: 30amount_out: 90
-
Vault shares (ERC-4626 style) — share_mint converts a deposit into shares against the current vault totals with floor rounding; share_redeem converts shares back to assets. An empty vault bootstraps 1:1.
minted_shares: 1000redeemed_assets: 500
-
Sandwich attack exposure — simulate_sandwich front-runs and back-runs a victim trade. It reports the attacker's profit and the victim's loss versus the fair execution.
attacker_profit: 117victim_loss: 171victim_y: 816victim_fair_y: 987profitable: True
-
Bound it with the rate governor — simulate_sandwich_with_governor caps per-block price movement. The same attack becomes unprofitable once the move is clipped.
attacker_profit: -388was_clipped: Trueprofitable: False— The governor clips the price move and the MEV profit goes negative.
Guided tour output (from a verified run):
Constant-product pricing, share accounting, MEV exposure
-- Act 1 - Price a swap --
-> amm_swap_x_for_y prices a constant-product (x*y=k) swap with a fee in basis points. A 100-unit swap into a balanced 1000/1000 pool at 30 bps returns 90 units out.
reserve_x: 1000
reserve_y: 1000
amount_in: 100
fee_bps: 30
amount_out: 90
-- Act 2 - Vault shares (ERC-4626 style) --
-> share_mint converts a deposit into shares against the current vault totals with floor rounding; share_redeem converts shares back to assets. An empty vault bootstraps 1:1.
minted_shares: 1000
redeemed_assets: 500
-- Act 3 - Sandwich attack exposure --
-> simulate_sandwich front-runs and back-runs a victim trade. It reports the attacker's profit and the victim's loss versus the fair execution.
attacker_profit: 117
victim_loss: 171
victim_y: 816
victim_fair_y: 987
profitable: True
-- Act 4 - Bound it with the rate governor --
-> simulate_sandwich_with_governor caps per-block price movement. The same attack becomes unprofitable once the move is clipped.
attacker_profit: -388
was_clipped: True
profitable: False
-> The governor clips the price move and the MEV profit goes negative.
-- Run complete --
amount_out: 90
sandwich_profitable: True
governed_profitable: False
next_journey: 04_pedersen_schnorr.pycd python
# Guided tour — narrated scenario walkthrough (recommended first run):
python examples/journeys/03_amm_shares.py
# Production one-liner — same API call you ship:
python -c "import blockchain_arithmetic as ba; print(ba.amm_swap_x_for_y(1000, 1000, 100, fee_bps=30))"Example 4: Journey 04 — Pedersen commit + Schnorr sign/verify
Hide a value, prove it adds up, sign the transaction. Commitments add: commit(v1,r1) + commit(v2,r2) == commit(v1+v2, r1+r2). pedersen_homomorphic_check proves it, which is what lets a confidential transaction show inputs == outputs without revealing amounts. schnorr_sign(private, nonce, msg) returns (R, s); schnorr_verify checks it against the public key. Here we derive the pubkey from the secret and verify the signature we just produced.
Walkthrough:
-
Commit to a hidden value — pedersen_commit(value, blinding) returns C = valueH + blindingG on secp256k1. The commitment reveals nothing about the value, but binds the committer to it.
value: 42blinding: 12345commitment: 027fb7c235fe4cc07d4791f8bd380b5d5a62a89e95eaf441132e5f6477998e12ba
-
Homomorphic addition — Commitments add: commit(v1,r1) + commit(v2,r2) == commit(v1+v2, r1+r2). pedersen_homomorphic_check proves it, which is what lets a confidential transaction show inputs == outputs without revealing amounts.
matches: Truev_sum: 400r_sum: 600
-
Schnorr sign + verify — schnorr_sign(private, nonce, msg) returns (R, s); schnorr_verify checks it against the public key. Here we derive the pubkey from the secret and verify the signature we just produced.
public_key: 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798verified: True
-
Tamper check — Verification must fail if the message changes. Same signature, different message -> reject.
tampered_message_verified: False— Genuine message verifies; tampered message is rejected.
Guided tour output (from a verified run):
Hide a value, prove it adds up, sign the transaction
-- Act 1 - Commit to a hidden value --
-> pedersen_commit(value, blinding) returns C = value*H + blinding*G on secp256k1. The commitment reveals nothing about the value, but binds the committer to it.
value: 42
blinding: 12345
commitment: 027fb7c235fe4cc07d4791f8bd380b5d5a62a89e95eaf441132e5f6477998e12ba
-- Act 2 - Homomorphic addition --
-> Commitments add: commit(v1,r1) + commit(v2,r2) == commit(v1+v2, r1+r2). pedersen_homomorphic_check proves it, which is what lets a confidential transaction show inputs == outputs without revealing amounts.
matches: True
v_sum: 400
r_sum: 600
-- Act 3 - Schnorr sign + verify --
-> schnorr_sign(private, nonce, msg) returns (R, s); schnorr_verify checks it against the public key. Here we derive the pubkey from the secret and verify the signature we just produced.
public_key: 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
verified: True
-- Act 4 - Tamper check --
-> Verification must fail if the message changes. Same signature, different message -> reject.
tampered_message_verified: False
-> Genuine message verifies; tampered message is rejected.
-- Run complete --
commitment: 027fb7c235fe4cc07d...
homomorphic_matches: True
schnorr_verified: True
next_journey: 05_mimblewimble_fees.pycd python
# Guided tour — narrated scenario walkthrough (recommended first run):
python examples/journeys/04_pedersen_schnorr.py
# Production one-liner — same API call you ship:
python -c "import blockchain_arithmetic as ba; x=ba.scalar_from_int(1); k=ba.scalar_from_int(2); p=ba.pubkey_from_scalar(x); r,s=ba.schnorr_sign(x,k,b'msg'); print(ba.schnorr_verify(p, b'msg', r, s))"Example 5: Journey 05 — Mimblewimble balance + fee governors
Confidential balance, kernel excess, EIP-1559 / rate governor. A Mimblewimble transaction proves balance on commitments, not cleartext. mw_compute_kernel_excess sums blinding factors; mw_verify_tx_balance checks that the input/output commitments reconcile against that excess. eip1559_base_fee_update moves the base fee toward the target gas. A full block (30M gas vs 15M target) raises the fee by 12.5%.
Walkthrough:
-
Value balance — mw_check_value_balance verifies that inputs == outputs + fee in the clear-value model. Inputs [100,200] against output [300] balances at fee=0 and fails at fee=1.
balanced_fee0: Truebalanced_fee1: False
-
Kernel excess + commitment balance — A Mimblewimble transaction proves balance on commitments, not cleartext. mw_compute_kernel_excess sums blinding factors; mw_verify_tx_balance checks that the input/output commitments reconcile against that excess.
kernel_excess: 0tx_balanced: True
-
EIP-1559 base fee — eip1559_base_fee_update moves the base fee toward the target gas. A full block (30M gas vs 15M target) raises the fee by 12.5%.
full_block_fee: 1125steady_block_fee: 1000
-
Rate governor — rate_governor_fee_update is the bounded-move fee controller: it raises the fee on overutilization but caps the per-step change, so fee shocks stay inside a safe band.
prev_fee: 1000governed_fee: 1050— Integer-exact fee math: no floats, deterministic across nodes.
Guided tour output (from a verified run):
Confidential balance, kernel excess, EIP-1559 / rate governor
-- Act 1 - Value balance --
-> mw_check_value_balance verifies that inputs == outputs + fee in the clear-value model. Inputs [100,200] against output [300] balances at fee=0 and fails at fee=1.
balanced_fee0: True
balanced_fee1: False
-- Act 2 - Kernel excess + commitment balance --
-> A Mimblewimble transaction proves balance on commitments, not cleartext. mw_compute_kernel_excess sums blinding factors; mw_verify_tx_balance checks that the input/output commitments reconcile against that excess.
kernel_excess: 0
tx_balanced: True
-- Act 3 - EIP-1559 base fee --
-> eip1559_base_fee_update moves the base fee toward the target gas. A full block (30M gas vs 15M target) raises the fee by 12.5%.
full_block_fee: 1125
steady_block_fee: 1000
-- Act 4 - Rate governor --
-> rate_governor_fee_update is the bounded-move fee controller: it raises the fee on overutilization but caps the per-step change, so fee shocks stay inside a safe band.
prev_fee: 1000
governed_fee: 1050
-> Integer-exact fee math: no floats, deterministic across nodes.
-- Run complete --
tx_balanced: True
eip1559_full: 1125
governed_fee: 1050
next_journey: 06_limits.pycd python
# Guided tour — narrated scenario walkthrough (recommended first run):
python examples/journeys/05_mimblewimble_fees.py
# Production one-liner — same API call you ship:
python -c "import blockchain_arithmetic as ba; print(ba.mw_check_value_balance([100, 200], [300], fee=0), ba.eip1559_base_fee_update(1000, 30_000_000, ba.EIP1559_TARGET_GAS))"Example 6: Journey 06 — Limits / when not to use
uint64 economic domain, dead-zone scalars, honest scope. For secp256k1 economic reasoning the library flags scalars outside the economically meaningful range. A value above 2^64 is a 'dead zone' scalar: valid on the curve, but not an economic quantity. div_ordering shows that ab/c, (a/c)b, and a(b/c) diverge under integer truncation. Use mul_div (ab then /c) for the exact floor; the other orderings are there to demonstrate the trap, not to use in production.
Walkthrough:
-
The economic domain is uint64 — AMM/vault/fee inputs are unsigned 64-bit. Token amounts scaled to 18 decimals fit comfortably (1e18 << 2^64), but you must keep quantities inside uint64. mul_div's 512-bit intermediate protects the PRODUCT, not arbitrary-precision inputs.
uint64_max: 18446744073709551615one_token_18dp: 1000000000000000000
-
Dead-zone scalars — For secp256k1 economic reasoning the library flags scalars outside the economically meaningful range. A value above 2^64 is a 'dead zone' scalar: valid on the curve, but not an economic quantity.
big_dead_zone: Truebig_is_economic: Falsesmall_is_economic: True
-
Ordering matters — div_ordering shows that ab/c, (a/c)b, and a(b/c) diverge under integer truncation. Use mul_div (ab then /c) for the exact floor; the other orderings are there to demonstrate the trap, not to use in production.
abc_fullmath: 1000001a_bc: 0ac_b: 999999max_divergence: 1000001
-
What this is NOT — Not a full node, wallet, or consensus client. Not a bignum library for arbitrary precision. Not a substitute for a full ZK range-proof system (it sizes bulletproofs, it does not generate them). It is the exact integer + curve arithmetic layer other systems build on.
Guided tour output (from a verified run):
uint64 economic domain, dead-zone scalars, honest scope
-- Act 1 - The economic domain is uint64 --
-> AMM/vault/fee inputs are unsigned 64-bit. Token amounts scaled to 18 decimals fit comfortably (1e18 << 2^64), but you must keep quantities inside uint64. mul_div's 512-bit intermediate protects the PRODUCT, not arbitrary-precision inputs.
uint64_max: 18446744073709551615
one_token_18dp: 1000000000000000000
-- Act 2 - Dead-zone scalars --
-> For secp256k1 economic reasoning the library flags scalars outside the economically meaningful range. A value above 2^64 is a 'dead zone' scalar: valid on the curve, but not an economic quantity.
big_dead_zone: True
big_is_economic: False
small_is_economic: True
-- Act 3 - Ordering matters --
-> div_ordering shows that a*b/c, (a/c)*b, and a*(b/c) diverge under integer truncation. Use mul_div (a*b then /c) for the exact floor; the other orderings are there to demonstrate the trap, not to use in production.
abc_fullmath: 1000001
a_bc: 0
ac_b: 999999
max_divergence: 1000001
-- Act 4 - What this is NOT --
-> Not a full node, wallet, or consensus client. Not a bignum library for arbitrary precision. Not a substitute for a full ZK range-proof system (it sizes bulletproofs, it does not generate them). It is the exact integer + curve arithmetic layer other systems build on.
-- Run complete --
dead_zone_flagged: True
ordering_max_divergence: 1000001
next_journey: (suite complete - see PROGRESSION.md)cd python
# Guided tour — narrated scenario walkthrough (recommended first run):
python examples/journeys/06_limits.py
# Production one-liner — same API call you ship:
python -c "import blockchain_arithmetic as ba; print(ba.scalar_dead_zone(ba.scalar_from_int((1<<64)+1)))"Example bundle
Every journey is a domain scenario with narrated acts — run the guided tour first to see what each number means, then copy the production one-liner into your pipeline.
| Resource | Purpose |
|---|---|
PROGRESSION.md | Ordered runbook — journeys 01→06 with dual commands |
COVERAGE.md | Capability matrix — which APIs each journey exercises |
APPLICATIONS.md | Where the product applies in real programs |
run_examples.py | Interactive menu to launch any journey |
Guided journeys
| # | Script | Scenario |
|---|---|---|
| 01 | 01_first_contact.py | Version, license, simplest successful call |
| 02 | 02_fullmath_mul_div.py | Exact 512-bit intermediate vs naive uint64 overflow |
| 03 | 03_amm_shares.py | Constant-product pricing, share accounting, MEV exposure |
| 04 | 04_pedersen_schnorr.py | Hide a value, prove it adds up, sign the transaction |
| 05 | 05_mimblewimble_fees.py | Confidential balance, kernel excess, EIP-1559 / rate governor |
| 06 | 06_limits.py | uint64 economic domain, dead-zone scalars, honest scope |
Run from the python/ directory after install and license activation.
Set BLOCKCHAIN_QUIET=1 only when you want silent CLI runs (no narration).