Product documentation — installation, licensing, and integration guides.
Blockchain Arithmetic
Examples

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:

  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.

  2. Version — Every support ticket starts with the package version.

    • version: 0.3.0
  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
  4. 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: 1e18
    • b: 3e6
    • denominator: 1e6
    • result: 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.py
cd 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:

  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.

  2. A hard case — a = b = 2^40, denominator = 2^30 (product is 2^80).

    • a: 1099511627776
    • b: 1099511627776
    • denominator: 1073741824
    • mul_div: 1125899906842624
  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.
  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

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.py
cd 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:

  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
  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
  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
  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.

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.py
cd 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:

  1. 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: 42
    • blinding: 12345
    • commitment: 027fb7c235fe4cc07d4791f8bd380b5d5a62a89e95eaf441132e5f6477998e12ba
  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
  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
  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.

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.py
cd 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:

  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
  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
  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
  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.

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.py
cd 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:

  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
  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
  3. 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: 1000001
    • a_bc: 0
    • ac_b: 999999
    • max_divergence: 1000001
  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.

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.

ResourcePurpose
PROGRESSION.mdOrdered runbook — journeys 01→06 with dual commands
COVERAGE.mdCapability matrix — which APIs each journey exercises
APPLICATIONS.mdWhere the product applies in real programs
run_examples.pyInteractive menu to launch any journey

Guided journeys

#ScriptScenario
0101_first_contact.pyVersion, license, simplest successful call
0202_fullmath_mul_div.pyExact 512-bit intermediate vs naive uint64 overflow
0303_amm_shares.pyConstant-product pricing, share accounting, MEV exposure
0404_pedersen_schnorr.pyHide a value, prove it adds up, sign the transaction
0505_mimblewimble_fees.pyConfidential balance, kernel excess, EIP-1559 / rate governor
0606_limits.pyuint64 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).