Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create bigint_modexp.md #198

Merged
merged 17 commits into from
Mar 27, 2018
Merged

Create bigint_modexp.md #198

merged 17 commits into from
Mar 27, 2018

Conversation

vbuterin
Copy link
Contributor

Precompile for bigint modular exponentiation. Meant to supersede #101.


<length_of_BASE> <length_of_EXPONENT> <length_of_MODULUS> <BASE> <EXPONENT> <MODULUS>

Where every length is a 32-byte left-padded integer representing the number of bytes to be taken up by the next value. Call data is assumed to be infinitely right-padded with zero bytes, and excess data is ignored. Consumes `floor(max(length_of_MODULUS, length_of_BASE) ** 2 * max(length_of_EXPONENT, 1) / GQUADDIVISOR)` gas, and if there is enough gas, returns an output `(BASE**EXPONENT) % MODULUS` as a byte array with the same length as the modulus.
Copy link
Member

@axic axic Feb 6, 2017

Choose a reason for hiding this comment

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

Would it be safe assuming that it is unlikely to have calls consuming gigabytes of data?

If yes, how about making each length field 32 bits wide (or even less):

     00000001
     00000020
     00000020
     03
     fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e
     fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f

I understand we have 0 gas for 0 bytes in the payload, but does that make any sense?

Copy link
Member

Choose a reason for hiding this comment

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

"representing the number of bytes to be taken up by the next value" <- I don't think this is correct anymore. It used to be like that in the initial drafts, but not anymore.

Copy link

Choose a reason for hiding this comment

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

Zasss..

@vbuterin
Copy link
Contributor Author

I like 32 bytes more for two reasons:

  1. Similarity to how the existing ABI works, and generally how ethereum works (we don't really do static sizes other than 32 at this point)
  2. It's actually easier to pack 32 bytes in EVM than it is to pack 4 bytes in EVM; the latter requires some arithmetic manipulations to fit the slice in, whereas the former is the same width as MLOAD/MSTORE so it works directly.

@axic
Copy link
Member

axic commented Feb 11, 2017

It's actually easier to pack 32 bytes in EVM than it is to pack 4 bytes in EVM

We could also pack them into a single 32 byte slot, that would make it easier. That would only need multiplication (2 times) and a single mstore.

If however the motivation is to make it easy on ABI encoding, then I would change the gas calculation not to be based on supplied length, but based on first byte set. That would allow sending each field as a multiple of 32 bytes.

Your example would become:

     0000000000000000000000000000000000000000000000000000000000000020
     0000000000000000000000000000000000000000000000000000000000000020
     0000000000000000000000000000000000000000000000000000000000000020
     0000000000000000000000000000000000000000000000000000000000000003
     fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e
     fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f

This way it is up to the caller's implementation to decide which is more beneficial: allocating more memory or using more instructions to pack them tight.

@Souptacular
Copy link
Contributor

Please make compliant with EIP-0 (eg, add a header with number/status etc), renumber to EIP 198 (or the issue number), update in response to any comments, and tag with editor-needs-to-review when it's ready for merge.

@pirapira
Copy link
Member

pirapira commented Mar 3, 2017

@vbuterin What is the value of (0 ** 0) % 10000? Zero or one? Maybe one because PUSH_1 0 PUSH_1 0 EXP results in one.

fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e
fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f

Would be parsed as a base of 0, exponent of `2**256 - 2**32 - 978` and modulus of `2**256 - 2**32 - 978`, and so would return 0. Notice how if the length_of_BASE is 0, then it does not interpret _any_ data as the base, instead immediately interpreting the next 32 bytes as length_of_EXPONENT.

Choose a reason for hiding this comment

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

length_of_EXPONENT -> EXPONENT?

Copy link
Member

Choose a reason for hiding this comment

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

Why? BASE is followed by length_of_EXPONENT.

Choose a reason for hiding this comment

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

L9: <length_of_BASE> <length_of_EXPONENT> <length_of_MODULUS> <BASE> <EXPONENT> <MODULUS>

Since length_of_BASE is zero, it does not interpret any data as the base. The following 32 bytes (after the zero-length BASE) are the EXPONENT, not the length_of_EXPONENT.

Copy link
Member

Choose a reason for hiding this comment

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

Also, modulus is interpreted as 2**256 - 2**32 - 977

@pirapira
Copy link
Member

pirapira commented Mar 15, 2017 via email

fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd

Would parse a base length of 0, a modulus length of 32, and an exponent length of `2**256 - 1`, where the base is empty, the modulus is `2**256 - 2` and the exponent is `(2**256 - 3) * 256**(2**256 - 33)` (yes, that's a really big number). It would then immediately fail, as it's not possible to provide enough gas to make that computation.
Copy link
Member

Choose a reason for hiding this comment

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

This is base of length 0, an exponent of length 32 and modulus of length 2**256 - 1.
The exponent is 2**256 - 2, the modulus is (2**256 - 3) * 256**(2**256 - 33)

Copy link
Member

Choose a reason for hiding this comment

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

This seems correct. I apply this change.

@Arachnid
Copy link
Contributor

Please update to follow the template here and rename to eip-198.md, and we'll merge as draft.

@axic
Copy link
Member

axic commented Apr 23, 2017

I would change the gas calculation not to be based on supplied length, but based on first byte set. That would allow sending each field as a multiple of 32 bytes.

I would like to propose this again. This enables callers to save on gas costs. (See the explanation above)

@vbuterin ?

@chfast
Copy link
Member

chfast commented Apr 23, 2017

I support for paying only for significant bytes in the provided data (the same way it is done for exponent of EXP).

If the field lengths are known at the "compile" time in most of the use cases, can we represent all lengths in a single word, with 32-bit reserved per field length?

  • When the lengths are combined (and known up-front) we have: PUSH 0x200000002000000020 PUSH 0x00 MSTORE (13 bytes of code).
  • When the lengths occupy a word each we have: PUSH 0x20 PUSH 0x00 MSTORE PUSH 0x20 PUSH 0x01 MSTORE PUSH 0x20 PUSH 0x02 MSTORE (15 bytes of code).

@pirapira
Copy link
Member

This PR is meant to replace #101, but I'm not seeing big int addition, subtraction, multiplication or division in this PR. Are they going to be added or not? This affects the choice of addresses for the following precompiled contracts.

@pirapira
Copy link
Member

pirapira commented Apr 24, 2017

Since #101 and #198 use different addresses, there is uncertainty about what address is assigned to which contract. I added [WIP] in the title. I was trying to change my PR in yellowpaper repository.

@mkalinin mkalinin mentioned this pull request Aug 25, 2017
13 tasks
@riordant
Copy link

What is recommended for doing bigint division now that the division precompile was removed? Currently I am getting the reciprocal of the divisor using the Newton-Raphson method and multiplying with the dividend using this contract. Is that sufficient?

@tristanhoy
Copy link

Division is incredibly slow - but there is an alternative for some cases.

Modular reduction (and therefore exponentiation) for any cryptographic scheme operating over a public prime group (Schnorr, ECC, ElGamal) can be massively sped up when a prime is chosen that is close to a power of two (e.g. 2^255 - 19, 2^3072 - 77405 etc).

The algorithm is really simple: https://gist.github.com/tristanhoy/01450b820864aa7205587581c7b12099

Additionally, if a set of recommended public primes are provided, the gas costs for exponentiation will be very predictable (unlike the product of two secret primes).

@pirapira
Copy link
Member

pirapira commented Dec 1, 2017

@vbuterin do you mind if I append

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

?

@tinybike tinybike mentioned this pull request Jan 9, 2018
pirapira added a commit to pirapira/yellowpaper that referenced this pull request Jan 17, 2018
Because ethereum/EIPs#198 supersedes ethereum/EIPs#101 and the new version does not contain these.
pirapira added a commit to pirapira/yellowpaper that referenced this pull request Jan 17, 2018
pirapira added a commit to pirapira/yellowpaper that referenced this pull request Jan 19, 2018
pirapira added a commit to pirapira/yellowpaper that referenced this pull request Jan 19, 2018
@fulldecent
Copy link
Contributor

@Arachnid You nominated this as an "EIPs that should be merged". Can you please share your notes on that here?

@Arachnid
Copy link
Contributor

This pull request is referenced by #609, which has already been merged. As such, it needs to either be finalised and merged, or the dependency in the existing EIP needs to be removed.

Arachnid and others added 2 commits March 25, 2018 17:56
Rename bigint_modexp.md to eip-198.md, add new prologue and copyrigt notice
@Arachnid Arachnid merged commit a76a0a0 into master Mar 27, 2018
@Arachnid Arachnid deleted the vbuterin-patch-2 branch March 27, 2018 14:34
@Arachnid
Copy link
Contributor

This is a courtesy notice to let you know that the format for EIPs has been modified slightly. If you want your draft merged, you will need to make some small changes to how your EIP is formatted:

  • Frontmatter is now contained between lines with only a triple dash ('---')
  • Headers in the frontmatter are now lowercase.

If your PR is editing an existing EIP rather than creating a new one, this has already been done for you, and you need only rebase your PR.

In addition, a continuous build has been setup, which will check your PR against the rules for EIP formatting automatically once you update your PR. This build ensures all required headers are present, as well as performing a number of other checks.

Please rebase your PR against the latest master, and edit your PR to use the above format for frontmatter. For convenience, here's a sample header you can copy and adapt:

---
eip: <num>
title: <title>
author: <author>
type: [Standards Track|Informational|Meta]
category: [Core|Networking|Interface|ERC] (for type: Standards Track only)
status: Draft
created: <date>
---

Arachnid pushed a commit to Arachnid/EIPs that referenced this pull request Mar 27, 2018
* Create bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Update bigint_modexp.md

* Fixing an example after the specification change

https://github.com/ethereum/EIPs/pull/198/files#r106236783

* Fix one example after a format change

https://github.com/ethereum/EIPs/pull/198/files#r109660742

* Rename bigint_modexp.md to eip-198.md, add new prologue and copyright notice.
@Akrom99
Copy link

Akrom99 commented Jun 13, 2024

Good projeck

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.