Skip to content

Conversation

euonymos
Copy link

@euonymos euonymos commented Sep 15, 2025

While working on the Hydrozoa project, we decided to use pair-based accumulators as part of ZKifing proofs of membership for the L2 utxo set in the rule-based regime. We are pretty happy with the results, since KZG commitments are easier to work with than Merkle tree-like structures we wanted to use previously.

Operations over scalars for BLS12-381 in Plutus might require some improvements; probably it will become the next bottleneck for this particular use case after MSM makes it to Plutus, as our benchmarks suggest.

By drafting this CIP, I mostly wanted to share those results with the community and establish a place for a potential discussion on the topic, since the current state of things feels a bit rough around the edges, at least it questions Scalar module in Aiken and other frameworks (initially we ported it to Scalus, but now we likely will use unbounded integers as this approach proves to be less expensive).

I am happy to hear from everyone who has a take or related ideas. Thanks.

Link for reading current version: here

@jmagan
Copy link
Contributor

jmagan commented Sep 16, 2025

I think this CIP will add considerable value to the ZK capabilities in Cardano L1. The rationale is correct and spot-on regarding one of the biggest use cases where we encounter these Plutus/Plinth limitations. It's quite unfortunate that we almost exhaust the Plutus execution budget with just a few elements using bilinear accumulators, and it's even worse to consider that most of the budget is spent on unoptimized 'simple' multiplication and addition operations on Fr.

I have a couple of observations:

  • The introduction of a new type to represent Fr could be avoided since we currently abstract it using Integer in other BLS operations. This is already mentioned in the CIP, and I think it would be more flexible to handle the conversion in the binding layer.
  • As @euonymos mentioned, I would add all the Fr-related operations natively supported in blst. These could be useful later for creating algorithms in embedded curves like JubJub, namely inversion.

@rphair rphair changed the title CIP-? | Efficient scalars for BLS12-381 CIP-???? | Efficient scalars for BLS12-381 Sep 16, 2025
@rphair rphair added Category: Plutus Proposals belonging to the 'Plutus' category. State: Triage Applied to new PR afer editor cleanup on GitHub, pending CIP meeting introduction. labels Sep 16, 2025
Copy link
Collaborator

@rphair rphair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagging Triage to introduce at the CIP meeting in a few hours: https://hackmd.io/@cip-editors/119

@euonymos it's nice to see that Plutus expert review has already started & as usual we would be happy to hear from @zliu41 @effectfully @kwxm and others about this.

and considers different ways of evolving Plutus
toward efficient implementation of scalars for BLS12-381 curve.

## Motivation: why is this CIP necessary?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the subsections her actually belong in the Rationale section, in which implementation details and comparative approaches are considered. This includes performance considerations for what you have simply described the need for doing here in the Motivation section.

Comment on lines +135 to +139
```aiignore
(a, 1) final_poly_int

memory units cpu units
⡁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⢀⠕⡁ 5189564.0 ⡁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⠀⠁⠈⢀⠕⡁ 1669321088.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would serve this CIP & the repository well, by assuring portability / readability / responsiveness, if you could implement these graphs in Mermaid (I think the same set of points that produced the text renderings can be applied to a graph). And if & when someday it is possible for an AI to interpret these graphs, that would make it more achievable.

@rphair
Copy link
Collaborator

rphair commented Sep 16, 2025

@euonymos we decided to leave this in Triage because this was submitted shortly before today's CIP meeting and therefore to allow time for the already tagged Plutus reviewers to contribute their assessment about whether this change is doable (if not planned already).

A potential benefit for prompt review was also suggested at the meeting: the upcoming mid-term hard fork, in which some similar improvements for curve primitive support is planned, might also be able to include this change.

@euonymos
Copy link
Author

  • The introduction of a new type to represent Fr could be avoided since we currently abstract it using Integer in other BLS operations. This is already mentioned in the CIP, and I think it would be more flexible to handle the conversion in the binding layer.

Yes, this would be ideal since otherwise, we would end up having two sets of functions - old for integers and new for Fr. But how can we decide whether and Integer arguments belong to a field? Another thing to consider is that if we munge to/from Montgomery representation on every operation, it will be prohibitively wasteful.

And speaking more broadly, do we want to support only the scalar field of BLS of prime fields in general, at the level of Plutus API, in case we add another curve in the future, for example?

@euonymos
Copy link
Author

It would be nice to hear the thoughts of the Plutus team @effectfully @ana-pantilie @zliu41 @SeungheonOh.

@rphair
Copy link
Collaborator

rphair commented Sep 30, 2025

Still hoping for Plutus participation... there were some likely reviewers at the CIP meeting today, but discussion went entirely towards Leios CIP review due to massive turnout of those stakeholders & concerned devs. I think we are on track to consider this as a candidate at the following CIP meeting: https://hackmd.io/@cip-editors/121

@kwxm
Copy link
Contributor

kwxm commented Oct 1, 2025

Still hoping for Plutus participation...

I'll try to take a close look at this by the end of the week. Sorry for the delay.

Copy link

@SeungheonOh SeungheonOh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments. Thanks for the nice writing and nice plots. These seem like a reasonable and very useful addition.

With addition of new type for scalar in $F_r$, I think we should change existing builtins(i.e. scalar multiplication in $G1$ and $G2$) to use the new $F_r$ scalar. This does require changing existing builtins similar to how we have different semantics variant.

(which corresponds to `blst_fr` type) can be used along with introducing and eliminating from/to a _byte string_:

```
bytestring_to_bls12_381_fr: [bool, 𝚋𝚢𝚝𝚎𝚜𝚝𝚛𝚒𝚗𝚐] -> bls12_381_fr

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it

bytestring_to_bls12_381_fr: bool -> bytestring -> bls12_381_fr

or

bytestring_to_bls12_381_fr: [(bool, bytestring)] -> bls12_381_fr

I assume it's former. It's just a bit confusing; please update to clarify. Same goes with other ones below.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also these belong in the below section in "Function definition"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the shared correspondence between the underlying blst lib it is

bytestring_to_bls12_381_fr: bool -> bytestring -> bls12_381_fr

is understandable but not quite satisfying for several reasons.

The main argument showcased by this use case is that the significant share of work
(20% using pointwise multiplication, which will be bigger with MSM)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

20% of onchain exbudget I assume?

```
TBD: Scalar and multi-scalar multiplication in $G1$ and $G2$ are typical downstream functions
for `bls12_381_fr` values, but in the current Plutus, they use integers, i.e., double conversion is needed:
`bls12_381_fr -> bytestring -> integer` to call them.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: this looks like a type signature. It'd be better to write out

"bls12_381_fr to bytestring to integer"

|---------------------:|---------------|---------|---------------|---------|--------------|
| **(a)** Coefficients | 1_669_321_088 | 19% | 1_847_736_704 | 21% | +178_415_616 |
| **(b)** Commitment | 5_908_456_448 | 68% | 5_892_875_264 | 67% | −15_581_184 |
| **(c)** Pairing | 1_098_158_336 | 13% | 1_098_158_336 | 12% | - |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come "percent" for 1 is 13% and for 2 is 12% when they have exactly same CPU budget?

also diff is 0 for consistency.

* It's counterintuitive since it clashes with the mental model of the finite field.
* Representation of field elements as `Integers` (and even worse, peculiarities of the cost model as we saw)
pushes developers to use unbounded integers, which may lead to misunderstanding and unexpected bugs.
* It complicates the cost model by (mis)using `Integer` type for scalars.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cost of integer operation depends on the sizes of integers used. So it doesn't really complicate cost in perspective of VM. Not sure how else using Integer can complicates the cost model.

@perturbing
Copy link
Collaborator

@jmagan

can you explain what exactly you mean with

The introduction of a new type to represent Fr could be avoided since we currently abstract it using Integer in other BLS operations. This is already mentioned in the CIP, and I think it would be more flexible to handle the conversion in the binding layer.

@jmagan
Copy link
Contributor

jmagan commented Oct 6, 2025

@perturbing

I initially thought that $F_r$ was a simpler type — essentially an Integer reduced modulo r, similar to Scalar. However, that’s not the case: it’s actually an opaque type that stores the value in Montgomery form.

My first idea was to use plain Integer instead, abstracting away the $F_r$ type, much like we do in the scalar point multiplication primitive of BLS.

Mainly because I think using the blst conversion interface approach could cause problems within Plutus scripts. For instance, in polynomial multiplication (e.g., when constructing a polynomial from terms like $(x - a_n)$, we’d need to convert every $a_n$ term to $F_r$, perform the multiplication, and then convert back to Integer. This could be significantly more budget-expensive than performing the operations directly on integers.

Moreover, the use of Fr here doesn’t seem to provide any additional benefit, since the Montgomery representation is mainly an internal optimization for arithmetic efficiency.

That’s why I was considering keeping Fr as an internal detail, only using it at the interface between Plutus and the blst library. Exposing it more widely to end users might not add much value. However, as @euonymos pointed out, this could also become computationally expensive, since every function argument and return value would require a conversion between Integer and Fr.

@rphair rphair changed the title CIP-???? | Efficient scalars for BLS12-381 CIP-0166? | Efficient scalars for BLS12-381 Oct 14, 2025
Copy link
Collaborator

@rphair rphair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accepted as CIP candidate at today's CIP meeting based mainly on positive response from Plutus stakeholders. @euonymos please rename this directory to CIP-0166 and update your "Link for reading current version" 🎉

@rphair rphair added State: Confirmed Candiate with CIP number (new PR) or update under review. and removed State: Triage Applied to new PR afer editor cleanup on GitHub, pending CIP meeting introduction. labels Oct 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Category: Plutus Proposals belonging to the 'Plutus' category. State: Confirmed Candiate with CIP number (new PR) or update under review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants