-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Precompiles for bigint arithmetic #101
Comments
I think a justification why this problem should be solved using precompiles should be added here, including gas costs and runtime performance of the most efficient EVM assembly implementation. One thing specifically to note about addition and subtraction: At least the Y value has to be copied around in memory at least once before the call to the precompile (probably both X, Y and the result will be copied around). If this is done using a loop, the loop itself should already take almost the same gas and runtime costs as an addition implemented in EVM assembly. |
Why should these be precompiles and not instructions? Efficient bigint arithmetic generally requires coding fairly close to the metal - C and assembly tuned to the platform. |
Update: confirmed by @vbuterin that the original is correct. |
@obscuren : I am curious to test bigint compatibility with go, |
This is partially superseded by #198 |
Because ethereum/EIPs#198 supersedes ethereum/EIPs#101 and the new version does not contain these.
Because ethereum/EIPs#198 supersedes ethereum/EIPs#101 and the new version does not contain these.
There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review. |
This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment. |
Parameters
GADDSUBBASE
: 15GMULDIVBASE
: 30GMODEXPBASE
: 45GARITHWORD
: 6GQUADDIVISOR
: 32METROPOLIS_FORK_BLKNUM
: TBASpecification
If
block.number > METROPOLIS_FORK_BLKNUM
, then:At the address
0x0000....05
, add a precompile that expects input in the following format:This should then return the output:
There are no leading zero bytes in the output; if
X + Y = 0
it returns an empty array. An exception is thrown if the input data is shorter than the amount specified forX
(eg. if the length of X is specified as 42 bytes but the total data size is 72 bytes so only 40 bytes for X are present).X
andY
are interpreted as big endian integers; leading zero bytes inX
orY
are allowed. Gas costGADDSUBBASE + GARITHWORD * ceil(<total length of input data> / 32)
.At the address
0x0000....06
, add a precompile that works similarly, but returnsX - Y
in the same format. Throws ifX < Y
. Same gas cost as for addition above.At the address
0x0000....07
, add a precompile that works similarly, but returnsX * Y
in the same format. Gas costGMULDIVBASE + GARITHWORD * ceil(<total length of input data> / 32) + <length of X> * <length of Y> / GQUADDIVISOR
.At the address
0x0000....08
, add a precompile that works similarly, but returnsfloor(X / Y)
in the same format. IfY = 0
, returns zero (represented in the same format). Same gas cost as for multiplication above.At the address
0x0000....09
, add a precompile that expects input in the following format:This should return
B**E % M
, and the data should be returned in the same format as above. IfM = 0
, it returns zero. Gas costGMODEXPBASE + GARITHWORD * ceil(<total length of input data> / 32) + <length of M> * <length of M> * <length of E> / GQUADDIVISOR
.Examples
Call to 5:
The first 32 bytes represent length 13, so the next 13 bytes are interpreted as
X
and the remaining 7 bytes are interpreted asY
. Returns 820517673944445067756173565489 + 6634204312890625 = 820517673944451701960486456114, ie. the bytes:Call to 5:
Throws an exception, because it expects 13 bytes but only sees 8.
Call to 7:
The first 32 bytes represent length 0, so the next zero bytes are interpreted as
X
(ie.X = 0
), and te remaining bytes are interpreted asY
. Because anything times is zero is zero, this returns this:Call to 9:
The first 32 bytes represent that the next 32 bytes represent
B
; these bytes specifyB = 2
(note that there are leading zero bytes in this representation; this is ok). The 32 bytes after that represent that the next 32 bytes representE
; these bytes represent the prime number2**256 - 189
. Finally, the remaining bytes specifyM
, also equal to2**256 - 189
. By Fermat's little theorem, we know that2**p % p = 2
ifp
is prime, so the result is2
. Hence, this returns thirty three bytes:Rationale
This allows for efficient bigint arithmetic, facilitating RSA verification as well as other forms of cryptography that require integers larger than 256 bytes. The gas costs are chosen to roughly maintain computational cost parity with other operations, and they also have the property that a single MODEXP where the base, modulus and exponent are 4096-bit values takes up slightly less than the maximum gas limit (it takes ~0.31s to compute in python); note that RSA can be designed in such a way that the exponent for signature verification is 3, and in this case, gas costs drop to ~10000.
The text was updated successfully, but these errors were encountered: