CHIP 2025-05 Native Elliptic Curve Arithmetic Operations

I’d like to introduce a proposal I put together to bring native elliptic curve arithmetic to the Bitcoin Cash VM. Specifically, I’m proposing the addition of OP_ECADD and OP_ECMUL to support elliptic curve point addition and scalar multiplication directly in script.

With native ECADD/ECMUL, BCH smart contracts would gain the ability to natively validate zero-knowledge proofs, enable signature aggregation, and lay the groundwork for scalable privacy and off-chain protocols like Bulletproofs – all without resorting to trusted setups or external proof systems.

While these operations can be approximated via covenants and loops, doing so comes at a massive cost in complexity, size, and execution cost. Native opcodes would make these systems practical and accessible.

This is the initial draft of the CHIP. Feedback is very welcome as we continue refining the proposal.

Looking forward to your feedbacks, questions and thoughts.

https://github.com/lightswarm124/bch-ec-arithmetic

9 Likes

I like this proposal initially.

What I am interested in, as usual, is what would the CPU cost of these operations?

Elliptic curve cryptography is used everywhere now, including SSH, of what I remember the SSH’s version is actually faster and simpler than many other algos that can be used.

But would that be the case here too?

I think I am optimistic, but I wouldn’t want the nodes to be burdened with too heavy math. Maybe some performance numbers/benchmarks could be determined experimentally during the CHIP process so that we know what kind of impact we are dealing with before we make the final decision?

What I am interested in, as usual, is what would the CPU cost of these operations?

I’m hoping to explore this as well and see what kind of vm limits would be appropriate to set for these operations. I’ll assume the multiplication will be more expensive than addition, but will definitely need to see some benchmarking to get a better sense of what range of operational costs will not over burden nodes while still providing the core functionalities.

Love this as a great area of research!

Is there any consideration to do with incoming quantum tech related to this?

1 Like

Not yet. As far as I can tell from what I looked up, this is just having arithmetic operations on the existing secp256k1 curve. If there are issues with secp256k1 with quantum, then this proposal, along with a whole bunch more cryptography we use in blockchain, will be impacted.

On the flipside, this proposal should just use the existing libsecp256k1 libraries that various blockchain projects are already using, so it would just be a matter of implementing the math behind EC arithmetic.

From what I heard from Hunter Beast, the author of BIP-360, Satoshi’s coins and taproot are vulnerable to quantum computing, and that P2PKH is somewhat safe from QC

3 Likes

Sharing some links I found helpful when I was learning about Chainlink VRF a while back:

Ethereum and ZCash both use alt_bc128 or BN-254 curve for zero knoelwdge proofs, with operations like ECADD, ECMUL and pairing checks. For Ethereum, precompiled contracts for elliptic curve operations are required in order to perform zkSNARK verification within the block gas limit.

4 Likes

EC_MUL is cheaper than OP_CHECKSIG or OP_CHECKDATASIG (because CDS uses EC_MUL internally + it does hashing)

EC_ADD is orders of magnitude cheaper

2 Likes

Just on a side note: [Functional] Quantum Computing does not (yet?) exist.

It’s all vaporware and handwaving so far.

It may never exist. Like energy-efficient fusion.

1 Like

Since these operations are already done by checksig/checkdatasig, they seem like relatively low-cost upgrades, and would be useful for a bunch of things outside of zk (say, doing something like EC Multiset but general purpose ). Is there a comparison to alternatives - exactly how costly would it be to do a multiplication and addition with loops?

1 Like

Since we are touching consensus again, it would generally make most sense to collect up multiple of these math operations together and implement them as a single upgrade.

Dividing mutiple small simple changes between multiple upgrades will create chaos and increase implementation cost across the entire ecosystem.

2 Likes

In order to emulate EC math, it seems we’ll need to implement every step in the secp256k1 group arithmetic. Roughly, that would equate to:

1. Finite‑Field Arithmetic Primitives - currently missing modular inverse, which might look something like this if we were to roll out our own implementation in Script

// Pseudocode in CashAssembly‑style

// Inputs: a, p (the prime)
// Outputs: inv = a⁻¹ mod p
// Maintains variables (a, b=p, x0=1, x1=0)

<E> OP_TOALTSTACK      // E = p
<A> OP_TOALTSTACK      // A = a

// x0=1, x1=0 on the stack as immediate constants
<1> <0>

// Loop until a == 1 or a == 0
OP_BEGIN
  // if a == 0, fail (no inverse)
  OP_DUP OP_0 OP_EQUALVERIFY  

  // q = b / a
  OP_FROMALTSTACK OP_SWAP   // bring b,a to top
  OP_DUP OP_HASH256 // not needed—just illustrative
  OP_DIV                   // q = b÷a

  // (b, a) ← (a, b mod a)
  OP_SWAP OP_MOD

  // (x0, x1) ← (x1, x0 − q·x1)
  OP_SWAP            // bring x0,x1
  OP_OVER OP_SWAP    // stack: x0,x1|x1,x0
  OP_OVER OP_MUL     // compute q·x1
  OP_SUB             // x0 − q·x1
  OP_SWAP            // new x1,x0

  // Continue looping while a > 1
  OP_DUP OP_1 OP_GREATERTHAN OP_ENDIF // jump back if a>1
OP_UNTIL
// Now x1 holds the inverse; reduce mod p

2. Point Addition for 2 points (x1, y1), (x2, y2)

  • Compute λ=(y2−y1)×inv(x2−x1)mod p\lambda = (y_2 - y_1)\times \text{inv}(x_2 - x_1)\mod pλ=(y2​−y1​)×inv(x2​−x1​)modp.
  • Compute x3=λ2−x1−x2x_3 = \lambda^2 - x_1 - x_2x3​=λ2−x1​−x2​.
  • Compute y3=λ (x1−x3)−y1y_3 = \lambda,(x_1 - x_3) - y_1y3​=λ(x1​−x3​)−y1​.

Each step is multiple multiplies, subs, and an extra inverse.

3. Scalar Multiplication

// binary expansion of k
// result = ∞
// for each bit of k (most to least):
//   result = ECADD(result, result)      // point doubling
//   if bit = 1: result = ECADD(result, P)

4. Curve‑Membership Checking

Before ever doing arithmetic, we must verify input points lie on
y2≡x3+7(modp)y^2 ≡ x^3 + 7 \pmod py2≡x3+7(modp): one OP_MUL , one OP_SUB , one OP_MOD , two OP_DIV

5. Looping & Stack‑Management

We’ll need to juggle at least 8–12 “registers” of big‑ints on the stack, managing the OP_SWAP / OP_TOALTSTACK choreography to keep the right values in place

I think with all these operations, we’ll easily hit the vm limit caps, increase unnecessary complexity and open DoS attack vectors with all these computations.

3 Likes

I’m currently looking for interesting problems to apply albaDsl to — especially where OP_EVAL can be utilized. The problem in this thread just became an obvious candidate.

My demo implementation of Elliptic curve multiplication on secp256k1 implemented in Bitcoin Cash script currently looks to be working. Example output from the REPL:

λ> ev (c (g # ecMul # getX)) 0xAA5E28D6A97A2479A65527F7290311A3624D4CC0FA1578598
EE3C2613BF99522

23960696573610029253367988531088137163395307586261939660421638862381187549638

This prints the x-coordinate of G multiplied by 0xAA5E28D6A97A2479A65527F7290311A3624D4CC0FA1578598.

This above is one of the test vectors from:
[https://crypto.stackexchange.com/questions/784/are-there-any-secp256k1-ecdsa-test-examples-available]

A multiplication takes a few seconds on the non-optimized albaVm on a laptop. The program itself is not optimized at all. With optimizations and running on BCHN I think this can be made orders of magnitude faster.

To make this work I raised the VM stack/cond-stack limits from 1000/100 to 5000/5000. With optimization, stack requirements could drop.

This example illustrates that it likely is possible to solve this kind of problem using BCH script. We just need to explore how performant it can be made.

Links:

4 Likes

Here are some other math operations that we could consider on top of ECADD and ECMUL.

Opcode Description Benefit (vs. emulation) Cost to Emulate in Script Risk/Complexity Notes & Recommendation
Basic Operations
OP_ECADD Point addition: given two secp256k1 points P, Q on the stack, pushes P+Q. ≈ >1000× faster than doing field operations + curve math in script. ~ 4000+ big‑int ops + looping (~200 K “unit” ops) Moderate: must validate inputs lie on curve, constant‑time implementation. Include: core building block for any EC work.
OP_ECMUL Scalar multiplication: given a point P and scalar k, pushes k·P. ≈ >10 000× faster than repeated doubling/add in script. ~ 100× OP_ECADD via double‑and‑add loop (≈ 400 K “unit” ops) Moderate: enforce 0<k<order, constant‑time ladder. Include: required to do any signature‑style verification or covenant logic.
Highly Useful
OP_MODINV Modular inversion: given nonzero a in 𝔽ₚ, returns a⁻¹ mod p. O(1) native vs. O(n²) exponentiation in script (≈ thousands of ops). ~ 5000+ big‑int ops + loops Must be constant‑time; must detect & reject a=0. Recommend: needed for slope computation in ECADD/ECDOUBLE and other field work.
OP_ECMULTGEN Generator mul: like OP_ECMUL(k, G), but 3× faster using precomputed G tables. ≈ 3× faster than generic ECMUL when one operand is known generator G. ≈ same cost as generic ECMUL in script Same checks as ECMUL; uses fixed-window tables. Strongly recommend if you plan any on‑chain Schnorr or MuSig verification.
Optional
OP_ECDOUBLE Point doubling: given a point P, pushes 2·P. ≈ 30–50% speedup in windowed ECMUL or multi‑add loops vs. two ECADD. N/A (would be 2× OP_ECADD) Same as ECADD. Optional: skip if you have ECMUL, but useful to speed up multi‑scalar routines.
OP_ECNEG Point negation: given P=(x,y), pushes –P=(x,−y). Native constant‑time negate vs. a handful of big‑int ops in script. ~ 20 big‑int ops Negligible. Optional: very cheap to emulate; lowest priority.
High‑Risk / Specialized
OP_DECOMPRESS Point decompress: given 33‑byte compressed P, pushes full 65‑byte (x,y). Saves 32 bytes per output + ~10× faster than script‑level sqrt. Emulate via modular sqrt ≈ O(p^¼) exponentiation → millions of ops Needs constant‑time sqrt, parity check, heavy code. Use with care: big chain‑savings but very tricky and DoS‑sensitive.
OP_ECMULTMULTI Multi‑scalar mult: given [kᵢ, Pᵢ] for i=1…n, pushes ∑kᵢ·Pᵢ sub‑linearly in n. Sub‑linear speedup vs. doing n separate ECMULs in script. ≥ n× generic ECMUL (linear) Must cap n, fixed-window, careful memory use. Only for very large batch ops (e.g. MuSig with many keys); otherwise too complex.
OP_PAIRING_CHECK BN‑pairing: verify pairing equation e(P, Q)… for SNARKs/BLS.* On‑chain SNARK/BLS proof with a single op vs. infeasible in script. Impossible in script Massive code size, DoS risk, consensus complexity. Not recommended—far too heavy & risky for BCH today.

For right now, it might be worth considering adding MODINV and ECMULTIGEN as these seem fairly useful without having cheap substitutes while still keeping to relatively safe computation. There are some like the one for on-chain SNARK/BLS proof, but I don’t think they are really needed for the near-term future until the tech gets a bit more mature

3 Likes

Might be worth looking into this chip for confidential amounts on BCH via bulletproofs. If i understand right, OP_ECADD/OP_ECMUL/OP_ECMULTMULTI + OP_MODINV would cover the range proofs with no trusted setup.

2 Likes

Coming from the Solana/ZK payments side. I built a shielded payroll protocol using Groth16 and ran into the same amount hiding wall from a different direction. Native EC ops would make confidential transactions practical for builders without requiring hand-rolled assembly workarounds so strong support for this CHIP.

4 Likes

My only concern is quantum threat, should we go ahead with these ops knowing it’s possible their usefulness has an expiration date?

1 Like

Welcome to BCH Research!

Glad to have you here. Especially good to see interest from Solana community members, who have a strong overlap with our philosophy but not as strong discussion channels between us. What was it that attracted you to BCH?

4 Likes

In the case of shielded pools that have confidential amounts specifically, it’s worth noting: Pedersen hiding is information-theoretic, so a future QC replaying old chain data can’t open the commitments themselves. The retroactive leak in the Monero case is the ECDH channel, which is the kind of surface that ML-KEM note delivery or a PQ NIKE-based exchange protects against.

What a QC does break is binding, i.e. forging proofs going forward. That’s where the design matters with a transparent-backed pool (BCH locked visibly into a covenant, confidential notes inside, redeem back out), the covenant is consensus-enforced to not release more than was locked. In Monero a binding break means undetectable counterfeit; here the worst case is bounded theft inside one pool, not supply inflation. And there’s no compact PQ drop-in for Pedersen + Bulletproofs today, lattice replacements are still research; the PQ-sound route that exists in principle is hash-based STARKs proving the same range and balance statements, just heavier, tens of KB vs ~700 bytes for a bulletproof.

Notably, that path needs zero new opcodes, it’s hashing plus field arithmetic, all live on CashVM today (SHA256, BigInt, loops, functions), waiting mainly on the TXv5 limit raise (op-cost budget feasibility still to be measured). Even Monero devs own answer to this concern is a migration timeline (Luke Parker from Monero proposed a 5-year PQ plan), so I see no reason to avoid EC. And to be clear on why the EC ops are needed at all: hiding itself costs nothing, a Pedersen commitment is just bytes the chain could carry blindly. The opcodes are for enforcement, the covenant checking that hidden amounts still obey the rules: the balance check (sum of input commitments equals sum of output commitments) is point addition, and the range-proof verify is scalar mult / one big MSM. Without them the chain can’t hold anyone to the commitments. The ops are cheap, reusing libsecp256k1, and as noted upthread ECMUL costs less than a CHECKSIG, which already does one internally. The STARK path is the later for the same layer, not a reason to withhold the now.

1 Like

Fair concern. However EC ops enable Pedersen commitments and Bulletproofs which are useful now regardless of the long-term quantum picture. The expressive VM argument cuts both ways here: if the VM can express any verifier in script, then when PQ-friendly proof systems mature, you swap the verifier without a consensus fork. EC ops don’t lock you in, they unlock confidential transactions now while the PQ layer catches

1 Like

If im being honest, it wasn’t BCH specifically that attracted me. I wasn’t explicitly poking around on here.
I built a shielded payroll protocol on Solana, had some non technical issues and stumbled on a friends project and joined his telegram. Then I met someone there who was solving the same amount-hiding problem from a completely different direction on BCH. The Nostr coordination layer and the expressive VM philosophy were things I hadn’t seen approached that way before. Plus The overlap in goals with very different constraints was too interesting to ignore. And very good discussions so far. I’m intrigued.
Thank you guys for having me

4 Likes